LogicFlow 控制面板(Control)插件完全指南:从注册到自定义扩展
【免费下载链接】LogicFlowA flow chart editing framework focus on business customization. 专注于业务自定义的流程图编辑框架,支持实现脑图、ER图、UML、工作流等各种图编辑场景。项目地址: https://gitcode.com/GitHub_Trending/lo/LogicFlow
导读
本文围绕 LogicFlow 官方扩展包@logicflow/extension中内置的控制面板(Control)插件展开,讲解如何在画布右上角快速启用一个集放大、缩小、适应画布、撤销(undo)与重做(redo)于一体的工具栏,以及如何基于该插件的addItem/removeItemAPI 深度定制自己的控制项。读完本文,你将掌握 Control 插件的注册方式、内置五个控制项各自的底层实现原理、控制项的数据结构与事件绑定机制,并能把自定义业务按钮(如导航、导出、保存)无缝接入画布。
一、插件定位与整体架构
Control 是 LogicFlow 的官方扩展插件之一,源码位于 packages/extension/src/components/control/index.ts,并在 packages/extension/src/index.ts 中通过export * from './components/control'统一对外导出。
从源码结构看,Control是一个标准的 LogicFlow 插件类,具备三个特征:
- 插件标识:通过
static pluginName = 'control'声明插件名,这也是后续通过lf.extension.control访问实例时的挂载键; - 生命周期:实现
render(_: LogicFlow, domContainer: HTMLElement)与destroy(),前者在画布容器中插入控制面板 DOM,后者在插件重渲染或销毁时清理 DOM,避免重复挂载; - 实例注入:构造函数接收
{ lf }(LogicFlow.IExtensionProps),持有 LogicFlow 主实例引用,从而在点击控制项时直接调用lf.zoom()、lf.undo()等能力。
此外,控制面板的样式集中定义在 packages/extension/src/style/index.less(浅色/深色/彩色主题),使用时需要单独引入扩展包的样式文件。
二、快速启用:三行代码注册 Control
在创建 LogicFlow 实例之前,通过LogicFlow.use(Control)注册插件即可:
import LogicFlow from "@logicflow/core"; import { Control } from "@logicflow/extension"; import "@logicflow/extension/es/index.css"; LogicFlow.use(Control);注册完成后,LogicFlow 会在画布右上方自动渲染一个控制面板。面板定位由样式.lf-control决定(position: absolute; top: 0; right: 10px;),并带有半透明白色背景、圆角与阴影,flex-wrap: nowrap保证所有控制项横向排布、溢出时可横向滚动(详见 style/index.less)。
内置控制项一览
Control 插件默认内置以下五个控制项(完整定义见 control/index.ts):
| key | iconClass | 显示文本 | 触发的方法 | 说明 |
|---|---|---|---|---|
zoom-out | lf-control-zoomOut | 缩小 | this.lf.zoom(false) | 按内置刻度缩小流程图 |
zoom-in | lf-control-zoomIn | 放大 | this.lf.zoom(true) | 按内置刻度放大流程图 |
reset | lf-control-fit | 适应 | this.lf.resetZoom() | 恢复流程原有尺寸 |
undo | lf-control-undo | 上一步 | this.lf.undo() | 回到上一步 |
redo | lf-control-redo | 下一步 | this.lf.redo() | 移到下一步 |
其中zoom-out/zoom-in/reset的图标由 LESS 中对应的lf-control-zoomOut、lf-control-zoomIn、lf-control-fit类名以 base64 内联 SVG 背景图提供(见 style/index.less),因此面板不依赖任何外部图片资源。
文档原文另提供了一份同一结构的内置控制项代码(见 control.zh.md),与当前仓库源码一致;若你不喜欢这套 UI 或功能,完全可以直接基于 LogicFlow 提供的实例 API 自定义实现,相关 API 参考 逻辑流实例 API 文档。
三、内置控制项的底层实现原理
3.1 放大缩小与适应画布
zoom-out、zoom-in与reset三个控制项本质上是把lf实例方法映射为按钮点击事件。核心调用链如下:
this.lf.zoom(zoomSize, point):内部委托给graphModel.transformModel.zoom(),zoomSize支持传0~n之间的数字(小于 1 缩小、大于 1 放大),也支持传入true/false按内置刻度放大/缩小,方法返回缩放后的比例(见 LogicFlow.tsx);this.lf.resetZoom():委托给transformModel.resetZoom(),将图形缩放比例重置为默认(见 LogicFlow.tsx);- 若需要限制缩放范围,还可配合
lf.setZoomMiniSize(size)设置能缩放到的最小倍数(默认 0.2,参数范围为 0~1,见 LogicFlow.tsx)。
3.2 undo / redo 的可用状态联动
undo与redo两个控制项并非一直可点,而是会跟随画布历史记录状态自动在“可用 / 禁用”之间切换。这一机制的实现位于 control/index.ts:
switch (item.key) { case 'undo': this.lf.on('history:change', ({ data: { undoAble } }: any) => { itemContainer.className = undoAble ? NORMAL : DISABLED }) break case 'redo': this.lf.on('history:change', ({ data: { redoAble } }: any) => { itemContainer.className = redoAble ? NORMAL : DISABLED }) break default: itemContainer.className = NORMAL break }即:Control 插件订阅核心的history:change事件,事件载荷中的undoAble/redoAble字段(由 packages/core/src/history/index.ts 在每次历史记录变化时抛出)决定按钮的 className。禁用态使用lf-control-item disabled,样式上表现为filter: opacity(0.5)且pointer-events: none,用户无法点击(见 style/index.less)。
而真正执行回退/前进的逻辑在核心层:
lf.undo():先通过history.undoAble()判断是否可回退,随后取出历史快照、clearSelectElements()清空选中态,再调用graphModel.graphDataToModel(graphData)把图数据还原到画布(见 LogicFlow.tsx);lf.redo():对称地执行history.redoAble()判断与数据恢复(见 LogicFlow.tsx)。
3.3 主题适配
getControlTool()中通过const { themeMode } = this.lf.graphModel读取当前主题模式(default/dark/colorful),据此拼接容器类名lf-control-${themeMode}与条目类名lf-control-item-${themeMode},使控制面板与画布整体主题保持一致(见 control/index.ts)。
四、添加自定义控制项:addItem
Control 插件向lf.extension.control暴露了addItem(item: ControlItem)方法,用于向面板追加自定义按钮。ControlItem的完整结构定义如下(见 control/index.ts):
type ControlItem = { key: string // 唯一标识,removeItem 时依赖它定位 iconClass: string // 图标类名,样式表需提供背景图 title: string // 鼠标悬浮提示(渲染在 span.title 上) text: string // 按钮下方显示的文字 hideText?: boolean // 设为 true 时只渲染图标,不渲染文字 onClick?: (lf: LogicFlow, e: MouseEvent) => void onMouseEnter?: (lf: LogicFlow, e: MouseEvent) => void onMouseLeave?: (lf: LogicFlow, e: MouseEvent) => void }其中四个事件回调均以(lf, e)形式注入:lf为 LogicFlow 主实例,e为原始鼠标事件。以下示例为控制面板添加一个“导航”按钮——鼠标移入或点击时,通过lf.getPointByClient(ev.x, ev.y)将浏览器客户端坐标换算为画布 DOM 覆盖层坐标,并在对应位置弹出小地图:
lf.extension.control.addItem({ key: 'mini-map', iconClass: 'custom-minimap', title: '', text: '导航', onMouseEnter: (lf, ev) => { const position = lf.getPointByClient(ev.x, ev.y) lf.extension.miniMap.show( position.domOverlayPosition.x - 120, position.domOverlayPosition.y + 35, ) }, onClick: (lf, ev) => { const position = lf.getPointByClient(ev.x, ev.y) lf.extension.miniMap.show( position.domOverlayPosition.x - 120, position.domOverlayPosition.y + 35, ) }, })需要注意的渲染细节(见 control/index.ts):
addItem仅把新条目push进controlItems数组;面板 DOM 是在render()时基于该数组一次性构建的,因此新增控制项后需要触发插件重渲染(如重新创建画布或调用插件 render 流程)才能在界面上看到;- 条目会生成
<div class="lf-control-item">容器,内部由<i class="iconClass">(20×20 的背景图元素)与<span class="lf-control-text">文字构成; - 若设置
hideText: true(或省略),则只渲染图标,不显示文字;注意源码判断为isNil(item.hideText) || item.hideText !== true,即只有显式传true才会隐藏文字(见 control/index.ts); - 自定义条目的默认状态为
lf-control-item(可用态),不会被history:change事件劫持。
五、删除控制项:removeItem
lf.extension.control.removeItem(key)用于从面板移除指定控制项,参数key与添加时传入的key一一对应。例如移除上一节添加的导航按钮:
/** * @params key 需要删除的选项的key */ lf.extension.control.removeItem('mini-map')其实现为在controlItems数组中按key查找并splice删除,若找不到则返回null(见 control/index.ts)。同样的,删除后需要重新触发渲染流程,面板才会反映变化。基于这一机制,你可以在运行时按需组合面板内容——例如在只读模式下移除 undo/redo,或在演示模式下移除缩放按钮。
六、应用场景与延伸
Control 插件适合以下典型场景:
- 开箱即用的基础工具栏:仅需一次
LogicFlow.use(Control),即获得缩放、适应、撤销/重做能力,且 undo/redo 按钮会自动跟随历史记录禁用/启用,无需额外状态管理; - 结合其他扩展的复合操作:如上文示例所示,在
onClick中访问lf.extension.miniMap等其它插件实例,实现“控制面板驱动小地图/导航”等复合交互; - 业务动作注入:在
onClick回调里调用lf.getGraphData()等实例方法,即可把“保存”“导出”“校验”等业务能力以按钮形式暴露给用户,所有方法仍可参考 逻辑流实例 API 文档。
如需更完整的可运行示例,仓库还提供了扩展演示页与示例工程,例如 engine-browser-examples 中的扩展示例、feature-examples 中的扩展演示,可结合源码与本文对照阅读。若想深入了解历史记录、缩放变换等底层机制,可继续阅读 history 模块源码 与 TransformModel 相关实现。
【免费下载链接】LogicFlowA flow chart editing framework focus on business customization. 专注于业务自定义的流程图编辑框架,支持实现脑图、ER图、UML、工作流等各种图编辑场景。项目地址: https://gitcode.com/GitHub_Trending/lo/LogicFlow
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考