尧图精选

Craft.js 图层面板完全指南:使用 @craftjs/layers 构建 Photoshop 式节点管理界面

🕒 发布时间:2026/9/25 6:52:49 📁 来源:尧图网络
前端【免费下载链接】craft.js A React Framework for building extensible drag and drop page editors项目地址https://gitcode.com/gh_mirrors/cr/craft.js点击查看免费下载导读craftjs/layers是 Craft.js 官方提供的图层管理扩展包为页面编辑器带来类似 Photoshop 的图层面板体验以树状结构展示编辑器中的全部节点支持悬停高亮、点击选中、拖拽重排、展开/折叠以及直接双击重命名图层。本文以packages/layers/README.md为骨架结合 packages/layers/src 的源码实现与 site/docs/additional/layers.md 官方 API 文档完整讲解安装接入、Layers /配置、useLayerHook、自定义渲染组件与底层状态机原理读完即可在自己的 Craft.js 编辑器中落地一个可用的图层面板。什么是 craftjs/layerscraftjs/layers是 Craft.js 生态中面向“页面编辑器”场景的图层面板组件见 packages/layers/package.json 中的描述 “A Photoshop-like layers panel for your page editor”。它本身不依赖任何第三方 UI 库只要求宿主环境提供styled-components并且以craftjs/core的编辑器状态为唯一数据源。从源码结构看包内主要分为四块packages/layers/srcmanager/图层状态管理。LayerManagerProvider维护一个独立的图层 store通过useMethods暴露registerLayer、toggleLayer、setLayerEvent、setIndicator等动作layers/图层树的递归渲染。LayerContextProvider为每个节点建立上下文LayerNode递归渲染子树events/图层事件体系。LayerHandlers从核心编辑器事件处理器派生接管图层的 hover、选中与拖拽layers/DefaultLayer/开箱即用的默认渲染组件含头部、可编辑名称、隐藏按钮。安装与基础接入README 给出的安装命令同时安装craftjs/layers与其 peer 依赖styled-componentsyarn add craftjs/layers styled-components从 packages/layers/package.json 可以看到其依赖约束craftjs/core 0.2.0、react ^16.8.0 || ^17 || ^18 || ^19、styled-components 6.1运行时还依赖craftjs/utils与react-contenteditable后者用于图层名内联编辑。当前仓库中该包版本为0.2.7。接入方式非常简洁——将Layers /作为Editor的子组件即可README 给出了完整示例import React from react; import {Editor} from craftjs/core import {Layers} from craftjs/layers export default function App() { return ( div style{{margin: 0 auto, width: 800px}} Typography varianth5 aligncenterA super simple page editor/Typography Editor resolver{...} Layers / /Editor /div ); }Layers /会自动以根节点为起点把整个节点树渲染为图层列表。其入口实现位于 packages/layers/src/index.tsx内部由LayerManagerProvider包裹一个LayerContextProvider后者以ROOT_NODE作为初始id、depth 0启动整棵树的递归渲染——因此它必须位于Editor内部才能通过上下文拿到编辑器 store。图层数据结构Layer 与 LayerState图层面板的每个条目对应一个Layer对象定义见 packages/layers/src/interfaces.tsx属性类型含义idNodeId对应编辑器节点的唯一 iddomHTMLElement当前图层整体含头部与子层的 DOM由layer连接器绑定headingDomHTMLElement当前图层头部标题栏的 DOM由layerHeader连接器绑定expandedboolean是否展开控制子层是否可见eventLayerRefEvents事件标记包含selected与hovered两个布尔值整个图层面板的状态被组织为LayerState见 interfaces.tsxexport type LayerState { layers: RecordNodeId, Layer; events: RecordLayerEvents, NodeId | null { indicator: LayerIndicator; }; options: LayerOptions; };其中events记录当前选中/悬停的节点 idindicator保存拖拽时的放置指示器LayerIndicator在Indicator基础上增加了onCanvas: boolean标记用于区分“落在画布内”还是“落在图层列表内”。这些状态全部由 packages/layers/src/manager/actions.tsx 中的LayerMethods操作例如setLayerEvent会在切换选中/悬停目标时自动清理旧目标的标记setDOM通过layer/layerHeader连接器回填每个图层的 DOM 引用。配置项Layers /的 PropsLayers /接收的 props 类型为PartialLayerOptions见 packages/layers/src/index.tsx官方文档site/docs/additional/layers.md列出的可配置项如下Props类型说明expandRootOnLoad?boolean可选。启用后加载时根节点默认展开renderLayer?React.ElementType可选。指定每个图层条目如何渲染的自定义组件默认使用DefaultLayerexpandRootOnLoad 的生效逻辑该选项在 packages/layers/src/layers/LayerNode.tsx 中生效组件挂载时会记录shouldBeExpandedOnLoad expandRootOnLoad id ROOT_NODE随后在useEffect中调用toggleLayer(id)展开根节点。值得注意的是即使不设置该选项当你在画布中选中某个深层节点时面板也会自动展开其全部祖先层级——LayerNode会通过query.node(selected).ancestors(true).includes(id)判断当前节点是否为选中节点的祖先见 LayerNode.tsx这一联动行为来自useEditor对核心编辑器状态的收集。renderLayer 的默认值从 packages/layers/src/manager/LayerManagerProvider.tsx 可以看到store 初始化时options.renderLayer的默认值就是DefaultLayer外部传入的 options 会通过对象展开覆盖默认值options: { renderLayer: DefaultLayer, ...options, },LayerNode渲染时会用React.createElement(renderLayer, {}, children)创建每个图层条目并把递归生成的下层LayerContextProvider作为children传入见 LayerNode.tsx——因此自定义渲染组件只要负责展示自身再透传children即可保留树形结构。在自定义组件中读取图层状态useLayeruseLayer是图层面板的“组件侧”核心 Hook用于在自定义渲染组件内获取当前图层的数据与操作能力。官方文档site/docs/additional/layers.md给出其完整 API参数collector?: (layer: Layer) Collected——一个收集函数从对应的Layer对象中挑选需要的状态返回的收集值变化时组件才会重渲染底层经由useCollector实现见 packages/layers/src/layers/useLayer.tsx。返回值见 useLayer.tsx返回字段说明id当前图层的节点 iddepth当前图层在树中的深度根节点为 0children当前节点的后代节点 id 数组来自核心编辑器的query.node(id).descendants()actions.toggleLayer切换当前图层的展开状态connectors.layer绑定到整个图层条目的 DOM用于选中、悬停、拖拽connectors.drag绑定到可拖拽区域默认是图层头部用于拖拽重排connectors.layerHeader绑定到图层头部 DOM用于计算放置位置连接器的绑定方式与核心包一致在 JSX 的ref回调中调用例如ref{(dom) { layer(dom); }}。useLayer内部通过wrapConnectorHooks把LayerHandlers中的layer/drag/layerHeader三个处理器包装为可绑定形式见 useLayer.tsx。自定义图层渲染与默认组件族如果默认样式不满足需求可以通过renderLayer传入自定义组件。官方文档给出了最简用法——完全替换条目但复用默认头部const Layer () { return ( div DefaultLayerHeader / /div ) } const App () { return ( Editor Frame ... /Frame Layers renderLayer{Layer} / /Editor ) }为了便于二次开发官方文档声明了以下可复用组件导出自 packages/layers/src/layers/index.tsDefaultLayer /完整图层条目内部包含头部与子层容器。它通过useLayer收集hovered/expanded状态并通过query.node(id).isParentOfTopLevelNodes()判断自己是否是顶层画布的直接父级hasChildCanvases据此决定子层容器的缩进、圆角卡片样式与左侧连接线见 packages/layers/src/layers/DefaultLayer/DefaultLayer.tsxDefaultLayerHeader /图层头部自左向右依次是“隐藏/显示”眼睛图标、顶层画布链接指示图标、可编辑名称、展开箭头见 packages/layers/src/layers/DefaultLayer/DefaultLayerHeader.tsx。眼睛图标读取节点的data.hidden并调用核心动作actions.setHidden(id, !hidden)切换画布内元素的可见性顶层链接指示图标Linkedsvg仅在query.node(id).isTopLevelCanvas()为真时显示EditableLayerName内联编辑组件。用户双击名称后进入编辑态基于react-contenteditable输入内容通过核心动作actions.setCustom(id, (custom) custom.displayName e.target.value)持久化到节点数据的custom.displayName字段见 packages/layers/src/layers/DefaultLayer/EditableLayerName.tsx点击组件外部自动退出编辑。setCustom对应的核心实现在 packages/core/src/editor/actions.ts 附近。底层原理事件派生与拖拽放置图层面板并非独立子系统而是深度复用了核心编辑器的事件机制。LayerEventContextProvider通过useEventHandler()取得核心事件处理器再调用coreEventHandler.derive(LayerHandlers, { layerStore })派生出图层专用处理器见 packages/layers/src/events/LayerEventContextProvider.tsx。LayerHandlerspackages/layers/src/events/LayerHandlers.ts提供了三个连接器layer绑定整个条目。内部通过this.inherit(...)继承核心的select、hover、drag能力并额外监听mouseover/mouseleave来写入setLayerEvent(hovered, ...)同时监听dragover/dragenter借助核心查询editorStore.query.getDropPlaceholder(dragId, target, pos, nodesToDOM)计算精确的放置位置getDropPlaceholder的核心实现见 packages/core/src/editor/query.tsx其中nodesToDOM回调把节点映射为图层 DOM从而让画布上的放置计算也能复用图层布局还会识别“悬停在折叠的 Canvas 头部上下 10px 内”的情况把放置位置自动提升到父级 Canvas见 LayerHandlers.tslayerHeader绑定头部 DOM 并写入headingDom供指示器定位drag设置draggabletrue在dragstart记录被拖节点在dragend时若无错误则执行核心动作editorStore.actions.move(draggedElement, parentId, index (where after ? 1 : 0))完成重排见 LayerHandlers.ts。拖拽过程中RenderLayerIndicatorpackages/layers/src/events/RenderLayerIndicator.tsx会读取图层 store 的events.indicator根据onCanvas标记分两种情况渲染落在画布内时高亮目标图层整个头部区域边框样式落在列表内时在插入位置绘制一条 2px 的横线。颜色取自核心编辑器的query.getOptions()中的indicator.success/indicator.error即核心包indicator选项错误时显示为错误色LayerIndicator组件也直接使用useEditor的state.options.indicator读取同款颜色见 packages/layers/src/layers/LayerIndicator.tsx。小结craftjs/layers的价值在于把“节点树的展示与操作”从画布内抽象出来接入只需一步安装、一个组件扩展则围绕renderLayer、useLayer与默认组件族展开而选中联动、拖拽重排、放置指示等交互能力全部由LayerHandlers派生自核心事件系统保证图层面板与画布编辑状态始终同步。对于需要层级管理、批量结构调整或“大纲视图”的 Craft.js 编辑器而言这是官方推荐且实现完整的现成方案。赞分享前端【免费下载链接】craft.js A React Framework for building extensible drag and drop page editors项目地址https://gitcode.com/gh_mirrors/cr/craft.js点击查看免费下载相关推荐使用 craftjs/layers 为 Craft.js 页面编辑器构建 Photoshop 式图层面板使用 craftjs/layers 为 Craft.js 页面编辑器构建 Photoshop 式图层面板 导读 Craft.js 是一个用于构建可扩展拖拽式页前端FlashSpace终极指南3个技巧让你轻松掌握macOS极速工作区管理FlashSpace终极指南3个技巧让你轻松掌握macOS极速工作区管理 你是否经常在macOS的多个应用之间来回切换感到效率低下桌面混乱找不到需要的窗Kepler.gl 图层管理实战隐藏、编辑与删除图层Data Layers 面板完全指南Kepler.gl 图层管理实战隐藏、编辑与删除图层Data Layers 面板完全指南 图层Layer是 Kepler.gl 中一切数据可视化的基础数据可视化数据分析上一篇如何永久保存微信聊天记录WeChatMsg让你的珍贵对话永不丢失下一篇Ceph Messenger 网络层剖析与 ceph_perf_msgr 基准测试实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →