Skip to content

Commit ee69436

Browse files
committed
Fix - VueUiXy - Sync zoom with selection rect in preview mode when LTTB is active
1 parent d2c4541 commit ee69436

File tree

2 files changed

+47
-21
lines changed

2 files changed

+47
-21
lines changed

src/atoms/SlicerPreview.vue

Lines changed: 46 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -280,52 +280,80 @@ onBeforeUnmount(() => {
280280
if (resizeObserver.value) resizeObserver.value.disconnect();
281281
});
282282
283+
const absLen = computed(() => Math.max(1, props.max - props.min));
284+
const miniLen = computed(() => Math.max(1, props.minimap.length));
285+
const scaleAbsToMini = computed(() => miniLen.value / absLen.value);
286+
287+
function absToMiniStart(i) {
288+
const v = Math.floor((i - props.min) * scaleAbsToMini.value);
289+
return Math.min(Math.max(0, v), miniLen.value);
290+
}
291+
292+
function absToMiniEnd(i) {
293+
const v = Math.ceil((i - props.min) * scaleAbsToMini.value);
294+
return Math.min(Math.max(0, v), miniLen.value);
295+
}
296+
297+
const startMini = computed(() => absToMiniStart(startValue.value));
298+
const endMini = computed(() => absToMiniEnd(endValue.value));
299+
283300
const unitWidthX = computed(() => {
284301
if(!props.minimap.length) return 0;
285302
return svgMinimap.value.width / props.minimap.length;
286303
});
287304
288305
const minimapLine = computed(() => {
289-
if(!props.minimap.length) return [];
306+
if (!props.minimap.length) return [];
290307
const max = Math.max(...props.minimap);
291308
const min = Math.min(...props.minimap) - 10;
292309
const diff = max - (min > 0 ? 0 : min);
293-
const points = props.minimap.map((dp, i) => {
294-
const normalizedVal = dp - min;
295-
return {
296-
x: svgMinimap.value.width / (props.minimap.length) * (i) + (unitWidthX.value / 2),
297-
y: svgMinimap.value.height - (normalizedVal / diff * (svgMinimap.value.height * 0.9))
298-
};
299-
});
310+
311+
const points = props.minimap.map((dp, i) => ({
312+
x: (svgMinimap.value.width / props.minimap.length) * i + (unitWidthX.value / 2),
313+
y: svgMinimap.value.height - ((dp - min) / diff) * (svgMinimap.value.height * 0.9),
314+
}));
315+
316+
const s = startMini.value;
317+
const e = Math.max(s + 1, endMini.value);
318+
300319
const fullSet = props.smoothMinimap ? createSmoothPath(points) : createStraightPath(points);
301-
const sliced = [...points].slice(props.valueStart, props.valueEnd);
320+
const sliced = points.slice(s, e);
302321
const selectionSet = props.smoothMinimap ? createSmoothPath(sliced) : createStraightPath(sliced);
322+
303323
return {
304324
fullSet,
305325
selectionSet,
306326
sliced,
307-
firstPlot: points[props.valueStart],
308-
lastPlot: points[props.valueEnd - 1]
327+
firstPlot: points[s],
328+
lastPlot : points[Math.max(0, e - 1)],
309329
};
310330
});
311331
312332
const selectionRectCoordinates = computed(() => {
333+
const s = startMini.value;
334+
const e = Math.max(s + 1, endMini.value);
313335
return {
314-
x: unitWidthX.value * startValue.value + (unitWidthX.value / 2),
315-
width: svgMinimap.value.width * ((endValue.value - startValue.value) / props.max) - unitWidthX.value
336+
x: unitWidthX.value * s + (unitWidthX.value / 2),
337+
width: unitWidthX.value * (e - s) - unitWidthX.value,
316338
};
317339
});
318340
319341
const selectedTrap = ref(props.minimapSelectedIndex);
320342
321343
watch(() => props.minimapSelectedIndex, (v) => {
322-
selectedTrap.value = v + props.valueStart;
344+
if ([null, undefined].includes(v)) {
345+
selectedTrap.value = null;
346+
return;
347+
}
348+
selectedTrap.value = absToMiniStart(props.valueStart) + v;
323349
}, { immediate: true });
324350
325351
function trapMouse(trap) {
326352
selectedTrap.value = trap;
327-
if (trap >= props.valueStart && trap < props.valueEnd) {
328-
emit('trapMouse', trap - props.valueStart);
353+
const s = startMini.value;
354+
const e = endMini.value;
355+
if (trap >= s && trap < e) {
356+
emit('trapMouse', trap - s);
329357
}
330358
}
331359
@@ -715,7 +743,7 @@ defineExpose({
715743
stroke-linecap="round"
716744
stroke-dasharray="2"
717745
stroke-width="1"
718-
v-if="selectedTrap === trap && trap >= valueStart && trap < valueEnd"
746+
v-if="selectedTrap === trap && trap >= startMini && trap < endMini"
719747
/>
720748
</g>
721749
</template>
@@ -730,7 +758,7 @@ defineExpose({
730758
fill="transparent"
731759
style="pointer-events: all !important;"
732760
:style="{
733-
cursor: trap >= valueStart && trap < valueEnd && enableSelectionDrag ? isMouseDown ? 'grabbing' : 'grab' : 'default',
761+
cursor: trap >= startMini && trap < endMini && enableSelectionDrag ? isMouseDown ? 'grabbing' : 'grab' : 'default',
734762
}"
735763
@mousedown="isMouseDown = true"
736764
@mouseup="isMouseDown = false"

src/components/vue-ui-xy.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,6 @@ const svg = computed(() => {
154154
}
155155
});
156156
157-
const lttbThreshold = props.config.downsample ? props.config.downsample.threshold ? props.config.downsample.threshold : 500 : 500;
158-
159157
function safeInt(n) { return Number.isFinite(n) ? Math.max(0, Math.floor(n)) : 0 }
160158
function safeDiv(a, b, fallback = 0) {
161159
return (Number.isFinite(a) && Number.isFinite(b) && Math.abs(b) > 1e-9) ? (a / b) : fallback
@@ -425,7 +423,7 @@ const { loading, FINAL_DATASET, manualLoading } = useLoading({
425423
426424
const maxX = computed({
427425
get: () => {
428-
return Math.max(...FINAL_DATASET.value.map(datapoint => largestTriangleThreeBucketsArray({ data: datapoint.series, threshold: lttbThreshold }).length));
426+
return Math.max(...FINAL_DATASET.value.map(datapoint => largestTriangleThreeBucketsArray({ data: datapoint.series, threshold: FINAL_CONFIG.value.downsample.threshold }).length));
429427
},
430428
set: (v) => v
431429
});

0 commit comments

Comments
 (0)