Skip to content

Commit b1e6b0b

Browse files
7418claude
andcommitted
fix: 修复预览面板拖拽分隔线快速移动时宽度不跟手的问题
根因:ResizeHandle 使用 document.addEventListener('mousemove') 监听拖拽, 当鼠标快速移到 iframe(HTML 预览)上方时,iframe 捕获了鼠标事件, document 上的 mousemove 回调不再触发,导致宽度停止更新。 修复:将 mouse events 替换为 pointer events + setPointerCapture。 - onMouseDown → onPointerDown + setPointerCapture - 在元素上直接监听 onPointerMove/onPointerUp(不再挂 document 事件) - pointer capture 确保所有后续事件锁定到拖拽手柄,即使鼠标移到 iframe 上方 - 添加 touch-none CSS 防止触屏浏览器默认行为干扰拖拽 - 代码更简洁:不再需要手动 addEventListener/removeEventListener Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 056e908 commit b1e6b0b

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

src/components/layout/ResizeHandle.tsx

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,42 +13,48 @@ export function ResizeHandle({ side, onResize, onResizeEnd }: ResizeHandleProps)
1313
const isDragging = useRef(false);
1414
const startX = useRef(0);
1515

16-
const handleMouseDown = useCallback(
17-
(e: React.MouseEvent) => {
16+
const handlePointerDown = useCallback(
17+
(e: React.PointerEvent) => {
1818
e.preventDefault();
1919
isDragging.current = true;
2020
startX.current = e.clientX;
21-
21+
// Capture pointer so all subsequent events route here, even over iframes
22+
(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
2223
document.body.style.cursor = "col-resize";
2324
document.body.style.userSelect = "none";
25+
},
26+
[]
27+
);
2428

25-
const handleMouseMove = (ev: MouseEvent) => {
26-
if (!isDragging.current) return;
27-
const delta = ev.clientX - startX.current;
28-
startX.current = ev.clientX;
29-
onResize(delta);
30-
};
31-
32-
const handleMouseUp = () => {
33-
isDragging.current = false;
34-
document.body.style.cursor = "";
35-
document.body.style.userSelect = "";
36-
document.removeEventListener("mousemove", handleMouseMove);
37-
document.removeEventListener("mouseup", handleMouseUp);
38-
onResizeEnd?.();
39-
};
29+
const handlePointerMove = useCallback(
30+
(e: React.PointerEvent) => {
31+
if (!isDragging.current) return;
32+
const delta = e.clientX - startX.current;
33+
startX.current = e.clientX;
34+
onResize(delta);
35+
},
36+
[onResize]
37+
);
4038

41-
document.addEventListener("mousemove", handleMouseMove);
42-
document.addEventListener("mouseup", handleMouseUp);
39+
const handlePointerUp = useCallback(
40+
(e: React.PointerEvent) => {
41+
if (!isDragging.current) return;
42+
isDragging.current = false;
43+
(e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId);
44+
document.body.style.cursor = "";
45+
document.body.style.userSelect = "";
46+
onResizeEnd?.();
4347
},
44-
[onResize, onResizeEnd]
48+
[onResizeEnd]
4549
);
4650

4751
return (
4852
<div
49-
onMouseDown={handleMouseDown}
53+
onPointerDown={handlePointerDown}
54+
onPointerMove={handlePointerMove}
55+
onPointerUp={handlePointerUp}
5056
className={cn(
51-
"group relative z-10 flex w-1 shrink-0 cursor-col-resize items-center justify-center",
57+
"group relative z-10 flex w-1 shrink-0 cursor-col-resize items-center justify-center touch-none",
5258
side === "left" ? "-ml-0.5" : "-mr-0.5"
5359
)}
5460
>

0 commit comments

Comments
 (0)