建 Photoshop 式節(jié)點管理界面)
前端【免費下載鏈接】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 的圖層面板體驗以樹狀結(jié)構(gòu)展示編輯器中的全部節(jié)點支持懸停高亮、點擊選中、拖拽重排、展開/折疊以及直接雙擊重命名圖層。本文以packages/layers/README.md為骨架結(jié)合 packages/layers/src 的源碼實現(xiàn)與 site/docs/additional/layers.md 官方 API 文檔完整講解安裝接入、Layers /配置、useLayerHook、自定義渲染組件與底層狀態(tài)機原理讀完即可在自己的 Craft.js 編輯器中落地一個可用的圖層面板。什么是 craftjs/layerscraftjs/layers是 Craft.js 生態(tài)中面向“頁面編輯器”場景的圖層面板組件見 packages/layers/package.json 中的描述 “A Photoshop-like layers panel for your page editor”。它本身不依賴任何第三方 UI 庫只要求宿主環(huán)境提供styled-components并且以craftjs/core的編輯器狀態(tài)為唯一數(shù)據(jù)源。從源碼結(jié)構(gòu)看包內(nèi)主要分為四塊packages/layers/srcmanager/圖層狀態(tài)管理。LayerManagerProvider維護一個獨立的圖層 store通過useMethods暴露registerLayer、toggleLayer、setLayerEvent、setIndicator等動作layers/圖層樹的遞歸渲染。LayerContextProvider為每個節(jié)點建立上下文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后者用于圖層名內(nèi)聯(lián)編輯。當前倉庫中該包版本為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 /會自動以根節(jié)點為起點把整個節(jié)點樹渲染為圖層列表。其入口實現(xiàn)位于 packages/layers/src/index.tsx內(nèi)部由LayerManagerProvider包裹一個LayerContextProvider后者以ROOT_NODE作為初始id、depth 0啟動整棵樹的遞歸渲染——因此它必須位于Editor內(nèi)部才能通過上下文拿到編輯器 store。圖層數(shù)據(jù)結(jié)構(gòu)Layer 與 LayerState圖層面板的每個條目對應一個Layer對象定義見 packages/layers/src/interfaces.tsx屬性類型含義idNodeId對應編輯器節(jié)點的唯一 iddomHTMLElement當前圖層整體含頭部與子層的 DOM由layer連接器綁定headingDomHTMLElement當前圖層頭部標題欄的 DOM由layerHeader連接器綁定expandedboolean是否展開控制子層是否可見eventLayerRefEvents事件標記包含selected與hovered兩個布爾值整個圖層面板的狀態(tài)被組織為LayerState見 interfaces.tsxexport type LayerState { layers: RecordNodeId, Layer; events: RecordLayerEvents, NodeId | null { indicator: LayerIndicator; }; options: LayerOptions; };其中events記錄當前選中/懸停的節(jié)點 idindicator保存拖拽時的放置指示器LayerIndicator在Indicator基礎上增加了onCanvas: boolean標記用于區(qū)分“落在畫布內(nèi)”還是“落在圖層列表內(nèi)”。這些狀態(tài)全部由 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可選。啟用后加載時根節(jié)點默認展開renderLayer?React.ElementType可選。指定每個圖層條目如何渲染的自定義組件默認使用DefaultLayerexpandRootOnLoad 的生效邏輯該選項在 packages/layers/src/layers/LayerNode.tsx 中生效組件掛載時會記錄shouldBeExpandedOnLoad expandRootOnLoad id ROOT_NODE隨后在useEffect中調(diào)用toggleLayer(id)展開根節(jié)點。值得注意的是即使不設置該選項當你在畫布中選中某個深層節(jié)點時面板也會自動展開其全部祖先層級——LayerNode會通過query.node(selected).ancestors(true).includes(id)判斷當前節(jié)點是否為選中節(jié)點的祖先見 LayerNode.tsx這一聯(lián)動行為來自useEditor對核心編輯器狀態(tài)的收集。renderLayer 的默認值從 packages/layers/src/manager/LayerManagerProvider.tsx 可以看到store 初始化時options.renderLayer的默認值就是DefaultLayer外部傳入的 options 會通過對象展開覆蓋默認值options: { renderLayer: DefaultLayer, ...options, },LayerNode渲染時會用React.createElement(renderLayer, {}, children)創(chuàng)建每個圖層條目并把遞歸生成的下層LayerContextProvider作為children傳入見 LayerNode.tsx——因此自定義渲染組件只要負責展示自身再透傳children即可保留樹形結(jié)構(gòu)。在自定義組件中讀取圖層狀態(tài)useLayeruseLayer是圖層面板的“組件側(cè)”核心 Hook用于在自定義渲染組件內(nèi)獲取當前圖層的數(shù)據(jù)與操作能力。官方文檔site/docs/additional/layers.md給出其完整 API參數(shù)collector?: (layer: Layer) Collected——一個收集函數(shù)從對應的Layer對象中挑選需要的狀態(tài)返回的收集值變化時組件才會重渲染底層經(jīng)由useCollector實現(xiàn)見 packages/layers/src/layers/useLayer.tsx。返回值見 useLayer.tsx返回字段說明id當前圖層的節(jié)點 iddepth當前圖層在樹中的深度根節(jié)點為 0children當前節(jié)點的后代節(jié)點 id 數(shù)組來自核心編輯器的query.node(id).descendants()actions.toggleLayer切換當前圖層的展開狀態(tài)connectors.layer綁定到整個圖層條目的 DOM用于選中、懸停、拖拽connectors.drag綁定到可拖拽區(qū)域默認是圖層頭部用于拖拽重排connectors.layerHeader綁定到圖層頭部 DOM用于計算放置位置連接器的綁定方式與核心包一致在 JSX 的ref回調(diào)中調(diào)用例如ref{(dom) { layer(dom); }}。useLayer內(nèi)部通過wrapConnectorHooks把LayerHandlers中的layer/drag/layerHeader三個處理器包裝為可綁定形式見 useLayer.tsx。自定義圖層渲染與默認組件族如果默認樣式不滿足需求可以通過renderLayer傳入自定義組件。官方文檔給出了最簡用法——完全替換條目但復用默認頭部const Layer () { return ( div DefaultLayerHeader / /div ) } const App () { return ( Editor Frame ... /Frame Layers renderLayer{Layer} / /Editor ) }為了便于二次開發(fā)官方文檔聲明了以下可復用組件導出自 packages/layers/src/layers/index.tsDefaultLayer /完整圖層條目內(nèi)部包含頭部與子層容器。它通過useLayer收集hovered/expanded狀態(tài)并通過query.node(id).isParentOfTopLevelNodes()判斷自己是否是頂層畫布的直接父級hasChildCanvases據(jù)此決定子層容器的縮進、圓角卡片樣式與左側(cè)連接線見 packages/layers/src/layers/DefaultLayer/DefaultLayer.tsxDefaultLayerHeader /圖層頭部自左向右依次是“隱藏/顯示”眼睛圖標、頂層畫布鏈接指示圖標、可編輯名稱、展開箭頭見 packages/layers/src/layers/DefaultLayer/DefaultLayerHeader.tsx。眼睛圖標讀取節(jié)點的data.hidden并調(diào)用核心動作actions.setHidden(id, !hidden)切換畫布內(nèi)元素的可見性頂層鏈接指示圖標Linkedsvg僅在query.node(id).isTopLevelCanvas()為真時顯示EditableLayerName內(nèi)聯(lián)編輯組件。用戶雙擊名稱后進入編輯態(tài)基于react-contenteditable輸入內(nèi)容通過核心動作actions.setCustom(id, (custom) custom.displayName e.target.value)持久化到節(jié)點數(shù)據(jù)的custom.displayName字段見 packages/layers/src/layers/DefaultLayer/EditableLayerName.tsx點擊組件外部自動退出編輯。setCustom對應的核心實現(xiàn)在 packages/core/src/editor/actions.ts 附近。底層原理事件派生與拖拽放置圖層面板并非獨立子系統(tǒng)而是深度復用了核心編輯器的事件機制。LayerEventContextProvider通過useEventHandler()取得核心事件處理器再調(diào)用coreEventHandler.derive(LayerHandlers, { layerStore })派生出圖層專用處理器見 packages/layers/src/events/LayerEventContextProvider.tsx。LayerHandlerspackages/layers/src/events/LayerHandlers.ts提供了三個連接器layer綁定整個條目。內(nèi)部通過this.inherit(...)繼承核心的select、hover、drag能力并額外監(jiān)聽mouseover/mouseleave來寫入setLayerEvent(hovered, ...)同時監(jiān)聽dragover/dragenter借助核心查詢editorStore.query.getDropPlaceholder(dragId, target, pos, nodesToDOM)計算精確的放置位置getDropPlaceholder的核心實現(xiàn)見 packages/core/src/editor/query.tsx其中nodesToDOM回調(diào)把節(jié)點映射為圖層 DOM從而讓畫布上的放置計算也能復用圖層布局還會識別“懸停在折疊的 Canvas 頭部上下 10px 內(nèi)”的情況把放置位置自動提升到父級 Canvas見 LayerHandlers.tslayerHeader綁定頭部 DOM 并寫入headingDom供指示器定位drag設置draggabletrue在dragstart記錄被拖節(jié)點在dragend時若無錯誤則執(zhí)行核心動作editorStore.actions.move(draggedElement, parentId, index (where after ? 1 : 0))完成重排見 LayerHandlers.ts。拖拽過程中RenderLayerIndicatorpackages/layers/src/events/RenderLayerIndicator.tsx會讀取圖層 store 的events.indicator根據(jù)onCanvas標記分兩種情況渲染落在畫布內(nèi)時高亮目標圖層整個頭部區(qū)域邊框樣式落在列表內(nèi)時在插入位置繪制一條 2px 的橫線。顏色取自核心編輯器的query.getOptions()中的indicator.success/indicator.error即核心包indicator選項錯誤時顯示為錯誤色LayerIndicator組件也直接使用useEditor的state.options.indicator讀取同款顏色見 packages/layers/src/layers/LayerIndicator.tsx。小結(jié)craftjs/layers的價值在于把“節(jié)點樹的展示與操作”從畫布內(nèi)抽象出來接入只需一步安裝、一個組件擴展則圍繞renderLayer、useLayer與默認組件族展開而選中聯(lián)動、拖拽重排、放置指示等交互能力全部由LayerHandlers派生自核心事件系統(tǒng)保證圖層面板與畫布編輯狀態(tài)始終同步。對于需要層級管理、批量結(jié)構(gòu)調(diào)整或“大綱視圖”的 Craft.js 編輯器而言這是官方推薦且實現(xiàn)完整的現(xiàn)成方案。贊分享前端【免費下載鏈接】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 頁面編輯器構(gòu)建 Photoshop 式圖層面板使用 craftjs/layers 為 Craft.js 頁面編輯器構(gòu)建 Photoshop 式圖層面板 導讀 Craft.js 是一個用于構(gòu)建可擴展拖拽式頁前端FlashSpace終極指南3個技巧讓你輕松掌握macOS極速工作區(qū)管理FlashSpace終極指南3個技巧讓你輕松掌握macOS極速工作區(qū)管理 你是否經(jīng)常在macOS的多個應用之間來回切換感到效率低下桌面混亂找不到需要的窗Kepler.gl 圖層管理實戰(zhàn)隱藏、編輯與刪除圖層Data Layers 面板完全指南Kepler.gl 圖層管理實戰(zhàn)隱藏、編輯與刪除圖層Data Layers 面板完全指南 圖層Layer是 Kepler.gl 中一切數(shù)據(jù)可視化的基礎數(shù)據(jù)可視化數(shù)據(jù)分析上一篇如何永久保存微信聊天記錄WeChatMsg讓你的珍貴對話永不丟失下一篇Ceph Messenger 網(wǎng)絡層剖析與 ceph_perf_msgr 基準測試實戰(zhàn)指南創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考