fix: 优化右键拖动布局
This commit is contained in:
@@ -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() {
|
||||
<div
|
||||
className={`director-canvas${trajectoryPlacementObjectId ? " is-placing-trajectory" : ""}`}
|
||||
data-testid="director-canvas"
|
||||
// 屏蔽在画布上右键(右键平移)弹出的浏览器上下文菜单 / 手势:
|
||||
// 相机视角下没有 OrbitControls 接管右键,右键拖拽会直接触发浏览器手势,这里统一拦截。
|
||||
// 兜底:拦截画布上的浏览器右键上下文菜单(与平移无关——平移已改中键)。
|
||||
// 相机视角下没有 OrbitControls 接管,右键仍可能弹出系统菜单,这里统一拦掉。
|
||||
onContextMenu={(event) => event.preventDefault()}
|
||||
>
|
||||
<Canvas
|
||||
@@ -971,6 +1005,11 @@ export function DirectorCanvas() {
|
||||
enabled
|
||||
makeDefault
|
||||
target={DEFAULT_DIRECTOR_VIEW_SNAPSHOT.target}
|
||||
// 按键映射:左键旋转 / 中键平移 / 滚轮推拉。
|
||||
// 故意不把"平移"绑到右键——Edge 自 121 版起把「按住右键拖拽」作为浏览器级鼠标手势
|
||||
// (前进/后退/切标签),页面层 preventDefault 无法拦截(微软官方确认无 JS 方案)。
|
||||
// 平移改用中键,触摸板用户用双指拖拽即可,右键不再触发手势。
|
||||
mouseButtons={{ LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.PAN, RIGHT: undefined }}
|
||||
// 滚轮推拉距离:three 默认 1 偏慢,这里整体调快(见常量注释)
|
||||
zoomSpeed={VIEWPORT_WHEEL_ZOOM_SPEED}
|
||||
onChange={(event) => {
|
||||
@@ -1024,6 +1063,7 @@ export function DirectorCanvas() {
|
||||
viewMode={viewMode}
|
||||
/>
|
||||
<ViewportWheelGuard enabled={viewMode === "camera"} />
|
||||
<ViewportContextMenuGuard />
|
||||
<PlaybackFrameDriver />
|
||||
<VideoExportBridge />
|
||||
<PlaybackTransformSync />
|
||||
|
||||
Reference in New Issue
Block a user