This commit is contained in:
syuilo 2023-01-03 14:08:52 +09:00
parent c93f091ba8
commit fb05e86db7
5 changed files with 103 additions and 16 deletions

View file

@ -1,6 +1,7 @@
<template>
<div class="cbbedffa">
<canvas ref="chartEl"></canvas>
<MkChartLegend ref="legendEl" style="margin-top: 8px;"/>
<div v-if="fetching" class="fetching">
<MkLoading/>
</div>
@ -24,6 +25,8 @@ import { chartVLine } from '@/scripts/chart-vline';
import { alpha } from '@/scripts/color';
import date from '@/filters/date';
import { initChart } from '@/scripts/init-chart';
import { chartLegend } from '@/scripts/chart-legend';
import MkChartLegend from '@/components/MkChartLegend.vue';
initChart();
@ -67,6 +70,8 @@ const props = defineProps({
},
});
let legendEl = $shallowRef<InstanceType<typeof MkChartLegend>>();
const sum = (...arr) => arr.reduce((r, a) => r.map((b, i) => a[i] + b));
const negate = arr => arr.map(x => -x);
@ -220,11 +225,7 @@ const render = () => {
},
plugins: {
legend: {
display: props.detailed,
position: 'bottom',
labels: {
boxWidth: 16,
},
display: false,
},
tooltip: {
enabled: false,
@ -264,7 +265,7 @@ const render = () => {
gradient,
},
},
plugins: [chartVLine(vLineColor)],
plugins: [chartVLine(vLineColor), ...(props.detailed ? [chartLegend(legendEl)] : [])],
});
};

View file

@ -0,0 +1,75 @@
<template>
<div :class="$style.root">
<button v-for="item in items" class="_button item" :class="{ disabled: item.hidden }" @click="onClick(item)">
<span class="box" :style="{ background: chart.config.type === 'line' ? item.strokeStyle?.toString() : item.fillStyle?.toString() }"></span>
{{ item.text }}
</button>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, shallowRef, watch, PropType, onUnmounted } from 'vue';
import { Chart, LegendItem } from 'chart.js';
const props = defineProps({
});
let chart = $shallowRef<Chart>();
let items = $shallowRef<LegendItem[]>([]);
function update(_chart: Chart, _items: LegendItem[]) {
chart = _chart,
items = _items;
}
function onClick(item: LegendItem) {
if (chart == null) return;
const { type } = chart.config;
if (type === 'pie' || type === 'doughnut') {
// Pie and doughnut charts only have a single dataset and visibility is per item
chart.toggleDataVisibility(item.index);
} else {
chart.setDatasetVisibility(item.datasetIndex, !chart.isDatasetVisible(item.datasetIndex));
}
chart.update();
}
defineExpose({
update,
});
</script>
<style lang="scss" module>
.root {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
&:global {
> .item {
font-size: 85%;
padding: 4px 12px 4px 8px;
border: solid 1px var(--divider);
border-radius: 999px;
&:hover {
border-color: var(--inputBorderHover);
}
&.disabled {
text-decoration: line-through;
opacity: 0.6;
}
> .box {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 100%;
vertical-align: -10%;
}
}
}
}
</style>

View file

@ -3,6 +3,7 @@
<MkLoading v-if="fetching"/>
<div v-show="!fetching" :class="$style.root" class="_panel">
<canvas ref="chartEl"></canvas>
<MkChartLegend ref="legendEl" style="margin-top: 8px;"/>
</div>
</div>
</template>
@ -20,6 +21,8 @@ import { useChartTooltip } from '@/scripts/use-chart-tooltip';
import { chartVLine } from '@/scripts/chart-vline';
import { alpha } from '@/scripts/color';
import { initChart } from '@/scripts/init-chart';
import { chartLegend } from '@/scripts/chart-legend';
import MkChartLegend from '@/components/MkChartLegend.vue';
initChart();
@ -28,6 +31,7 @@ const props = defineProps<{
}>();
const chartEl = $shallowRef<HTMLCanvasElement>(null);
let legendEl = $shallowRef<InstanceType<typeof MkChartLegend>>();
const now = new Date();
let chartInstance: Chart = null;
const chartLimit = 30;
@ -153,14 +157,7 @@ async function renderChart() {
},
},
legend: {
display: true,
position: 'bottom',
padding: {
left: 0,
right: 0,
top: 8,
bottom: 0,
},
display: false,
},
tooltip: {
enabled: false,
@ -173,7 +170,7 @@ async function renderChart() {
gradient,
},
},
plugins: [chartVLine(vLineColor)],
plugins: [chartVLine(vLineColor), chartLegend(legendEl)],
});
fetching = false;

View file

@ -0,0 +1,12 @@
import { Plugin } from 'chart.js';
import MkChartLegend from '@/components/MkChartLegend.vue';
export const chartLegend = (legend: InstanceType<typeof MkChartLegend>) => ({
id: 'htmlLegend',
afterUpdate(chart, args, options) {
// Reuse the built-in legendItems generator
const items = chart.options.plugins.legend.labels.generateLabels(chart);
legend.update(chart, items);
},
}) as Plugin;

View file

@ -1,3 +1,5 @@
import { Plugin } from 'chart.js';
export const chartVLine = (vLineColor: string) => ({
id: 'vLine',
beforeDraw(chart, args, options) {
@ -18,4 +20,4 @@ export const chartVLine = (vLineColor: string) => ({
ctx.restore();
}
},
});
}) as Plugin;