详解《基于 javascript 的流程图编辑框架LogicFlow》

您所在的位置:网站首页 前端怎么画流程图 详解《基于 javascript 的流程图编辑框架LogicFlow》

详解《基于 javascript 的流程图编辑框架LogicFlow》

2023-06-01 10:00| 来源: 网络整理| 查看: 265

1、LogicFlow 是什么

LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow 支持前端研发自定义开发各种逻辑编排场景,如流程图、ER 图、BPMN 流程等。在工作审批配置、机器人逻辑编排、无代码平台流程配置都有较好的应用。 在这里插入图片描述 目前,LogicFlow 已经支持了客服业务下 IVR、工单流转、智能机器人等多个运营系统,在各系统不同的流程配置需求中得到了验证。

2、LogicFlow 的能力和特性 2.1、快速搭建流程图编辑器

提供了一个流程图编辑所必需的各项能力,这也是 LogicFlow 的基础能力:

图的绘制能力。基于 SVG 来绘制形状各异的节点和线,并提供了基础的节点(矩形、圆形、多边形等)和线(直线、折线、曲线)各类交互能力,让图动起来。根据节点、线、图的各类鼠标事件(hover、点击、拖拽等)做出反应。比如节点拖拽、拖拽创建边、线的调整、双击节点编辑文本等提升编辑效率的能力。提供网格、对齐线,上一步、下一步,键盘快捷键,图放大缩小等配套能力,帮助用户提升编辑效率提供了丰富的 API ,宿主研发通过 API 传参调用和监听事件的方式,与 LogicFlow 完成交互 通过以上能力,前端研发可以低成本、快速的搭建起流程编辑的应用,提供流畅的产品交互。下面是通过 LogicFlow 内置的节点和配套能力,做的流程图示例:请添加图片描述 2.2、基于业务场景拓展

当基础能力无法满足业务需求的时候,便需要基于业务场景拓展。这也是 LogicFlow 能支持客服侧多个系统的关键所在。

设置图上所有元素的样式,比如各种节点、线、锚点、箭头、对齐线的大小颜色等,满足对前端样式调整的需求API 拓展。支持在 LogicFlow 上注册自定义的方法,比如通过 API 拓展提供图片下载的方法自定义节点、线。内置的矩形、圆形等图形类节点往往无法满足实际的业务需求,需要定义具有业务意义的节点。LogicFlow 提供了 的方式让用户定制具有自定义图形、业务数据的节点,比如流程审批场景中的 “审批” 节点拓展组件。LogicFlow 在 SVG 图层上提供了 HTML 层和一系列坐标转换逻辑,并支持在 HTML 层注册组件。宿主研发可以通过 LogicFlow 的 API,基于任何 View 框架开发组件,比如节点的右键菜单、控制面板等数据转换 adapter。LogicFlow 默认导出的图数据不一定适合所有业务,此时可以通过 adapter API,在图数据从 LogicFlow 输入、输出的时候做自定义转换,比如转换成 BPMN 规范的图数据内置部分拓展能力。基于上述拓展能力,我们还单独提供了 extension 的包,用来存放客服业务下沉淀出的具有通用性的节点、组件等,比如面向 BPMN 规范的节点和数据 adapter,默认菜单。注意 extension 可以单独安装,并支持按需引入。

基于上述拓展的能力,前端研发能够根据实际业务场景的需求,灵活的开发出所需的节点、组件等。下面有两个基于 LogicFlow 拓展能力做出的流程图:

BPMN: http://logic-flow.org/examples/#/extension/bpmn

请添加图片描述 审批流程:http://logic-flow.org/examples/#/extension/approve 请添加图片描述

3、安装使用 3.1、使用 npm 引入 npm install @logicflow/core npm install @logicflow/extension 3.2、绘制一个简单的流程图 import LogicFlow from "@logicflow/core"; import "@logicflow/core/dist/style/index.css"; const lf = new LogicFlow({ container: document.querySelector("#app"), grid: true, }); lf.render({ nodes: [ { id: "1", type: "rect", x: 100, y: 100, text: "节点1", }, { id: "2", type: "circle", x: 300, y: 200, text: "节点2", }, ], edges: [ { sourceNodeId: "1", targetNodeId: "2", type: "polyline", text: "连线", }, ], }); 3.3、在 vue项目中使用 logicflow

