Skip to content

Commit f00d701

Browse files
committed
Fix - VueUiXy - Fix weird random issue in Firefox when using a boatload of chart instances
1 parent be4e54d commit f00d701

File tree

2 files changed

+116
-78
lines changed

2 files changed

+116
-78
lines changed

src/atoms/SlicerPreview.vue

Lines changed: 65 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -184,23 +184,28 @@ const useMini = computed(() => hasMinimap.value && props.minimapCompact);
184184
185185
const wrapperWidth = ref(0);
186186
187+
const emitFutureStart = throttle((v) => emit('futureStart', v), 0);
188+
const emitFutureEnd = throttle((v) => emit('futureEnd', v), 0);
189+
187190
const start = computed({
188-
get() { return startValue.value },
191+
get: () => startValue.value,
189192
set(raw) {
190193
const v = Math.min(raw, endValue.value - 1);
194+
if (v === startValue.value) return;
191195
startValue.value = v;
192196
if (rangeStart.value) rangeStart.value.value = String(v);
193-
emit('futureStart', v);
197+
if (isRanging.value) emitFutureStart(v);
194198
}
195199
});
196200
197201
const end = computed({
198-
get() { return endValue.value },
202+
get: () => endValue.value,
199203
set(raw) {
200204
const v = Math.max(raw, startValue.value + 1);
205+
if (v === endValue.value) return;
201206
endValue.value = v;
202207
if (rangeEnd.value) rangeEnd.value.value = String(v);
203-
emit('futureEnd', v);
208+
if (isRanging.value) emitFutureEnd(v);
204209
}
205210
});
206211
@@ -342,12 +347,16 @@ const resizeObserver = ref(null);
342347
onMounted(() => {
343348
if (hasMinimap.value) {
344349
const handleResize = throttle(() => {
345-
const { width, height } = useResponsive({
346-
chart: minimapWrapper.value,
347-
});
348-
svgMinimap.value.width = width;
349-
svgMinimap.value.height = height - 47;
350-
});
350+
if (!minimapWrapper.value) return;
351+
const { width, height } = useResponsive({ chart: minimapWrapper.value });
352+
const W = Math.max(0, Math.round(width));
353+
const H = Math.max(0, Math.round(height - 47));
354+
355+
if (W !== svgMinimap.value.width || H !== svgMinimap.value.height) {
356+
svgMinimap.value.width = W;
357+
svgMinimap.value.height = H;
358+
}
359+
}, 50);
351360
352361
resizeObserver.value = new ResizeObserver(handleResize);
353362
resizeObserver.value.observe(minimapWrapper.value);
@@ -705,6 +714,7 @@ let activeMoveHandler = null;
705714
let activeEndHandler = null;
706715
707716
const startDragging = (event) => {
717+
isRanging.value = true;
708718
showTooltip.value = true;
709719
if (!props.enableSelectionDrag) return;
710720
@@ -803,16 +813,22 @@ const showTooltip = ref(false);
803813
804814
function setTooltipLeft() {
805815
if (tooltipLeft.value) {
806-
tooltipLeftWidth.value = tooltipLeft.value.getBoundingClientRect().width;
816+
const w = Math.round(tooltipLeft.value.getBoundingClientRect().width);
817+
if (w !== tooltipLeftWidth.value) tooltipLeftWidth.value = w;
807818
}
808819
}
809-
810820
function setTooltipRight() {
811821
if (tooltipRight.value) {
812-
tooltipRightWidth.value = tooltipRight.value.getBoundingClientRect().width;
822+
const w = Math.round(tooltipRight.value.getBoundingClientRect().width);
823+
if (w !== tooltipRightWidth.value) tooltipRightWidth.value = w;
813824
}
814825
}
815826
827+
onUpdated(() => {
828+
setTooltipLeft();
829+
setTooltipRight();
830+
});
831+
816832
const leftLabelZIndex = ref(0);
817833
818834
function setLeftLabelZIndex(handle) {
@@ -861,47 +877,54 @@ watch(() => props.labelRight, () => {
861877
nextTick(setTooltipRight);
862878
}, { deep: true });
863879
864-
const useCustomFormat = ref(false);
865-
866880
const labels = computed(() => {
867-
let left = { text: '' }, right = { text: '' };
868-
useCustomFormat.value = false;
881+
let leftText = '';
882+
let rightText = '';
883+
884+
let useCustomFormat = false;
869885
870886
if (isFunction(props.customFormat)) {
871887
try {
872-
const customLeft = props.customFormat({
873-
absoluteIndex: startValue.value,
874-
seriesIndex: startValue.value,
875-
datapoint: props.selectedSeries
876-
});
877-
const customRight = props.customFormat({
878-
absoluteIndex: endValue.value - 1,
879-
seriesIndex: - 1,
880-
datapoint: props.selectedSeries
881-
});
882-
if (typeof customLeft === 'string' && typeof customRight === 'string') {
883-
left.text = customLeft;
884-
right.text = customRight;
885-
useCustomFormat.value = true;
886-
}
887-
} catch (err) {
888-
console.warn('Custom format cannot be applied on zoom labels.');
889-
useCustomFormat.value = false;
888+
const customLeft = props.customFormat({
889+
absoluteIndex: startValue.value,
890+
seriesIndex: startValue.value,
891+
datapoint: props.selectedSeries
892+
});
893+
894+
const customRight = props.customFormat({
895+
absoluteIndex: endValue.value - 1,
896+
seriesIndex: -1,
897+
datapoint: props.selectedSeries
898+
});
899+
900+
if (typeof customLeft === 'string' && typeof customRight === 'string') {
901+
leftText = customLeft;
902+
rightText = customRight;
903+
useCustomFormat = true;
904+
}
905+
906+
} catch (_) {
907+
useCustomFormat = false;
890908
}
891909
}
892910
893-
if (!useCustomFormat.value) {
894-
left = props.usePreciseLabels ? props.preciseLabels.find(t => t.absoluteIndex === startValue.value) : props.timeLabels.find(t => t.absoluteIndex === startValue.value);
911+
if (!useCustomFormat) {
912+
const left = props.usePreciseLabels
913+
? props.preciseLabels.find(t => t.absoluteIndex === startValue.value)
914+
: props.timeLabels.find(t => t.absoluteIndex === startValue.value);
915+
916+
const right = props.usePreciseLabels
917+
? props.preciseLabels.find(t => t.absoluteIndex === endValue.value - 1)
918+
: props.timeLabels.find(t => t.absoluteIndex === endValue.value - 1);
895919
896-
right = props.usePreciseLabels ? props.preciseLabels.find(t => t.absoluteIndex === endValue.value - 1) : props.timeLabels.find(t => t.absoluteIndex === endValue.value - 1);
920+
leftText = left ? left.text : '';
921+
rightText = right ? right.text : '';
897922
}
898923
899-
return {
900-
left: left ? left.text : '',
901-
right: right ? right.text : ''
902-
};
924+
return { left: leftText, right: rightText };
903925
});
904926
927+
905928
onBeforeUnmount(() => {
906929
if (resizeObserver.value) resizeObserver.value.disconnect();
907930

src/components/vue-ui-xy.vue

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,12 @@ function normalizeSlicerWindow() {
477477
478478
slicer.value = { start: s, end: e }
479479
slicerPrecog.value.start = s
480-
slicerPrecog.value.end = e
480+
slicerPrecog.value.end = e
481+
482+
if(chartSlicer.value) {
483+
chartSlicer.value.setStartValue(s);
484+
chartSlicer.value.setEndValue(e)
485+
}
481486
}
482487
483488
const precogRect = computed(() => {
@@ -1001,39 +1006,49 @@ function validSlicerEnd(v) {
10011006
return v;
10021007
}
10031008
1004-
async function setupSlicer() {
1005-
await nextTick();
1006-
await nextTick();
1007-
1008-
const { startIndex, endIndex } = FINAL_CONFIG.value.chart.zoom;
1009-
const comp = chartSlicer.value;
1009+
const isSettingUp = ref(false);
1010+
const slicerReady = ref(false);
1011+
1012+
function setupSlicer() {
1013+
if (isSettingUp.value) return;
1014+
isSettingUp.value = true;
1015+
try {
1016+
const { startIndex, endIndex } = FINAL_CONFIG.value.chart.zoom;
1017+
const max = Math.max(...FINAL_DATASET.value.map(dp => lttb(dp.series).length));
1018+
1019+
const start = startIndex != null ? startIndex : 0;
1020+
const end = endIndex != null ? Math.min(validSlicerEnd(endIndex + 1), max) : max;
1021+
1022+
suppressChild.value = true;
1023+
slicer.value.start = start;
1024+
slicer.value.end = end;
1025+
slicerPrecog.value.start = start;
1026+
slicerPrecog.value.end = end;
1027+
normalizeSlicerWindow();
1028+
slicerReady.value = true;
1029+
} finally {
1030+
queueMicrotask(() => { suppressChild.value = false; });
1031+
isSettingUp.value = false;
1032+
}
1033+
}
10101034
1011-
const max = Math.max(...FINAL_DATASET.value.map(dp => lttb(dp.series).length));
1035+
const suppressChild = ref(false);
10121036
1013-
slicer.value = { start: 0, end: max };
1037+
function onSlicerStart(v) {
1038+
if (isSettingUp.value || suppressChild.value) return;
1039+
if (v === slicer.value.start) return;
1040+
slicer.value.start = v;
1041+
slicerPrecog.value.start = v;
1042+
normalizeSlicerWindow();
1043+
}
10141044
1015-
if ((startIndex != null || endIndex != null) && comp) {
1016-
if (startIndex != null) {
1017-
slicer.value.start = startIndex;
1018-
comp.setStartValue(startIndex);
1019-
} else {
1020-
slicer.value.start = 0;
1021-
comp.setStartValue(0);
1022-
}
1023-
if (endIndex != null) {
1024-
slicer.value.end = endIndex + 1
1025-
comp.setEndValue(validSlicerEnd(endIndex + 1));
1026-
} else {
1027-
slicer.value.end = max;
1028-
comp.setEndValue(max);
1029-
}
1030-
} else {
1031-
slicer.value = { start: 0, end: max };
1032-
slicerStep.value += 1;
1033-
}
1034-
slicerPrecog.value.start = slicer.value.start;
1035-
slicerPrecog.value.end = slicer.value.end;
1036-
normalizeSlicerWindow()
1045+
function onSlicerEnd(v) {
1046+
if (isSettingUp.value || suppressChild.value) return;
1047+
const end = validSlicerEnd(v);
1048+
if (end === slicer.value.end) return;
1049+
slicer.value.end = end;
1050+
slicerPrecog.value.end = end;
1051+
normalizeSlicerWindow();
10371052
}
10381053
10391054
async function refreshSlicer() {
@@ -4153,14 +4168,15 @@ defineExpose({
41534168
<template v-if="FINAL_CONFIG.chart.zoom.preview.enable">
41544169
<SlicerPreview
41554170
ref="chartSlicer"
4156-
v-if="FINAL_CONFIG.chart.zoom.show && maxX > 6 && isDataset"
4157-
:key="`slicer_${slicerStep}`"
4171+
v-if="FINAL_CONFIG.chart.zoom.show && maxX > 6 && isDataset && slicerReady"
41584172
:max="maxX"
41594173
:min="0"
41604174
:valueStart="slicer.start"
41614175
:valueEnd="slicer.end"
4162-
v-model:start="slicer.start"
4163-
v-model:end="slicer.end"
4176+
:start="slicer.start"
4177+
:end="slicer.end"
4178+
@update:start="onSlicerStart"
4179+
@update:end="onSlicerEnd"
41644180
:selectedSeries="selectedSeries"
41654181
:customFormat="FINAL_CONFIG.chart.zoom.customFormat"
41664182
:background="FINAL_CONFIG.chart.zoom.color"
@@ -4204,7 +4220,6 @@ defineExpose({
42044220
<template v-else>
42054221
<Slicer ref="chartSlicer"
42064222
v-if="FINAL_CONFIG.chart.zoom.show && maxX > 6 && isDataset"
4207-
:key="`slicer_${slicerStep}`"
42084223
:max="maxX"
42094224
:min="0"
42104225
:valueStart="slicer.start"

0 commit comments

Comments
 (0)