diff --git a/MinimumBoundingBox/README.md b/MinimumBoundingBox/README.md index 50240c6..df8e7e3 100644 --- a/MinimumBoundingBox/README.md +++ b/MinimumBoundingBox/README.md @@ -33,3 +33,7 @@ pnpm dev - **Mouse Left (Click on TransformControls Widget):** 拖动物体 - **Shift + Mouse Left:** 选中多个物体 - **Del:** 删除选中物体 + +#### 触控设备: + +- **长按:** 新增物体 diff --git a/MinimumBoundingBox/src/main.ts b/MinimumBoundingBox/src/main.ts index 5684805..8c619eb 100644 --- a/MinimumBoundingBox/src/main.ts +++ b/MinimumBoundingBox/src/main.ts @@ -5,6 +5,7 @@ import { ControlsManager } from "./controls"; import { SelectionManager } from "./selection"; import { BoundingBoxManager } from "./boundingBox"; import { computeCentroid } from "./utils"; +import { addTouchEventListener } from "./touch"; // 初始化 SceneManager const sceneManager = new SceneManager(); @@ -118,14 +119,25 @@ document.addEventListener("keyup", (event) => { } }); +addTouchEventListener(onAddPoint); + // 点击新增点的逻辑 -function onAddPoint(event: MouseEvent) { - const mouse = new THREE.Vector2( - (event.clientX / window.innerWidth) * 2 - 1, - -(event.clientY / window.innerHeight) * 2 + 1 - ); +function onAddPoint(event: MouseEvent | TouchEvent) { + let coords = new THREE.Vector2(); + if (event instanceof MouseEvent) { + coords = new THREE.Vector2( + (event.clientX / window.innerWidth) * 2 - 1, + -(event.clientY / window.innerHeight) * 2 + 1 + ); + } else if (event instanceof TouchEvent) { + const touch = event.touches[0]; + coords = new THREE.Vector2( + (touch.clientX / window.innerWidth) * 2 - 1, + -(touch.clientY / window.innerHeight) * 2 + 1 + ); + } const raycaster = new THREE.Raycaster(); - raycaster.setFromCamera(mouse, sceneManager.camera); + raycaster.setFromCamera(coords, sceneManager.camera); // 使用已经存在的 testPlane 进行交叉检测 const intersects = raycaster.intersectObject(sceneManager.testPlane); diff --git a/MinimumBoundingBox/src/touch.ts b/MinimumBoundingBox/src/touch.ts new file mode 100644 index 0000000..db2a915 --- /dev/null +++ b/MinimumBoundingBox/src/touch.ts @@ -0,0 +1,72 @@ +// 初始化变量 +let touchStartX = 0; +let touchStartY = 0; +let touchStartTime = 0; +let longPressTimer: any = null; +const LONG_PRESS_DURATION = 500; // 长按时间,单位毫秒 + +export function addTouchEventListener( + longPressCallback: (event: TouchEvent) => void +) { + // 支援触摸事件 + document.addEventListener("touchstart", (event) => { + // 如果有多个触摸点,则取消长按检测 + if (event.touches.length > 1) { + clearTimeout(longPressTimer); + longPressTimer = null; + return; + } + + // 记录触摸的起始位置和时间 + const touch = event.touches[0]; + touchStartX = touch.clientX; + touchStartY = touch.clientY; + touchStartTime = Date.now(); + + // 设置一个计时器,检测长按 + longPressTimer = setTimeout(() => { + // 在这里可以触发长按的相关逻辑 + longPressCallback(event); + }, LONG_PRESS_DURATION); + }); + + // touchend 事件处理 + document.addEventListener("touchend", (event) => { + // 如果触摸点数减少到0或1,可能需要重新判断 + if (event.touches.length === 0 || event.touches.length === 1) { + // 触摸结束时清除计时器 + clearTimeout(longPressTimer); + longPressTimer = null; + } + }); + + // touchmove 事件处理 + document.addEventListener("touchmove", (event) => { + // 如果有多个触摸点,则取消长按检测 + if (event.touches.length > 1) { + clearTimeout(longPressTimer); + longPressTimer = null; + return; + } + + // 检查触摸点是否有移动 + const touch = event.touches[0]; + const moveX = touch.clientX; + const moveY = touch.clientY; + + // 如果移动超过一定范围,认为不是长按 + if ( + Math.abs(moveX - touchStartX) > 10 || + Math.abs(moveY - touchStartY) > 10 + ) { + clearTimeout(longPressTimer); + longPressTimer = null; + } + }); + + document.addEventListener("touchcancel", () => { + // 触摸被中断时,清除计时器 + clearTimeout(longPressTimer); + longPressTimer = null; + }); +}