注意:初始化 LogicFlow 实例的时候,传入的参数 container,必须要 dom 上存在这个节点,不然会报错请检查 container 参数是否有效。

import LogicFlow from "@logicflow/core"; import "@logicflow/core/dist/style/index.css"; export default { mounted() { this.lf = new LogicFlow({ container: this.$refs.container, grid: true, }); this.lf.render({ nodes: [ { id: "1", type: "rect", x: 100, y: 100, text: { x: 100, y: 100, value: "节点1" }, }, { id: "2", type: "circle", x: 300, y: 200, text: { x: 300, y: 200, value: "节点2" }, }, ], edges: [ { sourceNodeId: "1", targetNodeId: "2", type: "polyline", }, ], }); }, }; .container { width: 1000px; height: 500px; }

效果: 在这里插入图片描述

4、核心功能 4.1、LogicFlow 实例 创建一个实例 每一个流程设计界面,就是一个 LogicFlow 的实例。为了统一术语,我们后面统一在代码层面将LogicFlow的实例写作lf。 #container { width: 1000px; height: 500px; } const lf = new LogicFlow({ container: document.querySelector("#container"), });

当创建一个实例的时候,我们需要传递初始化 LogicFlow 实例的配置项。LogicFlow 支持非常丰富的初始化配置项,但是只有 LogicFlow 画布初始化时挂载的 DOM 节点container参数是必填的。完整的配置项参见 LogicFlow API。

LogicFlow 的图数据

在 LogicFlow 里面,我们把流程图看做是由节点和连线组成的图。所以我们采用如下数据结构来表示 LogicFlow 的图数据。

const graphData = { nodes: [ { id: "node_id_1", type: "rect", x: 100, y: 100, text: { x: 100, y: 100, value: "节点1" }, properties: {}, }, { id: "node_id_2", type: "circle", x: 200, y: 300, text: { x: 300, y: 300, value: "节点2" }, properties: {}, }, ], edges: [ { id: "edge_id", type: "polyline", sourceNodeId: "node_id_1", targetNodeId: "node_id_2", text: { x: 139, y: 200, value: "连线" }, startPoint: { x: 100, y: 140 }, endPoint: { x: 200, y: 250 }, pointsList: [ { x: 100, y: 140 }, { x: 100, y: 200 }, { x: 200, y: 200 }, { x: 200, y: 250 }, ], properties: {}, }, ], };

为什么节点文本还要有坐标,直接用节点的坐标不行吗?

text是可以直接用字符串,这个时候,如果是节点的文本,我们会自动采用节点坐标作为节点文本坐标,如果是连接文本,我们会基于不同的连线类型计算一个合适的坐标作为节点坐标。 在有些应用场景下,我们文本是可以拖动的,为了保持一致,我们 LogicFlow 导出的文本数据都会带上坐标。

连线 startPoint、endPoint 数据和 pointsList 为什么是重复的?

目前,在 LogicFlow 内部内置了line, polyline, bezier三种基础连线,这三种连线都有startPoint、endPoint数据。但是其中line导出的数据是不会带上pointsList。对于polyline, pointsList表示折线所有的点。对于bezier,pointsList表示[‘起点’, ‘第一个控制点’,‘第二个控制点’, ‘终点’]。

properties 是用来做什么的? properties 的 LogicFlow 保留给具体业务场景使用的数据。

例如:在审批流场景,我们定义某个节点,这个节点通过了,节点为绿色,不通过节点为红色。那么节点的数据描述可以为:

{ type: 'apply', properties: { isPass: true } }

type 的含义是什么?

type 表示节点或者连线的类型,这里的类型不仅可以是rect,polyline这种 LogicFlow 内置的基础类型,也可以是用户基于基础类型自定义的类型。

将图数据渲染到画布上 lf.render(graphData); 4.2、节点 Node

LogicFlow 的内置了一些基础节点,开发者在实际应用场景中,可以基于这些基础节点,定义符合自己业务逻辑的节点。

认识 LogicFlow 的基础节点 LogicFlow 是基于 svg 做的流程图编辑框架,所以我们的节点和连线都是 svg 基本形状,对 LogicFlow 节点样式的修改,也就是对 svg 基本形状的修改。LogicFlow 内部存在 7 种基础节点,分别为:

矩形:rect圆形: circle椭圆: ellipse多边形: polygon菱形: diamond文本: textHTML: html 4.3、边 Edge

和节点一样,LogicFlow 也内置一些基础的边。LogicFlow 的内置边包括:

直线(line)直角折线(polyline)贝塞尔曲线(bezier) 4.4、主题 Theme

LogicFlow 提供了设置主题的方法,便于用户统一设置其内部所有元素的样式。 设置方式有两种:

初始化LogicFlow时作为配置传入初始化后,调用LogicFlow的 setTheme 方法 4.5、事件 Event

当我们使用鼠标或其它方式与画布交互时,会触发的对应的事件。通过监听这些事件,可以获取其在触发时所产生的数据,根据这些数据来实现需要的功能。详细可监听事件见事件 API

监听事件 lf实例上提供on方法支持监听事件。 lf.on("node:dnd-add", (data) => {});

LogicFlow 支持用逗号分割事件名。

lf.on("node:click,edge:click", (data) => {}); 自定义事件 除了 lf 上支持的监听事件外,还可以使用eventCenter对象来监听和触发事件。eventCenter是一个graphModel上的一个属性。所以在自定义节点的时候,我们可以使用eventCenter触发自定义事件。 class ButtonNode extends HtmlNode { setHtml(rootEl) { const { properties } = this.props.model; const el = document.createElement("div"); el.className = "uml-wrapper"; const html = ` Head + ${properties.name} ${properties.body} setHead(Head $head) setBody(Body $body) `; el.innerHTML = html; rootEl.innerHTML = ""; rootEl.appendChild(el); window.setData = () => { const { graphModel, model } = this.props; graphModel.eventCenter.emit("custom:button-click", model); }; } } 4.6、网格 Grid

网格是指渲染/移动节点的最小单位。网格最主要的作用是在移动节点的时候,保证每个节点中心点的位置都是在网格上。这样更有利于节点直接的对齐。一般来说,网格的间隔越大,在编辑流程图的时候,节点就更好对齐;网格的间隔越小,拖动节点的感觉就更加流畅。

网格默认关闭,渲染/移动最小单位为 1px,若开启网格,则网格默认大小为 20px,渲染节点时表示以 20 为最小单位对齐到网络,移动节点时表示每次移动最小距离为 20px。

注意在设置节点坐标时会按照网格的大小来对坐标进行转换,如设置中心点位置{ x: 124, y: 138 } 的节点渲染到画布后的实际位置为 { x: 120, y: 140 }。所以使用 LogicFlow 替换项目中旧的流程设计器时,需要对历史数据的坐标进行处理。

提示在实际开发中,如果期望节点既可以中心对齐,也可以按照两边对齐。那么自定义节点的宽高需要是 grid 的偶数倍。也就是假设 grid 为 20,那么所有的节点宽度最好是 20、40、80、120 这种偶数倍的宽度。

开启网格 在创建画布的时候通过配置 grid 来设置网格属性

开启网格并应用默认属性:

const lf = new LogicFlow({ grid: true, }); // 等同于默认属性如下 const lf = new LogicFlow({ grid: { size: 20, visible: true, type: "dot", config: { color: "#ababab", thickness: 1, }, }, }); 设置网格属性 支持设置网格大小、类型、网格线颜色和宽度等属性。 export type GridOptions = { size?: number // 设置网格大小 visible?: boolean, // 设置是否可见,若设置为false则不显示网格线但是仍然保留size栅格的效果 type?: 'dot' | 'mesh', // 设置网格类型,目前支持 dot 点状和 mesh 线状两种 config?: { color: string, // 设置网格的颜色 thickness?: number, // 设置网格线的宽度 } }; 4.7、背景 Background

提供可以修改画布背景的方法,包括背景颜色或背景图片,背景层位于画布的最底层。

创建画布时,通过 background 选项来设置画布的背景层样式,支持透传任何样式属性到背景层。默认值为 false 表示没有背景。

