From be6f22b3d6513375fa94ce0efa8aab633112c4d6 Mon Sep 17 00:00:00 2001 From: Your Name Date: Tue, 3 Feb 2026 10:19:10 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=94=BB=E5=B8=83?= =?UTF-8?q?=E7=BC=A9=E6=94=BE=E4=BA=A4=E4=BA=92=20-=20=E6=BB=9A=E8=BD=AE?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E7=BC=A9=E6=94=BE=EF=BC=8C=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=BC=A9=E6=94=BE=E6=8E=A7=E5=88=B6=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/canvas/CanvasWorkspace.tsx | 84 +++++++++++++++++++-------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/components/canvas/CanvasWorkspace.tsx b/components/canvas/CanvasWorkspace.tsx index 9ce2e24d8..245413d3a 100644 --- a/components/canvas/CanvasWorkspace.tsx +++ b/components/canvas/CanvasWorkspace.tsx @@ -9,6 +9,8 @@ import { ImageNode } from "./nodes/ImageNode"; import { TextNode } from "./nodes/TextNode"; import { VideoNode } from "./nodes/VideoNode"; import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { Minus, Plus } from "lucide-react"; // 性能优化:判断节点是否在视口内 function isNodeInViewport( @@ -112,29 +114,31 @@ export function CanvasWorkspace() { // 处理滚轮缩放 const handleWheel = useCallback((e: React.WheelEvent) => { - if (e.ctrlKey || e.metaKey) { - e.preventDefault(); - const delta = e.deltaY > 0 ? 0.9 : 1.1; - const newZoom = Math.max(0.1, Math.min(4, viewport.zoom * delta)); - - // 以鼠标位置为中心缩放 - const rect = containerRef.current?.getBoundingClientRect(); - if (rect) { - const mouseX = e.clientX - rect.left; - const mouseY = e.clientY - rect.top; - - const scaleChange = newZoom / viewport.zoom; - const newX = mouseX - (mouseX - viewport.x) * scaleChange; - const newY = mouseY - (mouseY - viewport.y) * scaleChange; - - setViewport({ x: newX, y: newY, zoom: newZoom }); - } - } else { - // 普通滚动平移 + e.preventDefault(); + + // Shift + 滚轮 = 平移 + if (e.shiftKey) { setViewport({ - x: viewport.x - e.deltaX, - y: viewport.y - e.deltaY, + x: viewport.x - e.deltaY, + y: viewport.y - e.deltaX, }); + return; + } + + // 默认滚轮 = 缩放(以鼠标位置为中心) + const delta = e.deltaY > 0 ? 0.9 : 1.1; + const newZoom = Math.max(0.1, Math.min(4, viewport.zoom * delta)); + + const rect = containerRef.current?.getBoundingClientRect(); + if (rect) { + const mouseX = e.clientX - rect.left; + const mouseY = e.clientY - rect.top; + + const scaleChange = newZoom / viewport.zoom; + const newX = mouseX - (mouseX - viewport.x) * scaleChange; + const newY = mouseY - (mouseY - viewport.y) * scaleChange; + + setViewport({ x: newX, y: newY, zoom: newZoom }); } }, [viewport, setViewport]); @@ -267,9 +271,41 @@ export function CanvasWorkspace() { )} - {/* 缩放指示器 */} -
- {Math.round(viewport.zoom * 100)}% + {/* 缩放控制器 */} +
+ + +
);