# 自定义插件 CustomPlugin
LogicFlow提供了很多的插件,但是这些插件都是一些具有普适性的插件,不一定都符合业务需求。这时候可以基于自己的业务场景进行自定义插件。
# 插件的基础格式
class PluginCls {
static pluginName = 'pluginName',
constructor({ lf, LogicFlow }) {
// do anything
}
render(lf, toolOverlay) {
// do anything
}
destroy() {
// do anythine
}
}
- 插件是一个类。
- 这个类有个静态属性
pluginName
用于标识插件的名称。同名的插件在初始化lf
实例的时候会覆盖。同时使用方可以通过lf.extension.插件名称
获取插件这个类的实例。 - 在初始化
lf
实例的时候,会同时初始化插件实例,此时会传入参数lf
和LogicFlow
。 - 在
lf
渲染完成后,会调用插件实例的render
方法(如有)。第二个参数domOverlay是表示LogicFlow
Dom层的节点。插件开发者可以直接在这个节点插入html内容。 destroy
是销毁插件是调用的方法。大多数情况下可以不写。
# 实现context-pad插件
下面实现一个context-pad
示例,向大家介绍如何定义符合自己业务的插件。context-pad
插件是一个点击节点后,在节点旁边出现可选的快捷操作,可以看做是左键点击出现的菜单。
# 增加插入选项方法
LogicFlow会将插件的实例以插件名称的形式挂载到lf.extension
上,这样我们在class
中的方法就可以用lf.extension.插件名称.插件方法
调用了。
class ContextPad {
/**
* 设置通用的菜单选项
*/
setContextMenuItems(items) {
this.commonMenuItems = items;
}
}
ContextPad.pluginName = "contextPad";
// 调用方法
lf.extension.contextPad.setContextMenuItems([
{
icon: "...",
callback: () => {}
}
])
# 监听节点被点击
在插件被初始化时,会将lf
以参数的形式传递给插件,这时可以利用lf
监听画布上发生的事件。
class ContextPad {
constructor({ lf }) {
lf.on("node:click", (data) => {
this.showContextPad(data)
})
}
showContextPad() {
// ...
}
}
# 在画布指定位置显示HTML内容
插件的render函数有两个参数,一个是lf
, 第二个参数是toolOverlay
, 也就是组件层。LogicFlow的画布是由多个图层组成,而组件层则是专门用来渲染自定义的组件。
LogicFlow的图分层

所以这里我们只需要将菜单插入到toolOverlay
, 然后将其菜单移动到对应的位置即可。
class ContextPad {
render(lf, toolOverlay) {
this.toolOverlay = toolOverlay;
}
createMenu () {
this.__menuDOM = document.createElement('div')
}
// 计算出菜单应该显示的位置(节点的右上角)
getContextMenuPosition() {
const data = this._activeData;
const Model = this.lf.graphModel.getElement(data.id);
let x;
let y;
if (Model.BaseType === "node") {
x = data.x + Model.width / 2;
y = data.y - Model.height / 2;
}
return this.lf.graphModel.transformModel.CanvasPointToHtmlPoint([x, y]);
}
showMenu () {
const [x, y] = this.getContextMenuPosition();
this.__menuDOM.style.display = "flex";
// 将菜单显示到对应的位置
this.__menuDOM.style.top = `${y}px`;
this.__menuDOM.style.left = `${x + 10}px`;
this.toolOverlay.appendChild(this.__menuDOM);
}
}