const lf = new LogicFlow({ background: false | BackgroundConfig, }); type BackgroundConfig = { backgroundImage?: string, backgroundColor?: string, backgroundRepeat?: string, backgroundPosition?: string, backgroundSize?: string, backgroundOpacity?: number, filter?: string, // 滤镜 [key: any]: any, };

配置项 设置背景颜色

const lf = new LogicFlow({ // ... background: { backgroundImage: "url(../asserts/img/grid.svg)", backgroundRepeat: "repeat", }, }); 4.8、拖拽创建节点 Dnd

在流程图编辑场景中比起通过代码配置创建节点,我们可能更需要通过图形用户界面来操作创建流程图,这时候就可以通过拖拽的方式来实现。

拖拽需要结合图形面板来实现,步骤:创建面板 → 拖拽初始化 → 监听 drop 事件创建节点

示例如下:

lf.dnd.startDrag({ type, text: `${type}节点`, });

通过上面的代码可以看出,将节点通过div标签+css样式的方式绘制到面板中,并为其绑定onMouseDown事件,当拖拽图形时,会触发lf.dnd.startDrag函数,表示开始拖拽,并传入选中图形的配置,startDrag入参格式:

lf.dnd.startDrag(nodeConfig: NodeConfig):void type NodeConfig = { id?: string; // 不建议直接传id, logicflow id不允许重复 type: string; text?: TextConfig; properties?: Record; };

拖拽结束鼠标松开时,将当前鼠标的位置转换为画布上的坐标,并以此为节点的中心点坐标x、y,合并拖拽节点传入的nodeConfig,监听到 drop 事件后会调用lf.addNode方法创建节点。

使用拖拽面板插件

LogicFlow 在 extension 中内置了拖拽面板插件,如果不想自定义图形面板,可以使用此插件快速实现。

4.9、键盘快捷键 Keyboard

快捷键配置 通过创建 LogicFlow 实例时传入 options 的 keyboard 属性可以开启快捷键, 可以只配置 enabled 属性,为 true 时,代表开启默认的快捷键。

const lf = new LogicFlow({ container: document.querySelector("#app"), keyboard: { enabled: true, }, });

内置快捷键功能 参考不同的产品,内置了复制,粘贴,redo/undo,删除 的快捷键。

快捷键 功能 cmd + c 或 ctrl + c 复制节点 cmd + v 或 ctrl + v 粘贴节点 cmd + z 或 ctrl + z 撤销操作 cmd + y 或 ctrl + y 回退操作 backspace 删除操作 自定义快捷键 shortcuts 则可以定义用户自定义的一组快捷键 值得一提的是 keys 的规则,与mousetrap一致。

我们已自定义删除功能为例,在删除之前添加一个确认操作。

const lf = new LogicFlow({ // ... keyboard: { enabled: true, shortcuts: [ { keys: ["backspace"], callback: () => { const r = window.confirm("确定要删除吗?"); if (r) { const elements = lf.getSelectElements(true); lf.clearSelectElements(); elements.edges.forEach((edge) => lf.deleteEdge(edge.id)); elements.nodes.forEach((node) => lf.deleteNode(node.id)); } }, }, ], }, }); 4.10、对齐线 Snapline

对齐线能够在节点移动过程中,将移动节点的位置与画布中其他节点位置进行对比,辅助位置调整。位置对比有如下两个方面。

节点中心位置节点的边框

对齐线使用 普通编辑模式下,默认开启对齐线,也可通过配置进行关闭。 在静默模式下,无法移动节点,所以关闭了对齐线功能,无法通过配置开启。

// 关闭对齐线功能 const lf = new LogicFlow({ snapline: false, });

对齐线样式设置 对齐线的样式包括颜色和宽度,可以通过设置主题的方式进行修改。

// 默认配置 { stroke: '#1E90FF', strokeWidth: 1, } // 修改对齐线样式 lf.setTheme({ snapline: { stroke: '#1E90FF', // 对齐线颜色 strokeWidth: 1, // 对齐线宽度 }, }) 4.11、设置图编辑方式

LogicFlow 提供了非常多的控制图如何编辑的配置,详情见editConfigModel。

初始化 LogicFlow 支持在初始化的时候传入很多配置参数,图编辑的配置也可以在初始化的时候传入。

const lf = new LogicFlow({ stopZoomGraph: true, // 禁止缩放 stopScrollGraph: true, // 禁止鼠标滚动移动画布 });

更新图编辑方式

lf.updateEditConfig({ stopZoomGraph: false, stopScrollGraph: false, });

静默模式 画布的静默模式可以简单理解为“只读”模式,这种模式下,画布中的节点和边不可移动,不可进行文案修改,没有锚点。

提示 静默模式只是 LogicFlow 内置的流程图编辑控制的一种快捷方式。

// 开启静默模式 const lf = new LogicFlow({ isSilentMode: true, });


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3