diff --git a/src/editor/canvas/DirectorCanvas.tsx b/src/editor/canvas/DirectorCanvas.tsx index 96c33dc..c016483 100644 --- a/src/editor/canvas/DirectorCanvas.tsx +++ b/src/editor/canvas/DirectorCanvas.tsx @@ -10,7 +10,7 @@ import { type CSSProperties, type MutableRefObject, } from "react"; -import { Euler, Matrix4, PerspectiveCamera as ThreePerspectiveCamera, Quaternion, Spherical, Vector3 } from "three"; +import { Euler, Matrix4, MOUSE, PerspectiveCamera as ThreePerspectiveCamera, Quaternion, Spherical, Vector3 } from "three"; import type { Object3D } from "three"; import type { OrbitControls as OrbitControlsImpl } from "three-stdlib"; import { clearViewportCaptureHandler, setViewportCaptureHandler } from "../io/captureBridge"; @@ -640,6 +640,40 @@ function ViewportWheelGuard({ enabled }: { enabled: boolean }) { return null; } +/** 兜底:拦截画布上的浏览器右键上下文菜单(平移已改用中键,这里主要防误触右键弹系统菜单)。 + * 以捕获阶段 + 非 passive 挂在 canvas 原生 dom 上;对右键 pointerdown 也 preventDefault, + * 顺手挡掉部分浏览器仍会冒出来的右键拖拽默认行为。 */ +function ViewportContextMenuGuard() { + const { gl } = useThree(); + + useEffect(() => { + const canvas = gl.domElement; + if (typeof canvas?.addEventListener !== "function") { + return; + } + const handleContextMenu = (event: Event) => { + event.preventDefault(); + }; + // 右键按下时先拦掉浏览器默认行为,避免 Edge 把右键拖拽识别成手势 + const handlePointerDown = (event: PointerEvent) => { + if (event.button === 2) { + event.preventDefault(); + } + }; + // 捕获阶段、非 passive:确保先于任何浏览器默认/手势逻辑执行 + canvas.addEventListener("contextmenu", handleContextMenu, { capture: true, passive: false }); + canvas.addEventListener("pointerdown", handlePointerDown, { capture: true, passive: false }); + canvas.addEventListener("dragstart", handleContextMenu, { capture: true, passive: false }); + return () => { + canvas.removeEventListener("contextmenu", handleContextMenu, { capture: true }); + canvas.removeEventListener("pointerdown", handlePointerDown, { capture: true }); + canvas.removeEventListener("dragstart", handleContextMenu, { capture: true }); + }; + }, [gl]); + + return null; +} + /** 把渲染三件套注册给视频导出逻辑(逐帧离线渲染用),模式仿 CanvasCaptureBridge */ function VideoExportBridge() { const { camera, gl, scene } = useThree(); @@ -914,8 +948,8 @@ export function DirectorCanvas() {