[READ-ONLY] Mirror of https://github.com/graphieros/vue-data-ui. An open source user-empowering data visualization Vue 3 components library for eloquent data storytelling vue-data-ui.graphieros.com/
charts components-library dashboard data-storytelling data-visualization donut gauge heatmap quadrant radar rating-stars scatter screenshot skeleton-loader sparkline table vue-data-ui vue3 vuejs vuejs3
3

Configure Feed

Select the types of activity you want to include in your feed.

fix(VueUiXy): disable shape transitions when zoom range is resized

graphieros (Jun 15, 2026, 9:59 PM +0200) 75730923 f7f4a9f0

+103 -40
+1 -1
manual-testing/package-lock.json
··· 28 28 } 29 29 }, 30 30 "..": { 31 - "version": "3.21.3", 31 + "version": "3.21.4", 32 32 "dev": true, 33 33 "license": "MIT", 34 34 "devDependencies": {
+12
src/atoms/Shape.vue
··· 24 24 transition: { 25 25 type: String, 26 26 }, 27 + still: { 28 + type: Boolean, 29 + }, 27 30 }); 28 31 29 32 const emit = defineEmits(['mouseover', 'mouseout', 'click']); ··· 87 90 <g data-cy="atom-shape"> 88 91 <circle 89 92 class="vdui-shape-circle" 93 + :class="{ 'vdui-shape-no-transition': still }" 90 94 v-if="config && config.points === 1" 91 95 :cx="plot.x" 92 96 :cy="plot.y" ··· 101 105 /> 102 106 <path 103 107 class="vdui-shape-polygon" 108 + :class="{ 'vdui-shape-no-transition': still }" 104 109 v-if="config && config.points >= limit" 105 110 :d="d" 106 111 :fill="color" ··· 113 118 /> 114 119 <polygon 115 120 class="vdui-shape-star" 121 + :class="{ 'vdui-shape-no-transition': still }" 116 122 v-if="starPoints" 117 123 :points="starPoints" 118 124 :fill="color" ··· 125 131 /> 126 132 </g> 127 133 </template> 134 + 135 + <style scoped> 136 + .vdui-shape-no-transition { 137 + transition: none !important; 138 + } 139 + </style>
+90 -39
src/components/vue-ui-xy.vue
··· 1579 1579 return Math.max(1, len); 1580 1580 }); 1581 1581 1582 - const showRangeSizeShapes = ref(true); 1583 - let showRangeSizeShapesTimeout = null; 1584 - 1585 - watch( 1586 - maxSeries, 1587 - (newValue, oldValue) => { 1588 - if (oldValue === undefined || newValue === oldValue) return; 1589 - 1590 - showRangeSizeShapes.value = false; 1591 - 1592 - if (showRangeSizeShapesTimeout) 1593 - clearTimeout(showRangeSizeShapesTimeout); 1594 - 1595 - const duration = Math.max( 1596 - FINAL_CONFIG.value.line.transitionDurationMs || 0, 1597 - FINAL_CONFIG.value.plot.transitionDurationMs || 0, 1598 - ); 1599 - 1600 - showRangeSizeShapesTimeout = window.setTimeout(() => { 1601 - showRangeSizeShapes.value = true; 1602 - }, duration); 1603 - }, 1604 - { flush: 'sync' }, 1605 - ); 1606 - 1607 1582 function selectMinimapIndex(payload) { 1608 1583 if (isContinuousScale.value) return; 1609 1584 selectedMinimapIndex.value = payload; ··· 1757 1732 1758 1733 const suppressChild = ref(false); 1759 1734 1735 + const disableShapeTransitionForRangeResize = ref(false); 1736 + let queuedSlicerFrame = null; 1737 + let restoreShapeTransitionFrame = null; 1738 + let queuedSlicerUpdate = {}; 1739 + 1740 + function getSlicerRangeSize(source = slicer.value) { 1741 + return Number(source.end) - Number(source.start); 1742 + } 1743 + 1744 + function clearQueuedSlicerFrames() { 1745 + if (queuedSlicerFrame) { 1746 + cancelAnimationFrame(queuedSlicerFrame); 1747 + queuedSlicerFrame = null; 1748 + } 1749 + 1750 + if (restoreShapeTransitionFrame) { 1751 + cancelAnimationFrame(restoreShapeTransitionFrame); 1752 + restoreShapeTransitionFrame = null; 1753 + } 1754 + } 1755 + 1756 + function queueSlicerUpdate(update) { 1757 + queuedSlicerUpdate = { 1758 + ...queuedSlicerUpdate, 1759 + ...update, 1760 + }; 1761 + 1762 + if (queuedSlicerFrame) { 1763 + cancelAnimationFrame(queuedSlicerFrame); 1764 + } 1765 + 1766 + queuedSlicerFrame = requestAnimationFrame(() => { 1767 + const previousRangeSize = getSlicerRangeSize(); 1768 + 1769 + const nextSlicer = { 1770 + ...slicer.value, 1771 + ...queuedSlicerUpdate, 1772 + }; 1773 + 1774 + const nextRangeSize = getSlicerRangeSize(nextSlicer); 1775 + 1776 + disableShapeTransitionForRangeResize.value = 1777 + nextRangeSize !== previousRangeSize; 1778 + 1779 + slicer.value = nextSlicer; 1780 + slicerPrecog.value = { ...nextSlicer }; 1781 + 1782 + queuedSlicerUpdate = {}; 1783 + queuedSlicerFrame = null; 1784 + 1785 + normalizeSlicerWindow(); 1786 + 1787 + if (restoreShapeTransitionFrame) { 1788 + cancelAnimationFrame(restoreShapeTransitionFrame); 1789 + } 1790 + 1791 + restoreShapeTransitionFrame = requestAnimationFrame(() => { 1792 + disableShapeTransitionForRangeResize.value = false; 1793 + restoreShapeTransitionFrame = null; 1794 + }); 1795 + }); 1796 + } 1797 + 1760 1798 function onSlicerStart(v) { 1761 1799 if (isSettingUp.value || suppressChild.value) return; 1762 1800 ··· 1773 1811 if (!Number.isFinite(nextStart)) return; 1774 1812 if (nextStart === slicer.value.start) return; 1775 1813 1776 - slicer.value.start = nextStart; 1777 - slicerPrecog.value.start = nextStart; 1778 - normalizeSlicerWindow(); 1814 + queueSlicerUpdate({ start: nextStart }); 1779 1815 } 1780 1816 1781 1817 function onSlicerEnd(v) { ··· 1802 1838 1803 1839 if (end === slicer.value.end) return; 1804 1840 1805 - slicer.value.end = end; 1806 - slicerPrecog.value.end = end; 1807 - normalizeSlicerWindow(); 1841 + queueSlicerUpdate({ end }); 1808 1842 1809 1843 return; 1810 1844 } ··· 1818 1852 1819 1853 if (end === slicer.value.end) return; 1820 1854 1821 - slicer.value.end = end; 1822 - slicerPrecog.value.end = end; 1823 - normalizeSlicerWindow(); 1855 + queueSlicerUpdate({ end }); 1824 1856 } 1825 1857 1826 1858 async function refreshSlicer() { 1859 + const previousRangeSize = getSlicerRangeSize(); 1860 + disableShapeTransitionForRangeResize.value = true; 1827 1861 await setupSlicer(); 1862 + const nextRangeSize = getSlicerRangeSize(); 1863 + if (nextRangeSize === previousRangeSize) { 1864 + disableShapeTransitionForRangeResize.value = false; 1865 + } else { 1866 + await nextTick(); 1867 + if (restoreShapeTransitionFrame) { 1868 + cancelAnimationFrame(restoreShapeTransitionFrame); 1869 + } 1870 + restoreShapeTransitionFrame = requestAnimationFrame(() => { 1871 + disableShapeTransitionForRangeResize.value = false; 1872 + restoreShapeTransitionFrame = null; 1873 + }); 1874 + } 1828 1875 emit('zoomReset'); 1829 1876 } 1830 1877 ··· 4893 4940 resizeObserver.value.disconnect(); 4894 4941 resizeObserver.value = null; 4895 4942 } 4896 - if (showRangeSizeShapesTimeout) { 4897 - clearTimeout(showRangeSizeShapesTimeout); 4898 - } 4943 + clearQueuedSlicerFrames(); 4899 4944 }); 4900 4945 4901 4946 useTimeLabelCollision({ ··· 7200 7245 > 7201 7246 <Shape 7202 7247 :data-cy="`xy-plot-${i}-${j}`" 7203 - v-show="showRangeSizeShapes" 7204 7248 v-if="plot && canShowValue(plot.value)" 7205 7249 :shape=" 7206 7250 [ ··· 7243 7287 " 7244 7288 :transition=" 7245 7289 loading || 7290 + disableShapeTransitionForRangeResize || 7246 7291 !FINAL_CONFIG.plot.showTransition || 7247 7292 isSelectedDatapoint(serie, plot, j) 7248 7293 ? undefined 7249 7294 : `all ${FINAL_CONFIG.plot.transitionDurationMs}ms ease-in-out` 7295 + " 7296 + :still=" 7297 + disableShapeTransitionForRangeResize 7250 7298 " 7251 7299 /> 7252 7300 ··· 7613 7661 > 7614 7662 <Shape 7615 7663 data-cy="datapoint-line-plot" 7616 - v-show="showRangeSizeShapes" 7617 7664 v-if=" 7618 7665 (!optimize.linePlot && 7619 7666 plot && ··· 7670 7717 " 7671 7718 :transition=" 7672 7719 loading || 7720 + disableShapeTransitionForRangeResize || 7673 7721 !FINAL_CONFIG.line.showTransition || 7674 7722 isSelectedDatapoint(serie, plot, j) 7675 7723 ? undefined 7676 7724 : `all ${FINAL_CONFIG.line.transitionDurationMs}ms ease-in-out` 7725 + " 7726 + :still=" 7727 + disableShapeTransitionForRangeResize 7677 7728 " 7678 7729 /> 7679 7730