From 9fb29b4b4172f6eced73ff0d6824833ef1728de0 Mon Sep 17 00:00:00 2001 From: zhangheng Date: Thu, 9 Apr 2026 09:47:53 +0800 Subject: [PATCH] fix(label): improve doubleclick --- components/label/usePaperStore.ts | 80 +++++++++++++++++-------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/components/label/usePaperStore.ts b/components/label/usePaperStore.ts index 5bd17c6..9c742f7 100644 --- a/components/label/usePaperStore.ts +++ b/components/label/usePaperStore.ts @@ -509,6 +509,37 @@ export const getShowContextMenuPosition = ( } } +const DOUBLE_CLICK_TOLERANCE_PX = 8 + +const getPaperDoubleClickTolerance = ( + coordinateSpace: "project" | "local" = "project" +) => { + const viewZoom = usePaperStore.getState().paperScope?.view.zoom || 1 + const projectTolerance = DOUBLE_CLICK_TOLERANCE_PX / viewZoom + + if (coordinateSpace === "local") { + const groupScale = usePaperStore.getState().group?.scaling.x || 1 + return projectTolerance / groupScale + } + + return projectTolerance +} + +const isPaperDoubleClick = ( + event: MouseEvent, + lastPoint: paper.Point | null | undefined, + currentPoint: paper.Point, + coordinateSpace: "project" | "local" = "project" +) => { + if (event.button !== 0 || event.detail < 2 || !lastPoint) return false + + // 交给浏览器按系统双击速度判定,再补一个小范围容差,避免画布点击抖动。 + return ( + lastPoint.getDistance(currentPoint) <= + getPaperDoubleClickTolerance(coordinateSpace) + ) +} + export const usePositionStore = create((set) => ({ currentMousePosition: [0, 0], setCurrentMousePosition: (point) => @@ -637,7 +668,6 @@ export const usePaperStore = create((set) => ({ let panTool = paperPanTool let lastPoint: paper.Point let isChanged: boolean = false - let lastTime: number // const handleSelected = (path: paper.Path) => { // // path.blendMode = "subtract"; @@ -778,8 +808,6 @@ export const usePaperStore = create((set) => ({ panTool.onMouseDown = (e: { event: MouseEvent; point: paper.Point }) => { if (startMiddleMousePan(e.event)) return if (pressCtrl) return - const currentTime = Date.now() - const timeDelta = currentTime - lastTime if (e.event && e.event.button === 0) { hidePaperContextMenu() @@ -790,6 +818,12 @@ export const usePaperStore = create((set) => ({ } let point = usePaperStore.getState().group!.globalToLocal(e.point) + const isDoubleClick = isPaperDoubleClick( + e.event, + lastPoint, + point, + "local" + ) let hitResult = usePaperStore.getState().group?.hitTest(e.point, { segments: true, @@ -978,12 +1012,7 @@ export const usePaperStore = create((set) => ({ // item.fillColor = new paper.Color("transparent"); // item.strokeColor = item.strokeColor || new paper.Color("red"); // item.strokeWidth = item.strokeWidth || 1; - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { console.log("点击位置 多边形子路径", childHitResult) if (childHitResult.item instanceof paper.Path) { // if (!childHitResult.item.data.selected) { @@ -1011,12 +1040,7 @@ export const usePaperStore = create((set) => ({ }) } else if (hitResult.item instanceof paper.Path) { // doubleclick; - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { if (hitResult.item.data.isHollowPolygon) return let selectedItems = usePaperStore.getState().group!.getItems({ data: { selected: true }, @@ -1216,12 +1240,7 @@ export const usePaperStore = create((set) => ({ activePath?.data?.type === "point" ) { // doubleclick - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { if (activePath instanceof paper.CompoundPath) { ;(activePath.children as paper.Path[]).forEach((item) => { const childHitResult = item.hitTest(point, { @@ -1310,12 +1329,7 @@ export const usePaperStore = create((set) => ({ activePath?.data?.type === "brush" || activePath?.data?.type === "point" ) { - if ( - lastPoint && - lastPoint.x === point.x && - lastPoint.y === point.y && - timeDelta < 200 - ) { + if (isDoubleClick) { if (activePath instanceof paper.CompoundPath) { ;(activePath.children as paper.Path[]).forEach((item) => { const childHitResult = item.hitTest(point, { @@ -1456,7 +1470,6 @@ export const usePaperStore = create((set) => ({ console.log("鼠标按下 选中路径", activePath, "当前模式", panMode) lastPoint = point - lastTime = Date.now() } panTool.onMouseDrag = (e: { @@ -3320,12 +3333,9 @@ export const usePaperStore = create((set) => ({ // 先判断是否存在吸附点 let checkPoint = currentMagnetPoint ? currentMagnetPoint : e.point + const isDoubleClick = isPaperDoubleClick(e.event, lastPoint, checkPoint) // doubleclick - if ( - lastPoint && - lastPoint.x === checkPoint.x && - lastPoint.y === checkPoint.y - ) { + if (isDoubleClick) { if (polygon) { if ((polygon as paper.Path).segments.length < 3) { polygon.remove() @@ -4246,7 +4256,7 @@ export const usePaperStore = create((set) => ({ } // doubleclick - if (lastPoint && lastPoint.x === e.point.x && lastPoint.y === e.point.y) { + if (isPaperDoubleClick(e.event, lastPoint, e.point)) { if (myPath) { // 初始化 compoundPolygon compoundPolygon = new paper.Path() @@ -4717,7 +4727,7 @@ export const usePaperStore = create((set) => ({ } // doubleclick - if (lastPoint && lastPoint.x === e.point.x && lastPoint.y === e.point.y) { + if (isPaperDoubleClick(e.event, lastPoint, e.point)) { if (myPath) { // 去除超出图片边界的部分 myCircle = myCircle.filter((circle) => {