feat: 形状工具改为拖拽创建,五种形状 + Shift 约束比例(T12)

This commit is contained in:
2026-09-05 18:24:56 +08:00
parent 19c8c604cb
commit 27c540837e
3 changed files with 441 additions and 26 deletions
+9 -6
View File
@@ -4,6 +4,7 @@ import { useEditor } from "@/editor/useEditor";
import { useViewport } from "@/editor/useViewport";
import { initHistory, commit } from "@/editor/useHistory";
import { openContextMenu } from "@/editor/useContextMenu";
import { attachShapeTool } from "@/editor/useShapeTool";
/**
* 画布区。**画布元素的像素尺寸跟着容器走**(它是「视口」),
@@ -16,7 +17,7 @@ import { openContextMenu } from "@/editor/useContextMenu";
*
* **这个文件由主控独占。**
*/
const { mount, unmount, getCanvas, tool, addText, addRect } = useEditor();
const { mount, unmount, getCanvas, tool, addText } = useEditor();
const { zoomAt, panBy, zoomToFit } = useViewport();
const canvasEl = ref<HTMLCanvasElement | null>(null);
@@ -26,6 +27,7 @@ let spaceDown = false;
let panning = false;
let lastX = 0;
let lastY = 0;
let detachShapeTool: (() => void) | null = null;
/**
* 视口尺寸跟着容器走。
@@ -86,14 +88,12 @@ function onPointerDown(e: PointerEvent) {
(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
return;
}
// 形状工具:拖拽创建由 useShapeTool 的 attachShapeTool 接管,这里完全让开。
if (e.button === 0 && tool.value === "shape") return;
// 非选择工具:在点击处放一个新对象,然后回到选择工具(和 Figma 一致)
if (e.button === 0 && tool.value !== "select") {
const c = getCanvas();
const p = c.getViewportPoint(e);
const scene = c.getScenePoint(e);
void p;
if (tool.value === "text") addText();
else if (tool.value === "shape") addRect({ x: scene.x, y: scene.y });
if (tool.value !== "background") {
tool.value = "select";
commit();
@@ -126,6 +126,8 @@ onMounted(() => {
// 尺寸与首次适应交给 resize(),它会等到 stage 真的有尺寸了再做。
resize();
initHistory();
// 形状工具的指针交互单独挂在画布上,这里只负责装/卸。
detachShapeTool = attachShapeTool(c);
// 拖拽 / 缩放 / 旋转结束都算一步操作。
c.on("object:modified", () => commit());
observer = new ResizeObserver(resize);
@@ -136,6 +138,7 @@ onMounted(() => {
onBeforeUnmount(() => {
observer?.disconnect();
detachShapeTool?.();
window.removeEventListener("keydown", onKeyDown);
window.removeEventListener("keyup", onKeyUp);
unmount();