Skip to content

Commit b036dee

Browse files
committed
Fix - Slicer & SlicerPreview - Fix offset from client position when dragging selection from the range track
1 parent e772544 commit b036dee

File tree

2 files changed

+399
-323
lines changed

2 files changed

+399
-323
lines changed

src/atoms/Slicer.vue

Lines changed: 80 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
<script setup>
2-
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, onUpdated } from 'vue';
3-
import BaseIcon from './BaseIcon.vue';
4-
import { useResponsive } from '../useResponsive';
2+
import {
3+
computed,
4+
nextTick,
5+
onBeforeUnmount,
6+
onMounted,
7+
onUpdated,
8+
ref,
9+
watch,
10+
} from 'vue';
11+
import {
12+
adaptColorToBackground,
13+
createSmoothPath,
14+
createStraightPath,
15+
createUid,
16+
XMLNS,
17+
} from '../lib';
518
import { throttle } from '../canvas-lib';
6-
import { XMLNS, adaptColorToBackground, createSmoothPath, createStraightPath, createUid } from '../lib';
19+
import { useResponsive } from '../useResponsive';
20+
import BaseIcon from './BaseIcon.vue';
721
822
const props = defineProps({
923
background: {
@@ -355,13 +369,23 @@ const selectionWidth = computed(() => {
355369
return ((wrapperWidth.value - 48) / (props.max - props.min)) * currentRange.value;
356370
});
357371
358-
const RA_SPECIAL_MAGIC_NUMBER = ref(2.5);
372+
const TRACK_PADDING = 48;
373+
374+
const usablePx = computed(() => {
375+
return Math.max(1, wrapperWidth.value - TRACK_PADDING - selectionWidth.value);
376+
});
359377
360-
const flooredDatapointsToWidth = computed(() => {
361-
const w = wrapperWidth.value - 48;
362-
return Math.ceil((props.max - props.min) / ((w - selectionWidth.value) / RA_SPECIAL_MAGIC_NUMBER.value));
378+
const usableSteps = computed(() => {
379+
return Math.max(1, (props.max - props.min) - currentRange.value);
363380
});
364381
382+
const indicesPerPixel = computed(() => usableSteps.value / usablePx.value);
383+
384+
const dragStartX = ref(0);
385+
const dragStartStart = ref(0);
386+
const dragStartEnd = ref(0);
387+
const ippAtStart = ref(0);
388+
365389
let activeMoveEvent = null;
366390
let activeEndEvent = null;
367391
let activeMoveHandler = null;
@@ -372,28 +396,30 @@ const startDragging = (event) => {
372396
if (!props.enableSelectionDrag) return;
373397
374398
const isTouch = event.type === 'touchstart';
399+
if (!isTouch) event.stopPropagation();
375400
376-
if(!isTouch) {
377-
event.stopPropagation();
378-
}
379-
380-
const touch0 =
381-
isTouch && event.targetTouches && event.targetTouches[0] ? event.targetTouches[0] : null;
401+
const touch0 = isTouch && event.targetTouches && event.targetTouches[0] ? event.targetTouches[0] : null;
382402
const target = isTouch ? (touch0 ? touch0.target : null) : event.target;
383403
384404
if (!target || !(target instanceof Element)) return;
385405
if (target.classList && target.classList.contains('range-handle')) return;
386406
387407
isDragging.value = true;
388-
initialMouseX.value = isTouch ? (touch0 ? touch0.clientX : 0) : event.clientX;
389408
390-
activeMoveEvent = isTouch ? 'touchmove' : 'mousemove';
391-
activeEndEvent = isTouch ? 'touchend' : 'mouseup';
409+
const x = isTouch ? (touch0 ? touch0.clientX : 0) : event.clientX;
410+
initialMouseX.value = x;
411+
dragStartX.value = x;
412+
dragStartStart.value = Number(startValue.value);
413+
dragStartEnd.value = Number(endValue.value);
414+
ippAtStart.value = indicesPerPixel.value;
415+
416+
activeMoveEvent = isTouch ? 'touchmove' : 'mousemove';
417+
activeEndEvent = isTouch ? 'touchend' : 'mouseup';
392418
activeMoveHandler = isTouch ? handleTouchDragging : handleDragging;
393-
activeEndHandler = isTouch ? stopTouchDragging : stopDragging;
419+
activeEndHandler = isTouch ? stopTouchDragging : stopDragging;
394420
395421
window.addEventListener(activeMoveEvent, activeMoveHandler, { passive: false });
396-
window.addEventListener(activeEndEvent, activeEndHandler);
422+
window.addEventListener(activeEndEvent, activeEndHandler);
397423
};
398424
399425
function handleDragging(event) {
@@ -420,27 +446,14 @@ function handleTouchDragging(event) {
420446
421447
function updateDragging(currentX) {
422448
if (!isDragging.value) return;
423-
424-
const deltaX = currentX - initialMouseX.value;
425-
426-
if (Math.abs(deltaX) > dragThreshold.value) {
427-
if (deltaX > 0) {
428-
if (Number(endValue.value) + 1 <= props.max) {
429-
const v = Math.min(props.max, Number(endValue.value) + flooredDatapointsToWidth.value);
430-
setEndValue(v);
431-
setStartValue(v - currentRange.value);
432-
}
433-
} else {
434-
if (Number(startValue.value) - 1 >= props.min) {
435-
const v = Math.max(props.min, Number(startValue.value) - flooredDatapointsToWidth.value);
436-
setStartValue(v);
437-
setEndValue(v + currentRange.value);
438-
}
439-
}
440-
initialMouseX.value = currentX;
441-
}
449+
const dx = currentX - dragStartX.value;
450+
const shift = dx * ippAtStart.value;
451+
let newStart = Math.round(dragStartStart.value + shift);
452+
newStart = Math.max(props.min, Math.min(newStart, props.max - currentRange.value));
453+
const newEnd = newStart + currentRange.value;
454+
setStartValue(newStart);
455+
setEndValue(newEnd);
442456
}
443-
444457
function stopDragging() {
445458
endDragging();
446459
}
@@ -571,28 +584,49 @@ onBeforeUnmount(() => {
571584
@touchstart="startDragging"
572585
@touchend="showTooltip = false"
573586
>
574-
<div class="vue-data-ui-slicer-labels" style="position: relative; z-index: 1; pointer-events: none;">
575-
<div v-if="valueStart !== refreshStartPoint || valueEnd !== endpoint" style="width: 100%; position: relative">
587+
<div
588+
class="vue-data-ui-slicer-labels"
589+
style="position: relative; z-index: 1; pointer-events: none;"
590+
>
591+
<div
592+
v-if="valueStart !== refreshStartPoint || valueEnd !== endpoint"
593+
style="width: 100%; position: relative"
594+
>
576595
<button
577596
v-if="!useResetSlot"
578-
data-cy="slicer-reset" tabindex="0"
597+
data-cy="slicer-reset"
598+
tabindex="0"
579599
role="button"
580600
class="vue-data-ui-refresh-button"
581601
:style="{
582602
top: hasMinimap ? '36px' : '-16px',
583603
pointerEvents: 'all !important'
584604
}"
585-
@click="reset">
605+
@click="reset"
606+
>
586607
<BaseIcon name="refresh" :stroke="textColor" />
587608
</button>
588609
<slot v-else name="reset-action" :reset="reset" />
589610
</div>
590611
</div>
591612

592-
<div class="double-range-slider" ref="minimapWrapper" style="z-index: 0" @mouseenter="showTooltip = true" @mouseleave="showTooltip = false">
613+
<div
614+
class="double-range-slider"
615+
ref="minimapWrapper"
616+
style="z-index: 0"
617+
@mouseenter="showTooltip = true"
618+
@mouseleave="showTooltip = false"
619+
>
593620
<template v-if="hasMinimap">
594-
<div class="minimap" style="width: 100%" data-cy="minimap">
595-
<svg data-cy="slicer-minimap-svg" :xmlns="XMLNS" :viewBox="`0 0 ${svgMinimap.width < 0 ? 0 : svgMinimap.width} ${svgMinimap.height < 0 ? 0 : svgMinimap.height}`">
621+
<div
622+
class="minimap"
623+
style="width: 100%" data-cy="minimap"
624+
>
625+
<svg
626+
data-cy="slicer-minimap-svg"
627+
:xmlns="XMLNS"
628+
:viewBox="`0 0 ${svgMinimap.width < 0 ? 0 : svgMinimap.width} ${svgMinimap.height < 0 ? 0 : svgMinimap.height}`"
629+
>
596630
<defs>
597631
<linearGradient :id="uid" x1="0%" y1="0%" x2="0%" y2="100%">
598632
<stop offset="0%" :stop-color="`${minimapLineColor}50`"/>

0 commit comments

Comments
 (0)