/* const moveFn = createDragUtil(); moveFn.setOnMoveCallback((clientX: number, clientY: number, movedX: number, movedY: number) => { const dragDom = moveFn.getDraggingDom(); if (dragDom?.classList.contains('xxx')) { updateRangeMMove(clientX, true, dragDom, _saved.stopDoms); } else if (dragDom?.classList.contains('yyy')) { updatePicMMove(clientX); } });
// when zooming an image, the way to scale slowly const slowDelta = 1 + (scale - 1) * 0.2; tempScale = lastScale * slowDelta; */ export const createDragUtil = () => { let isDragging = false; let initialX = 0; let initialY = 0; let initialDirection: 'none' | 'vertical' | 'horizontal' = 'none'; let draggingDom: HTMLDivElement | null = null; let onMoveCallback: (clientX: number, clientY: number, movedX: number, movedY: number, initialDirection: 'none' | 'vertical' | 'horizontal') => void = () => {}; let onMoveEndCallback: () => void = () => {}; let onScaleCallback: (scale: number) => void = () => {}; let isZooming = false; let initialDistance = 0; const getDistance = (t1: Touch, t2: Touch) => { const dx = t2.clientX - t1.clientX; const dy = t2.clientY - t1.clientY; return Math.sqrt(dx * dx + dy * dy); }; const onMoveEnd = () => { onMoveEndCallback(); isDragging = false; isZooming = false; draggingDom = null; initialDirection = 'none'; }; return { setOnMoveCallback: (callback: (clientX: number, clientY: number, movedX: number, movedY: number, initialDirection: 'none' | 'vertical' | 'horizontal') => void) => { onMoveCallback = callback; }, setOnMoveEndCallback: (callback: () => void) => { onMoveEndCallback = callback; }, setOnScaleCallback: (callback: (scale: number) => void) => { onScaleCallback = callback; }, getDirection: () => initialDirection, getDistance, getDraggingDom: () => draggingDom, onMouseDown: (event: MouseEvent) => { event.preventDefault(); if (event.buttons !== 1) { isDragging = false; draggingDom = null; return; } isDragging = true; isZooming = false; draggingDom = event.currentTarget as HTMLDivElement; initialX = event.clientX; initialY = event.clientY; initialDirection = 'none'; }, onMouseMove: (event: MouseEvent) => { if (event.buttons === 0 && isDragging) { onMoveEnd(); } if (event.buttons === 0 || !draggingDom) { isDragging = false; draggingDom = null; initialDirection = 'none'; return; } const movedX = event.clientX - initialX; const movedY = event.clientY - initialY; if (initialDirection === 'none') { if (Math.abs(movedX) > 5 || Math.abs(movedY) > 5) { initialDirection = Math.abs(movedX) > Math.abs(movedY) ? 'horizontal' : 'vertical'; } } onMoveCallback(event.clientX, event.clientY, movedX, movedY, initialDirection); }, onMouseUp: onMoveEnd, onTouchStart: (event: TouchEvent) => { if (event.touches.length === 1) { isDragging = true; isZooming = false; draggingDom = event.currentTarget as HTMLDivElement; initialX = event.touches[0].clientX; initialY = event.touches[0].clientY; initialDirection = 'none'; } else if (event.touches.length === 2) { initialDistance = getDistance(event.touches[0], event.touches[1]); isDragging = false; isZooming = true; } else { isDragging = false; draggingDom = null; initialDirection = 'none'; } }, onTouchMove: (event: TouchEvent) => { if (isZooming) { if (event.touches.length === 2) { event.preventDefault(); // 防止页面滚动 const newDistance = getDistance(event.touches[0], event.touches[1]); const delta = newDistance / initialDistance; // const newScale = Math.min(Math.max(1, scale * delta), 4); // 限制缩放范围 onScaleCallback(delta); } else { onMoveEnd(); } return; } if (event.touches.length === 0 && isDragging) { onMoveEnd(); } if (event.touches.length === 0 || !draggingDom) { isDragging = false; draggingDom = null; initialDirection = 'none'; return; } const movedX = event.touches[0].clientX - initialX; const movedY = event.touches[0].clientY - initialY; if (initialDirection === 'none') { if (Math.abs(movedX) > 5 || Math.abs(movedY) > 5) { initialDirection = Math.abs(movedX) > Math.abs(movedY) ? 'horizontal' : 'vertical'; } } onMoveCallback( event.touches[0].clientX, event.touches[0].clientY, movedX, movedY, initialDirection ); }, onTouchEnd: onMoveEnd, }; };