自从 LogicFlow 正式开源后,受到的关注比咱们想象的要多。在最开始打算要作 LogicFlow 的时候,咱们花了不少的精力去讨论要作一个什么样的流程可视化库。其中一个选择是基于现有的业务直接实现一个开箱即用,包括了全部的流程编辑库经常使用功能的库。可是最终仍是没有选择这样作,由于咱们当时的背景是:不一样的项目中,在流程图的外观、后台所需数据格式都存在较大的差别。 有些项目用的是 activity, 有些是某些团队自研的流程引擎。因此咱们须要作一个能支持各系统平滑迁移的流程可视化库,须要这个库足够的灵活,视觉上也要知足个各系统本身的风格,并且最好是流程图上的各类功能均可以自按需使用。javascript
咱们对于如何将 LogicFlow 实现成一个足够灵活的流程可视化库存在两种想法。一种是一切皆可配置,也就是配置化。这个是不少可视化库的作法,最典型的就是 ECharts,用过 ECharts 的人应该都知道,它的配置功能特别丰富,几乎能够作到配置任何图上的元素的效果,从而达到业务开发者须要的自定义效果。html
可是对于咱们来讲,配置化为了保持其提供足够的灵活性,咱们须要在内部维护太多的 UI 相关的逻辑。以一个节点为例:前端
若是是采用配置化的方式的话,开发者传入的配置大体是:java
{
type: 'rect',
icon: 'https://example-icon.com/settings.png',
text: '22\n33333',
}
复制代码
咱们就须要在内部代码中判断传入的参数是否有 icon,若是有,就在左上角显示 icon。可是有的流程但愿本身在左上角显示的是文本,咱们可能就要再增长一个字段 nodeText 来控制了。那若是咱们想显示一个图标在右边呢?想里面显示 3 列文本呢?node
总的来讲,配置化虽然对业务开发者足够友好,只须要文档足够完善,库内部兼容的效果足够多,就能够达到很好的效果。可是对于咱们来讲倒是须要付出很大的成本去实现各类效果,并且极可能由于一些其余状况,舍弃支持一些不经常使用的效果。从长远来看,这种配置化方案对咱们来讲仍是不够灵活的。git
另外一种方案就是插件化,就是将不断变化的非核心功能分散到插件中,避免其与核心代码耦合,保持其核心部分代码简洁和稳定。在插件化方案下,咱们就能够实现一个支持设置 icon 节点就行了,至于其它特殊需求的节点,就有用户本身利用自定义机制来实现便可。并且开放到社区后,其它开发者自定义的内容也能够当作一个插件,贡献到 LogicFlow 中来。github
插件化会带来不少好处:json
什么是插件?插件是在核心程序上遵循其提供出来的接口规范再次编写的出来的程序。插件是不能脱离核心程序单独存在的,是一种对核心程序功能的扩展。因此我的以为插件化最重要的一点就是核心程序的 API 健全性和稳定性。若是咱们的 API 不够完善,社区开发者是没法开发出符合其需求的插件;若是咱们的 API 变化很大,颇有可能致使以前开发的插件在咱们版本升级后就不能用了,会致使整个 LogicFlow 的社区生态混乱。微信
为了保证 API 的健全性和稳定性,咱们作了这些事情:markdown
若是咱们只提供表示这图编辑部分的@logicflow/core
,那么意味 LogicFlow 就是一个半成品,既不利于推广,也不利于上手使用。因此咱们将 LogicFlow 将非核心功能例如菜单、工具栏等组件; 各种特点形态节点; 一些常见的流程实际应用场景等都采用插件的方式实现放到了@logicflow/extension
包中。其中就有 bpmn-js 插件,这里我大体介绍一下 LogicFlow 是如何如何利用插件机制,去实现兼容 bpmn-js 的插件。
LogicFlow 自己只是一个单纯的流程图编辑器,不带有业务属性。为了更好的易用性,咱们提供了 Bpmn-js 插件,让使用 bpmn-js 的项目可以快速替换。有了 Bpmn 插件后,直接经过 LogicFlow 装载 bpmn 插件,这个页面就表现成为 bpmn-js 了。
import LogicFlow from '@logicflow/core';
import { Bpmn } from '@logicflow/extension';
LogicFlow.use(Bpmn);
复制代码
前面提到过,插件的扩展性是否强大,是看核心程序提供的 API 是否有足够的扩展性。LogicFlow 在绝大多数 API 上的设计,其目标就是支持的拓展能力。咱们在@logicflow/extension
中开发的插件,也是一种验证咱们 API 的方式。从下图能够看到LogicFlow 在支持拓展能力上的总体思路。
为了提升易用性,在节点方面,LogicFlow 内置了基础节点,而后在@logicflow/extension
中也实现了一些特殊节点。开发者在实际使用中,能够基于这些基础节点和特殊节点进行自定义知足其业务需求的节点。
@logicflow/core
内部有一个 BaseNode 抽象类,这个类中实现了流程图中节点所需的绝大部分逻辑,例如节点拖动、点击等事件处理和连线处理等。同时也有获取节点外观属性、获取节点基础属性、获取节点配置自定义属性等能够被子类重写的方法。@logicflow/extension
中提供了更多的节点。例如圆柱体(CylinderNode)、带有图标的矩形(RectIconNode)等。@logicflow/extension
中的节点),采用继承重写对应的方法,实现本身业务需求的节点。一样,开发者本身自定义的节点也能够成为插件,开源到社区中。后续咱们会增长 LogicFlow 的插件市场,到时你们能够自由选择本身项目所需的节点。在某些时候,咱们可能须要控制连线的链接方式,好比 A 节点不能做为连线的起点、B 节点不能做为连线的终点、C 节点后面必须是 A 节点等等。LogicFlow 提供了自定义节点规则功能来实现这个需求。
LogicFlow 内部有getConnectedSourceRules
和getConnectedTargetRules
两个公共方法,分别返回当前节点做为连线开始点和做为链接目标点时的校验规则。当在面板上进行连线操做的时候,会判断全部的规则是否经过,只有经过了才能链接。
class CnodeModel extends RectModel {
/* ignore other code*/
// 判断这个节点的下一个节点是否符合自定义要求
getConnectedSourceRules(): ConnectRule[] {
const rules = super.getConnectedSourceRules();
const gateWayOnlyAsTarget = {
message: 'C节点下一个节点只能是A节点',
validate: (source: BaseNode, target: BaseNode) => {
let isValid = true;
if (target.type !== 'a-node ') {
isValid = false;
}
return isValid;
},
};
rules.push(gateWayOnlyAsTarget);
return rules;
}
// 判断这个节点的上一个节点是否符合自定义要求
getConnectedTargetRules() {}
}
复制代码
自定义连线方案和自定义节点基本一致,由基础连线实现线的绝大部分逻辑,而后在内置连线中实现连线的特殊交互处理,最后再由开发者基于内置连线进行自定义开发。固然,因为绝大多数图编辑上线的表现形式都只有直线、折线和曲线三种形式,因此通常开发者自定义连线都是改变一下样式(颜色、虚线)和名字(如Bpmn中连线叫作bpmn:sequenceFlow
)。
通常来讲,对于一个节点,咱们只须要type
、x
、y
、text
就能够完整的图中的一个节点的全部可见信息了。type
控制这个节点的类型,x
、y
控制着节点所处的位置,text
控制着节点上的文本。 可是在实际使用中,咱们可能须要将更多的带有业务性质的属性放到节点上,而后在基于这些业务属性,在节点显示的作出对应处理。例如在流程中,咱们须要将某些节点高亮,表示这些节点正处于异常状态。
LogicFlow 中提供了一个properties
字段用于开发者存放本身业务相关的属性,而后能够在自定义节点的时候,基于这些properties
本身进行处理。
lf.register('custom-process', ({TriangleNode,TriangleModel }) => {
class CustomProcessNode extends TriangleNode {
static extendKey = 'CustomProcessNode';
getShapeStyle() {
const attributes = super.getShapeStyle();
const properties = super.getProperties();
// 判断自定义属性customStatus是否为error,
// 若是是,则将这个节点的填充颜色设置为红色。
if (properties.customStatus === 'error') {
attributes.fill = 'red'
}
return attributes;
}
}
return {
view: CustomProcessNode,
model: PolygonNodeModel,
};
});
复制代码
上面的代码自定义了一个 custom-process 节点,当传入的数据中节点 type 为 custom-process,节点属性中 customStatus 为 error 的时候,流程图上显示的就是一个红色的三角形。
在 LogicFlow 中,除了节点和连线这种由 svg 渲染的图形外,还存在着一些用于图编辑过程当中进行控制的组件,这些组件 LogicFlow 是经过 html 来实现的(好比菜单、控制面板等)。LogicFlow 开放了在图上插入 DOM 的能力,开发者就能够基于这个能力来实现自定义组件。
有了在图上自由插件 DOM 的能力,咱们就能够作不少事情了,好比能够实现一个自由调整节点颜色、字体大小的工具。这个工具的开发就只须要按照咱们正常前端开发便可。而后在监听到用户选中节点后,将这个 DOM 插入到节点对应的位置旁边。
上面咱们提到过能够用自定义节点来定制任何节点的外观,可是对每一个节点都单独自定义一次太多麻烦。LogicFlow 提供了主题功能,来统一设置因此节点的外观基础属性。好比咱们想让全部的矩形都不带边框。
lf.setTheme({
rect: {
strokeWidth: 0
},
})
复制代码
主题除了能够设置节点和连线的外观之外,还能够设置内部功能的样式,好比文本、对齐线等。
经过上面的介绍,你们对 LogicFlow 的拓展机制应该有了必定的了解。LogicFlow 自己不是一个专门处理某个场景的流程设计工具,而是一个流程图编辑库。大多数状况下,拓展性强就意味着没法开箱即用,为了让 LogicFlow 成为一个开箱即用的库,LogicFlow 采用了插件化的机制,经过插件,将场景限定到实际业务场景中来。
LogicFlow 仍是一个很新的开源项目,提供的插件还不够丰富,也存在业务场景考虑不周的状况,欢迎你们在 github 上提 issue,咱们必定会认真对待每个 issue!LogicFlow 也在寻找 contributor ,若是你感兴趣的话,欢迎一块儿来共建!
更多阅读资料: