ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

open-pencil Vue SDK:用 PageListRoot 与 LayerTreeRoot 构建页面/图层导航面板

open-pencil Vue SDK:用 PageListRoot 与 LayerTreeRoot 构建页面/图层导航面板 前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载在设计类应用如 Figma 类编辑器中侧边面板几乎是标配上方是页面列表下方是图层树配合选中状态与行内重命名。open-pencil 的 Vue SDKpackages/vue为这两块区域提供了无样式unstyled的组件与组合式函数PageListRoot/usePageList()负责页面列表LayerTreeRoot/useLayerTree()负责图层树useSelectionState()负责驱动选中状态。本指南以官方文档《Panneaux de navigation》navigation-panels.md为骨架结合 packages/vue 下的真实实现说明如何用它们搭出可复用、可定制的导航面板以及这些组件内部是如何与编辑器状态、场景图同步的。设计原则无样式组件 作用域插槽SDK 的设计思路是把状态管理交给 SDK把 UI 渲染交给应用。页面列表和图层树的组件本身不携带任何 CSS也不假设你使用什么 UI 库——它们通过v-slot向外暴露数据与操作由你在插槽模板里自由组织布局和样式。这样做的直接收益列表的视觉呈现按钮、菜单、缩进、图标完全由应用决定交互逻辑切页、增删页面、选中、展开/折叠、拖拽由 SDK 统一维护保证与画布状态一致可以轻松套用任意组件库如 TreeView、reka-ui 等或自己写原生 DOM。两个根组件在源码中的导出位置是 packages/vue/src/index.ts而PageListRoot和LayerTreeRoot的实现分别位于 PageListRoot.vue 与 LayerTreeRoot.vue。页面列表PageListRoot 与 usePageList组件用法文档给出的最小示例直接用PageListRoot渲染一组按钮PageListRoot v-slot{ pages, currentPageId, switchPage, addPage } div button v-forpage in pages :keypage.id clickswitchPage(page.id) {{ page.name }} /button button clickaddPage()Nouvelle Page/button /div /PageListRoot插槽内可用的数据与动作与 usePageList.ts 的返回值一一对应名称类型说明pages响应式数组当前文档的全部页面来自editor.graph.getPages()随场景变化自动更新currentPageIdstring当前激活页面的 IDswitchPage(id: string) void切换到指定页面addPage() void新建页面renamePage(id, name) void重命名页面deletePage(id) void删除页面movePage(id, index) void调整页面顺序更完整的实现分割线与事件在真实代码中PageListRoot还额外暴露了更多能力可用于实现 Figma 式的“分割线页面”分隔符和菜单操作PageListRoot v-slot{ pages, currentPageId, isDivider, actions } div button v-forpage in pages :keypage.id :data-activepage.id currentPageId clickactions.switch(page.id) {{ page.name }} /button button clickactions.add() Nouvelle Page/button /div /PageListRootisDivider(page)判断一个页面是否为分割线。分割线的判定规则在 PageListRoot.vue该页面没有子节点且名称匹配dividerPattern默认正则/^[-–—*\s]$/即仅由-、–、—、*或空白组成的名称会被视为分割线。如需自定义可向组件传入dividerPatternprop类型为RegExp。actions对象封装了add、switch、rename、delete、move五个操作每个操作在调用编辑器方法后会向上 emit 对应事件add、switch、rename、delete、move方便父级做额外的埋点、确认弹窗或撤销逻辑。usePageList()组合式函数见 usePageList.ts是组件的底层实现它通过useEditor()获取编辑器实例用useSceneComputed(() editor.graph.getPages())保持页面列表与场景图响应式同步并用computed(() editor.state.currentPageId)跟踪当前页面。如果你不想用组件也可以直接用这个 composable 手写整个列表。图层树LayerTreeRoot 与 useLayerTree图层树比页面列表复杂得多要处理嵌套结构、展开/折叠、多选含 Shift 范围选择、拖拽排序、可见性/锁定切换、行内重命名以及和画布选中状态的互相联动。这些逻辑全部封装在LayerTreeRoot中。组件用法文档给出的示例是把数据交给一个通用的TreeView组件渲染LayerTreeRoot v-slot{ items, selectedIds, select, toggleExpand, getKey, getChildren } TreeView :itemsitems :selected-idsselectedIds :get-keygetKey :get-childrengetChildren selectselect toggle-expandtoggleExpand / /LayerTreeRoot插槽对外暴露的内容见 LayerTreeRoot.vue包括名称说明items当前页的图层树模型LayerNode[]只含非internalOnly的节点flattenItemsreka-uiTreeRoot拍平后的条目可用于虚拟滚动visibleRows展开后的可见行LayerRow[]带level与hasChildrenexpanded已展开节点的 ID 数组treeVersion树结构版本号结构变化时自增可用于驱动动画/缓存失效selectedIds当前选中节点 ID 的集合Setstringfocused树是否获得焦点draggingId/instruction/instructionTargetId拖拽状态被拖节点、拖拽指令reorder-above/reorder-below/make-child、目标节点actionsselect、toggleExpand、setFocused、setVirtualizer等操作集合getKey返回节点 IDgetChildren返回子节点数组这两个函数直接提供给底层的 reka-uiTreeRoot使用。树模型是如何构建的图层树数据来源于场景图SceneGraph构建逻辑在 model.ts 中buildLayerTreeModel(graph, parentId)从当前页面节点开始递归遍历childIds把每个SceneNode映射为LayerNode包含id、name、type、layoutMode、visible、locked跳过internalOnly节点同时建立byId索引以便快速查找visibleLayerRows(items, expandedIds)按展开状态把嵌套树拍平成LayerRow[]level从 1 开始这是虚拟滚动和选区计算的基础patchLayerNode(target, source)局部更新单个节点的可见属性名称、类型、布局模式、可见性、锁定避免每次属性变化都重建整棵树layerSelectionForTarget(visibleIds, currentIds, anchorId, targetId, mode)实现单点选、Ctrl/Cmd 加选/反选、Shift 范围选择的核心算法。LayerNode与LayerRow的类型定义见 context.ts。与编辑器事件的联动LayerTreeRoot在挂载时订阅了编辑器的一批事件LayerTreeRoot.vue这是它“与画布永远同步”的关键graph:replaced、page:changed→ 立即整体重建树node:created、node:deleted、node:reparented、node:reordered→ 通过queueMicrotask合并重建scheduleTreeRebuild避免连续多次变更反复渲染node:updated→ 只对命中PATCHABLE_NODE_KEYSname、type、layoutMode、visible、locked的属性做局部 patchselection:changed→ 自动展开选中节点的祖先、滚动到选中节点expandSelectionAncestorsscrollToNode。反向联动也成立点击树中节点时select()会把选择同步回editor.select([...next])并调用syncCanvasScope()自动进入包含该节点的容器保证画布与图层树视角一致。拖拽、可见性与重命名LayerTreeRoot内置了拖拽重排与层级调整能力实现在 useLayerDrag.ts通过setupDrag注册拖拽指令支持“插入上方 / 插入下方 / 成为子节点”三种结果即LayerDragInstruction。同时通过useLayerTree()见 context.ts可以在后代组件中拿到整个树上下文调用toggleVisibility(id)/toggleLock(id)切换节点可见性与锁定并 emit 事件供 UI 更新图标rename(id, name)行内重命名直接落到editor.renameNodesetRowRef(id, el)注册每行 DOM 引用用于滚动定位setVirtualizer(virtualizer)接入虚拟滚动scrollToIndex。配套的 LayerTreeItem.vue 提供了单行的默认骨架也可以完全自定义。选中状态useSelectionState图层树、属性面板、画布三者共享同一份选中状态。useSelectionState()selection-state/use.ts是对editor.state.selectedIds的响应式封装返回值包括名称类型说明selectedIdsSetstring当前选中的节点 ID 集合hasSelectionboolean是否至少选中一个节点selectedNode节点对象当前选中的主节点多选时取主节点selectedCountnumber选中数量selectedNodeTypestring \| null选中节点类型INSTANCE、COMPONENT、GROUP等isInstance/isComponent/isGroupboolean类型快捷判断canCreateComponentSetboolean是否可以把当前多选合并为组件集要求全部为COMPONENT且数量 ≥ 2典型场景属性面板根据selectedNodeType显示不同的编辑区工具栏根据isComponent决定是否显示“创建组件集”按钮。它和LayerTreeRoot插槽中的selectedIds来源一致因此树、画布、面板之间天然联动。常见布局与组合建议官方文档给出的面板布局建议为页面上方页面列表图层树在其下行内即可完成详情查看与重命名。一个典型的组合示例template aside classnav-panel PageListRoot v-slot{ pages, currentPageId, actions } ul li v-forpage in pages :keypage.id button clickactions.switch(page.id) :class{ active: page.id currentPageId } {{ page.name }} /button /li libutton clickactions.add() Nouvelle Page/button/li /ul /PageListRoot LayerTreeRoot v-slot{ visibleRows, selectedIds, actions } ul li v-forrow in visibleRows :keyrow.node.id :style{ paddingLeft: (row.level - 1) * 16 px } :class{ selected: selectedIds.has(row.node.id) } clickactions.select(row.node.id, false) {{ row.node.name }} /li /ul /LayerTreeRoot /aside /template要点visibleRows已按展开状态拍平直接v-for即可渲染无需自己递归缩进可以基于row.level计算组件默认indentPerLevel 16px可通过 prop 覆盖需要虚拟滚动时用setVirtualizer接入并配合flattenItems渲染行内重命名可参考 SDK 的useInlineRename相关封装文档在双击行时进入编辑态并调用actions.rename。相关 API 与进一步阅读usePageList页面列表组合式函数PageListRoot页面列表无样式组件LayerTreeRoot图层树无样式根组件LayerTreeItem图层树单行骨架useLayerTree在子组件中访问树上下文useSelectionState选中状态组合式函数。实现层面可直接阅读 packages/vue/src/primitives/PageList 与 packages/vue/src/primitives/LayerTree 两个目录的源码SDK 的整体结构与“无样式组件”的设计动机可参考 packages/vue/ARCHITECTURE.md 和 packages/vue/README.md。赞分享前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载相关推荐OpenPencil 导航面板开发指南用 PageListRoot、LayerTreeRoot 构建页面与图层面板OpenPencil 导航面板开发指南用 PageListRoot、LayerTreeRoot 构建页面与图层面板 本文围绕 OpenPencil Vue S前端桌面应用AI 应用MCP 服务用 PageListRoot 构建无样式的页面导航面板OpenPencil Vue SDK 页面列表演示原语用 PageListRoot 构建无样式的页面导航面板OpenPencil Vue SDK 页面列表演示原语 PageListRoot 是 OpenPenci前端桌面应用AI 应用MCP 服务Open Pencil 的 LayerTreeRoot构建无样式可定制图层树面板的 SDK 组件指南Open Pencil 的 LayerTreeRoot构建无样式可定制图层树面板的 SDK 组件指南 LayerTreeRoot 是 Open Pencil前端桌面应用AI 应用MCP 服务上一篇8GB显存玩转影视级视频生成WanVideo_comfy开源模型重构创作流程下一篇Deep-Live-Cam 实时换脸快速上手指南一张照片十分钟开播创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表