From 8934f374bbe6af028d5ed91d040a18235c9dcfa1 Mon Sep 17 00:00:00 2001 From: Jz0ojiang <0ojixueseno0@gmail.com> Date: Sat, 5 Sep 2026 02:18:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Figma=20=E5=BC=8F=E5=A4=96=E5=A3=B3?= =?UTF-8?q?=E4=B8=8E=E7=BC=96=E8=BE=91=E5=99=A8=E5=86=85=E6=A0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 布局改成 顶部工具栏 / 左图层 / 中画布 / 右属性 / 底部悬浮胶囊。 新内核: - 图层模型:fabric 对象是唯一真源,LayerInfo 是只读投影; id/名字/锁定挂在 customProperties 上,随 toJSON 持久化 - 视口:zoom/pan 走 viewportTransform,只影响显示; 导出改为按视口裁剪(artboardExportOptions),旧的「multiplier 恒为 1」 在画布铺满工作区之后不再成立 - 历史:快照式撤销重做,30 步上限,带重入保护 - 命令表:快捷键 / 右键菜单 / 工具栏三个入口共用一份注册表 键位取自 Penpot 快捷键表 - 画板用 backgroundImage 画(跟随视口且不进 getObjects) 两个 fabric 陷阱已在注释里记下: - Rect 默认原点是中心,left:0/top:0 不写 originX/originY 会画错位置 - canvas.clipPath 不吃 viewportTransform,不能用来裁画板 --- src/App.vue | 58 ++++++- src/components/BottomDock.vue | 38 +++++ src/components/ContextMenu.vue | 32 ++++ src/components/Inspector.vue | 46 ++++++ src/components/LayersPanel.vue | 40 +++++ src/components/SelectionMenu.vue | 38 +++++ src/components/TopBar.vue | 32 ++++ src/components/Workspace.vue | 170 +++++++++++++++---- src/components/panels/CanvasPanel.vue | 6 +- src/components/panels/ExportPanel.vue | 4 +- src/editor/commands.ts | 217 +++++++++++++++++++++++++ src/editor/useContextMenu.ts | 25 +++ src/editor/useEditor.ts | 224 +++++++++++++++++++++----- src/editor/useHistory.ts | 105 ++++++++++++ src/editor/useLayers.ts | 125 ++++++++++++++ src/editor/useShortcuts.ts | 85 ++++++++++ src/editor/useViewport.ts | 138 ++++++++++++++++ src/io/export.ts | 55 +++++-- src/io/selfcheck.ts | 47 ++++-- src/style.css | 10 ++ src/types.ts | 96 +++++++++++ 21 files changed, 1493 insertions(+), 98 deletions(-) create mode 100644 src/components/BottomDock.vue create mode 100644 src/components/ContextMenu.vue create mode 100644 src/components/Inspector.vue create mode 100644 src/components/LayersPanel.vue create mode 100644 src/components/SelectionMenu.vue create mode 100644 src/components/TopBar.vue create mode 100644 src/editor/commands.ts create mode 100644 src/editor/useContextMenu.ts create mode 100644 src/editor/useHistory.ts create mode 100644 src/editor/useLayers.ts create mode 100644 src/editor/useShortcuts.ts create mode 100644 src/editor/useViewport.ts diff --git a/src/App.vue b/src/App.vue index 4eddcdf..e3fd8a8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,21 +1,69 @@ diff --git a/src/components/BottomDock.vue b/src/components/BottomDock.vue new file mode 100644 index 0000000..a9d4a1c --- /dev/null +++ b/src/components/BottomDock.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/components/ContextMenu.vue b/src/components/ContextMenu.vue new file mode 100644 index 0000000..de445be --- /dev/null +++ b/src/components/ContextMenu.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/components/Inspector.vue b/src/components/Inspector.vue new file mode 100644 index 0000000..14434ff --- /dev/null +++ b/src/components/Inspector.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/src/components/LayersPanel.vue b/src/components/LayersPanel.vue new file mode 100644 index 0000000..db49cdc --- /dev/null +++ b/src/components/LayersPanel.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/components/SelectionMenu.vue b/src/components/SelectionMenu.vue new file mode 100644 index 0000000..1eeed2b --- /dev/null +++ b/src/components/SelectionMenu.vue @@ -0,0 +1,38 @@ + + + + + diff --git a/src/components/TopBar.vue b/src/components/TopBar.vue new file mode 100644 index 0000000..0e95422 --- /dev/null +++ b/src/components/TopBar.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/components/Workspace.vue b/src/components/Workspace.vue index f4ef202..26a039a 100644 --- a/src/components/Workspace.vue +++ b/src/components/Workspace.vue @@ -1,62 +1,172 @@ diff --git a/src/components/panels/CanvasPanel.vue b/src/components/panels/CanvasPanel.vue index 3f57abc..9448d0b 100644 --- a/src/components/panels/CanvasPanel.vue +++ b/src/components/panels/CanvasPanel.vue @@ -1,9 +1,13 @@