@@ -15,6 +15,7 @@ import {
1515 createStraightPath ,
1616 createStraightPathWithCuts ,
1717 createUid ,
18+ triggerEvent ,
1819 XMLNS ,
1920} from ' ../lib' ;
2021import { debounce , throttle } from ' ../canvas-lib' ;
@@ -147,6 +148,14 @@ const props = defineProps({
147148 cutNullValues: {
148149 type: Boolean ,
149150 default: false ,
151+ },
152+ focusOnDrag: {
153+ type: Boolean ,
154+ default: false ,
155+ },
156+ focusRangeRatio: {
157+ type: Number ,
158+ default: 0.1
150159 }
151160});
152161
@@ -616,6 +625,10 @@ const currentRange = computed(() => {
616625 return props .valueEnd - props .valueStart ;
617626});
618627
628+ const isZoom = computed (() => {
629+ return currentRange .value < (props .max - props .min );
630+ });
631+
619632const isDragging = ref (false );
620633let initialMouseX = ref (null );
621634
@@ -645,7 +658,24 @@ let activeEndEvent = null;
645658let activeMoveHandler = null ;
646659let activeEndHandler = null ;
647660
648- const startDragging = (event ) => {
661+ const dragStartIndex = ref (props .min );
662+
663+ function clientXToIndex (clientX ) {
664+ if (! zoomWrapper .value ) return props .min ;
665+
666+ const rect = zoomWrapper .value .getBoundingClientRect ();
667+ const left = rect .left + TRACK_PADDING / 2 ;
668+ const right = rect .right - TRACK_PADDING / 2 ;
669+ const trackWidth = Math .max (1 , right - left);
670+
671+ const x = Math .max (left, Math .min (clientX, right));
672+ const pct = (x - left) / trackWidth;
673+
674+ const span = Math .max (1 , props .max - props .min );
675+ return Math .round (props .min + pct * span);
676+ }
677+
678+ const startDragging = async (event ) => {
649679 showTooltip .value = true ;
650680 if (! props .enableSelectionDrag ) return ;
651681
@@ -663,6 +693,27 @@ const startDragging = (event) => {
663693 const x = isTouch ? (touch0 ? touch0 .clientX : 0 ) : event .clientX ;
664694 initialMouseX .value = x;
665695 dragStartX .value = x;
696+
697+ if (props .focusOnDrag && ! isZoom .value && zoomWrapper .value ) {
698+ dragStartIndex .value = clientXToIndex (x);
699+ const ratio = Math .min (0.95 , Math .max (0.05 , props .focusRangeRatio ));
700+
701+ const total = props .max - props .min ;
702+ const span = Math .max (1 , Math .round (total * ratio));
703+ const half = Math .floor (span / 2 );
704+
705+ let focusStart = dragStartIndex .value - half;
706+ focusStart = Math .max (props .min , Math .min (focusStart, props .max - span));
707+ const focusEnd = Math .min (props .max , focusStart + span);
708+
709+ setStartValue (focusStart);
710+ setEndValue (focusEnd);
711+
712+ triggerEvent (zoomWrapper .value , ' mouseup' );
713+ await nextTick ();
714+ triggerEvent (zoomWrapper .value , ' mousedown' , { clientX: x });
715+ }
716+
666717 dragStartStart .value = Number (startValue .value );
667718 dragStartEnd .value = Number (endValue .value );
668719 ippAtStart .value = indicesPerPixel .value ;
@@ -700,14 +751,20 @@ function handleTouchDragging(event) {
700751
701752function updateDragging (currentX ) {
702753 if (! isDragging .value ) return ;
703- const dx = currentX - dragStartX .value ;
704- const shift = dx * ippAtStart .value ;
705- let newStart = Math .round (dragStartStart .value + shift);
706- newStart = Math .max (props .min , Math .min (newStart, props .max - currentRange .value ));
707- const newEnd = newStart + currentRange .value ;
754+ const i0 = clientXToIndex (dragStartX .value );
755+ const i1 = clientXToIndex (currentX);
756+ const deltaIdx = i1 - i0;
757+ const span = Math .max (1 , dragStartEnd .value - dragStartStart .value );
758+ let newStart = Math .round (dragStartStart .value + deltaIdx);
759+ const minStart = props .min ;
760+ const maxStart = props .max - span;
761+ if (newStart < minStart) newStart = minStart;
762+ if (newStart > maxStart) newStart = maxStart;
763+ const newEnd = newStart + span;
708764 setStartValue (newStart);
709765 setEndValue (newEnd);
710766}
767+
711768function stopDragging () {
712769 endDragging ();
713770}
0 commit comments