Skip to content

Commit cece2a8

Browse files
committed
Improvement - Added smooth animation on category segregation
1 parent 084d51e commit cece2a8

File tree

3 files changed

+69
-18
lines changed

3 files changed

+69
-18
lines changed

src/components/vue-ui-radar.vue

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,23 @@ const svg = computed(() => {
118118
const emit = defineEmits(['selectLegend']);
119119
120120
const segregated = ref([]);
121+
const inSegregation = ref(null);
122+
const isAnimating = ref(false);
121123
122124
function segregate(index) {
125+
isAnimating.value = true;
123126
if(segregated.value.includes(index)) {
127+
inSegregation.value = index;
124128
segregated.value = segregated.value.filter(s => s !== index);
129+
setTimeout(() => {
130+
isAnimating.value = false;
131+
inSegregation.value = null;
132+
}, 500)
125133
}else {
126134
segregated.value.push(index);
135+
setTimeout(() => {
136+
isAnimating.value = false;
137+
}, 500)
127138
}
128139
emit('selectLegend', legendSet.value.filter((_, i) => !segregated.value.includes(i)).map(l => {
129140
return {
@@ -324,18 +335,6 @@ const legendConfig = computed(() => {
324335
}
325336
})
326337
327-
const table = computed(() => {
328-
const head = [{ name:"", color:""}, {name:radarConfig.value.translations.target, color:""}, ...legendSet.value];
329-
const body = props.dataset.series.map((s, i) => {
330-
return [ s.name, s.target, ...s.values.flatMap(v => {
331-
return [
332-
v ? v.toFixed(radarConfig.value.table.td.roundingValue) : '-', isNaN(v / s.target) ? '' : (v / s.target * 100).toFixed(radarConfig.value.table.td.roundingPercentage) + '%'
333-
]
334-
})]
335-
});
336-
return { head, body };
337-
});
338-
339338
const dataTable = computed(() => {
340339
const head = [
341340
{ name: radarConfig.value.translations.datapoint, color: "" },
@@ -636,13 +635,21 @@ defineExpose({
636635
637636
<!-- PLOTS -->
638637
<g v-for="(d, i) in datasetCopy">
639-
<g v-if="!segregated.includes(i)">
640-
<path
638+
<g>
639+
<polygon
641640
data-cy-radar-path
642-
:d="makePath(radar.map(r => r.plots[i]))"
641+
:points="makePath(radar.map(r => r.plots[i]), false, true)"
642+
:stroke="radarConfig.style.chart.backgroundColor"
643+
:stroke-width="radarConfig.style.chart.layout.dataPolygon.strokeWidth + 1"
644+
fill="none"
645+
/>
646+
<polygon
647+
data-cy-radar-path
648+
:points="makePath(radar.map(r => r.plots[i]), false, true)"
643649
:stroke="d.color"
644650
:stroke-width="radarConfig.style.chart.layout.dataPolygon.strokeWidth"
645651
:fill="radarConfig.style.chart.layout.dataPolygon.transparent ? 'transparent' : radarConfig.style.chart.layout.dataPolygon.useGradient ? `url(#radar_gradient_${uid}_${i})` : d.color + opacity[radarConfig.style.chart.layout.dataPolygon.opacity]"
652+
:class="{ 'animated-out': segregated.includes(i) && radarConfig.useCssAnimation, 'animated-in': isAnimating && inSegregation === i && radarConfig.useCssAnimation }"
646653
/>
647654
</g>
648655
</g>
@@ -655,6 +662,9 @@ defineExpose({
655662
:cy="p.y"
656663
:fill="segregated.includes(j) ? 'transparent' : datasetCopy[j].color"
657664
:r="selectedIndex !== null && selectedIndex === i ? radarConfig.style.chart.layout.plots.radius * 1.6 : radarConfig.style.chart.layout.plots.radius"
665+
:stroke="segregated.includes(j) ? 'transparent' : radarConfig.style.chart.backgroundColor"
666+
:stroke-width="0.5"
667+
:class="{ 'animated-out': segregated.includes(j) && radarConfig.useCssAnimation, 'animated-in': isAnimating && inSegregation === j && radarConfig.useCssAnimation }"
658668
/>
659669
</g>
660670
</g>
@@ -764,7 +774,7 @@ defineExpose({
764774
}
765775
766776
path, line, rect, circle {
767-
animation: xyAnimation 0.5s ease-in-out;
777+
animation: xyAnimation 0.5s ease-in-out !important;
768778
transform-origin: center;
769779
}
770780
@keyframes xyAnimation {
@@ -794,4 +804,38 @@ path, line, rect, circle {
794804
text-align:center;
795805
width:100%;
796806
}
807+
808+
polygon {
809+
transform-origin: center;
810+
}
811+
812+
.animated-in {
813+
animation: animatedIn 0.3s cubic-bezier(0, 1.01, 1, 1) forwards;
814+
}
815+
816+
@keyframes animatedIn {
817+
0% {
818+
transform: scale(0, 0);
819+
}
820+
80% {
821+
transform: scale(1.05, 1.05);
822+
}
823+
100% {
824+
transform: scale(1, 1);
825+
}
826+
}
827+
828+
.animated-out {
829+
animation: animatedOut 0.3s cubic-bezier(0, 1.01, 1, 1) forwards;
830+
}
831+
832+
@keyframes animatedOut {
833+
from {
834+
transform: scale(1, 1);
835+
}
836+
to {
837+
transform: scale(0, 0);
838+
}
839+
}
840+
797841
</style>

src/lib.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -717,12 +717,16 @@ export function sumByAttribute(arr, attr) {
717717
return [...arr].map(a => a[attr]).reduce((a, b) => a + b, 0)
718718
}
719719

720-
export function makePath(plots, closed = true) {
720+
export function makePath(plots, closed = true, bare = false) {
721721
let path = "";
722722
plots.forEach(plot => {
723723
path += `${plot.x},${plot.y} `
724724
})
725-
return `M${path}${closed ? 'Z' : ''}`;
725+
if(bare) {
726+
return path.trim();
727+
} else {
728+
return `M${path}${closed ? 'Z' : ''}`;
729+
}
726730
}
727731

728732
export function downloadCsv({ csvContent, title = "vue-data-ui" }) {

tests/lib.test.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,9 @@ describe('makePath', () => {
677677
test('creates a closed svg path from an array of plots', () => {
678678
expect(makePath(plots)).toBe('M1,2 2,3 3,4 4,5 5,6 Z')
679679
})
680+
test('creates svg points for a polygon', () => {
681+
expect(makePath(plots, false, true)).toBe('1,2 2,3 3,4 4,5 5,6')
682+
})
680683
})
681684

682685
describe('calculateNiceScale', () => {

0 commit comments

Comments
 (0)