Skip to content

Commit 44e6a0f

Browse files
committed
Improvement - VueUiDonutEvolution - Added zoom feature
1 parent 0ea860d commit 44e6a0f

File tree

3 files changed

+64
-17
lines changed

3 files changed

+64
-17
lines changed

src/components/vue-ui-donut-evolution.vue

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import UserOptions from "../atoms/UserOptions.vue";
2828
import DataTable from "../atoms/DataTable.vue";
2929
import Legend from "../atoms/Legend.vue";
3030
import Skeleton from "./vue-ui-skeleton.vue";
31+
import Slicer from "../atoms/Slicer.vue";
3132
3233
const props = defineProps({
3334
config: {
@@ -48,6 +49,19 @@ const isDataset = computed(() => {
4849
return !!props.dataset && props.dataset.length;
4950
})
5051
52+
const slicer = ref({
53+
start: 0,
54+
end: Math.max(...props.dataset.map(ds => ds.values.length))
55+
})
56+
57+
function refreshSlicer() {
58+
slicer.value = {
59+
start: 0,
60+
end: maxLength.value
61+
};
62+
slicerStep.value += 1;
63+
}
64+
5165
onMounted(() => {
5266
if(objectIsEmpty(props.dataset)) {
5367
error({
@@ -85,6 +99,7 @@ const isFixed = ref(false);
8599
const fixedDatapoint = ref(null);
86100
const donutEvolutionChart = ref(null);
87101
const step = ref(0);
102+
const slicerStep = ref(0);
88103
89104
const emit = defineEmits(['selectLegend'])
90105
@@ -155,21 +170,27 @@ const convertedDataset = computed(() => {
155170
});
156171
157172
const mutableDataset = computed(() => {
158-
return convertedDataset.value.filter(ds => !segregated.value.includes(ds.uid))
173+
return convertedDataset.value.filter(ds => !segregated.value.includes(ds.uid)).map(ds => {
174+
return {
175+
...ds,
176+
values: ds.values.filter((_v, k) => k >= slicer.value.start && k <= slicer.value.end)
177+
}
178+
})
159179
})
160180
161181
const maxLength = computed(() => {
162182
return Math.max(...mutableDataset.value.map(ds => ds.length))
163183
})
164184
165185
const slit = computed(() => {
166-
return svg.value.width / maxLength.value;
186+
return svg.value.width / (slicer.value.end - slicer.value.start);
167187
})
168188
169189
const drawableDataset = computed(() => {
170190
const arr = [];
171-
for(let i = 0; i < maxLength.value; i += 1) {
172-
const values = mutableDataset.value.map(ds => ds.values[i] ?? null);
191+
for(let i = 0; i < (slicer.value.end - slicer.value.start); i += 1) {
192+
const values = mutableDataset.value
193+
.map(ds => ds.values[i] ?? null)
173194
const allValuesAreNull = values.filter(v => [undefined, null].includes(v)).length === values.length;
174195
const subtotal = values.reduce((a, b) => a + b, 0);
175196
const percentages = values.map(v => v / subtotal);
@@ -417,7 +438,7 @@ const table = computed(() => {
417438
}
418439
419440
const colNames = [
420-
donutEvolutionConfig.value.table.columnNames.period
441+
donutEvolutionConfig.value.table.columnNames.period
421442
].concat(convertedDataset.value.filter(ds => !segregated.value.includes(ds.uid)).map(ds => ds.name)).concat(donutEvolutionConfig.value.table.columnNames.total)
422443
423444
return { head, body, config, colNames };
@@ -555,7 +576,7 @@ defineExpose({
555576
556577
<!-- X LABELS -->
557578
<g v-if="donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.show" :class="{'donut-opacity': true, 'donut-behind': isFixed}">
558-
<g v-for="(_, i) in maxLength">
579+
<g v-for="(_, i) in (slicer.end - slicer.start)">
559580
<text
560581
v-if="(donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.showOnlyFirstAndLast && (i === 0 || i === maxLength - 1)) || !donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.showOnlyFirstAndLast"
561582
:text-anchor="donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.rotation > 0 ? 'start' : donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.rotation < 0 ? 'end' : 'middle'"
@@ -564,7 +585,7 @@ defineExpose({
564585
:transform="`translate(${padding.left + (slit * i) + (slit / 2)}, ${donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.offsetY + svg.absoluteHeight - padding.bottom + donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.fontSize * 2}), rotate(${donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.rotation})`"
565586
566587
>
567-
{{ donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.values[i] ?? '' }}
588+
{{ donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.values[Number(i) + Number(slicer.start)] ?? '' }}
568589
</text>
569590
</g>
570591
</g>
@@ -655,15 +676,6 @@ defineExpose({
655676
/>
656677
</g>
657678
</g>
658-
<g v-if="datapoint.subtotal !== null">
659-
<circle
660-
v-if="datapoint.subtotal"
661-
:cx="datapoint.x"
662-
:cy="datapoint.y"
663-
:r="hoveredIndex === datapoint.index ? svg.width / 30 : slit / 10"
664-
:fill="donutEvolutionConfig.style.chart.backgroundColor"
665-
/>
666-
</g>
667679
</g>
668680
669681
<!-- DATALABELS -->
@@ -819,7 +831,7 @@ defineExpose({
819831
:font-size="donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.fontSize * 1.6"
820832
:fill="donutEvolutionConfig.style.chart.layout.dataLabels.color"
821833
>
822-
{{ donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.values[fixedDatapoint.index] }}
834+
{{ donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.values[Number(fixedDatapoint.index) + Number(slicer.start)] }}
823835
</text>
824836
</g>
825837
<slot name="svg" :svg="svg"/>
@@ -843,6 +855,29 @@ defineExpose({
843855
}"
844856
/>
845857
858+
<Slicer
859+
v-if="maxLength > 1 && donutEvolutionConfig.style.chart.zoom.show"
860+
:key="`slicer_${slicerStep}`"
861+
:background="donutEvolutionConfig.style.chart.backgroundColor"
862+
:fontSize="donutEvolutionConfig.style.chart.zoom.fontSize"
863+
:useResetSlot="donutEvolutionConfig.style.chart.zoom.useResetSlot"
864+
:labelLeft="donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.values[Number(slicer.start)] || ''"
865+
:labelRight="donutEvolutionConfig.style.chart.layout.grid.xAxis.dataLabels.values[Number(slicer.end)-1] || ''"
866+
:textColor="donutEvolutionConfig.style.chart.color"
867+
:inputColor="donutEvolutionConfig.style.chart.zoom.color"
868+
:max="maxLength"
869+
:min="0"
870+
:valueStart="slicer.start"
871+
:valueEnd="slicer.end"
872+
v-model:start="slicer.start"
873+
v-model:end="slicer.end"
874+
@reset="refreshSlicer"
875+
>
876+
<template #reset-action="{ reset }">
877+
<slot name="reset-action" v-bind="{ reset }"/>
878+
</template>
879+
</Slicer>
880+
846881
<Legend
847882
v-if="donutEvolutionConfig.style.chart.legend.show"
848883
:legendSet="legendSet"

src/default_configs.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2972,6 +2972,12 @@
29722972
"chart": {
29732973
"backgroundColor":"#FFFFFF",
29742974
"color":"#2D353C",
2975+
"zoom": {
2976+
"show": true,
2977+
"color": "#CCCCCC",
2978+
"fontSize": 14,
2979+
"useResetSlot": false
2980+
},
29752981
"layout": {
29762982
"height": 316,
29772983
"width": 500,

types/vue-data-ui.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,12 @@ declare module 'vue-data-ui' {
805805
chart?: {
806806
backgroundColor?: string;
807807
color?: string;
808+
zoom?: {
809+
show?: boolean;
810+
color?: string;
811+
fontSize?: number;
812+
useResetSlot?: boolean;
813+
};
808814
layout?: {
809815
height?: number;
810816
width?: number;

0 commit comments

Comments
 (0)