LogicFlow 是什么
LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端自定义开发各种逻辑编排场景,如流程图、ER图、BPMN流程等。在工作审批流配置、机器人逻辑编排、无代码平台流程配置都有较好的应用。**个人公众号:鱼樱AI实验室**
安装
pnpm add @logicflow/core
# 插件包(不使用插件时不需要引入)
pnpm add @logicflow/extension
基础使用
基础节点
LogicFlow的基础节点是比较简单的,但是在业务中对节点外观要求可能有各种情况。LogicFlow提供了非常强大的自定义节点功能,可以支持开发者自定义各种节点。下面是基于继承的自定义节点介绍。
<template>
<div id="logic-flow"></div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import LogicFlow from '@logicflow/core'
import { Control } from '@logicflow/extension'
import '@logicflow/core/lib/style/index.css'
import '@logicflow/extension/es/index.css'
// 全局使用 每一个lf实例都具备 Control
LogicFlow.use(Control)
let lf: LogicFlow
// 图数据
const graphData = {
// 节点数据 基础节点 & 自定义节点数据
nodes: [
// 节点数据属性:节点1
{
id: '1',
type: 'rect',
x: 50,
y: 50,
text: { x: 100, y: 100, value: '方形' }, // 节点文本
properties: {
width: 80,
height: 80,
style: {
stroke: 'blue',
},
isPass: 'true', // 例如:在审批流场景,我们定义某个节点,这个节点通过了,节点为绿色,不通过节点为红色。
},
},
// 节点2
{
id: '2',
type: 'circle',
x: 200,
y: 300,
text: { x: 300, y: 300, value: '圆形' },
properties: {},
},
{
id: '3',
type: 'ellipse',
x: 500,
y: 60,
text: '椭圆',
},
{
id: '4',
type: 'polygon',
x: 100,
y: 200,
text: '多边形',
},
{
id: '5',
type: 'diamond',
x: 300,
y: 200,
text: '菱形',
},
{
id: '6',
type: 'text',
x: 500,
y: 200,
text: '纯文本节点',
},
{
id: '7',
type: 'html',
x: 100,
y: 320,
text: 'html节点',
},
],
edges: [
// 边数据属性 连线属性配置
{
id: 'edge_id',
type: 'polyline',
sourceNodeId: '1',
targetNodeId: '2',
text: { x: 139, y: 200, value: '连线' }, // 连线文本
properties: {},
},
],
}
onMounted(() => {
lf = new LogicFlow({
container: document.querySelector('#logic-flow') as HTMLElement,
stopScrollGraph: true,
stopMoveGraph: true,
})
lf.render(graphData)
lf.translateCenter() // 将图形移动到画布中央
const data = lf.getGraphData()
console.log(data, '获取画布数据')
})
</script>
<style>
#logic-flow {
width: 100%;
height: 500px;
border: 1px solid #dcdcdc;
}
</style>
自定义节点
LogicFlow是基于继承来实现自定义节点、边。开发者可以继承LogicFlow内置的节点,然后利用面向对象的机制 重写
model
: 数据层,包含节点各种样式(边框、颜色)、形状(宽高、顶点位置)、业务属性等。
view
: 视图层,控制节点的最终渲染效果,通过改变model
就可以满足自定义节点,同时可以在view
上定制更加复杂的svg
元素。
LogicFlow 内部存在 7 种基础节点, 自定义节点的时候可以基于需要选择任意一种来继承, 然后取一个符合自己业务意义的名字。以@logicflow/extension中提供的可缩放节点为例:LogicFlow 基础节点不支持节点缩放,于是 LogicFlow 在extension包中,基于基础节点,封装了对节点缩放的逻辑,然后发布出去。这样开发者可以直接基于extension中的可缩放节点进行自定义。
import LogicFlow, { RectNode, RectNodeModel } from '@logicflow/core'
export type CustomProperties = {
// 形状属性
width?: number
height?: number
radius?: number
// 文字位置属性
refX?: number
refY?: number
// 样式属性
style?: LogicFlow.CommonTheme
textStyle?: LogicFlow.TextNodeTheme
}
class CustomRectNode extends RectNode {}
class CustomRectModel extends RectNodeModel {
// 设置矩形的形状属性:大小和圆角
setAttributes() {
this.width = 200
this.height = 80
this.radius = 50
}
// 重写文本样式属性
getTextStyle(): LogicFlow.TextNodeTheme {
const { refX = 0, refY = 0 } = this.properties as CustomProperties
const style = super.getTextStyle()
// 通过 transform 重新设置 text 的位置:向下移动70px
return {
...style,
transform: `matrix(1 0 0 1 ${refX} ${refY + 60})`,
}
}
// 设置矩形的样式属性:边框颜色
getNodeStyle() {
const style = super.getNodeStyle()
style.stroke = 'blue'
return style
}
}
export default {
// 类型
type: 'custom-rect',
view: CustomRectNode,
model: CustomRectModel,
}
<template>
<div id="logic-flow"></div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import LogicFlow from '@logicflow/core'
import { Control } from '@logicflow/extension'
import '@logicflow/core/lib/style/index.css'
import '@logicflow/extension/es/index.css'
// 自定义节点 view & model
import CustomRect from './customRect'
// 全局使用 每一个lf实例都具备 Control
LogicFlow.use(Control)
let lf: LogicFlow
// 图数据
const graphData = {
nodes: [
// 节点数据属性:节点1
{
id: '1',
type: 'rect',
x: 50,
y: 50,
text: { x: 100, y: 100, value: '方形' }, // 节点文本
properties: {
width: 80,
height: 80,
style: {
stroke: 'blue',
},
isPass: 'true', // 例如:在审批流场景,我们定义某个节点,这个节点通过了,节点为绿色,不通过节点为红色。
},
},
// 节点2
{
id: '2',
type: 'circle',
x: 200,
y: 300,
text: { x: 300, y: 300, value: '圆形' },
properties: {},
},
{
id: '3',
type: 'ellipse',
x: 500,
y: 60,
text: '椭圆',
},
{
id: '4',
type: 'polygon',
x: 100,
y: 200,
text: '多边形',
},
{
id: '5',
type: 'diamond',
x: 300,
y: 200,
text: '菱形',
},
{
id: '6',
type: 'text',
x: 500,
y: 200,
text: '纯文本节点',
},
{
id: '7',
type: 'html',
x: 100,
y: 320,
text: 'html节点',
},
// 节点数据属性:节点1
{
id: '8',
type: 'custom-rect', // 使用自定义节点类型
x: 50,
y: 50,
text: { x: 100, y: 100, value: '自定义方形' }, // 节点文本
properties: {
width: 80,
height: 80,
style: { stroke: 'red' },
isPass: 'true',
},
},
],
edges: [
// 边数据属性
{
id: 'edge_id',
type: 'polyline',
sourceNodeId: '1',
targetNodeId: '2',
text: { x: 139, y: 200, value: '连线' }, // 连线文本
properties: {},
},
],
}
onMounted(() => {
lf = new LogicFlow({
container: document.querySelector('#logic-flow') as HTMLElement,
stopScrollGraph: true,
stopMoveGraph: true,
})
// 注册自定义节点,注册后才能使用自定义节点
lf.register(CustomRect)
lf.render(graphData)
lf.translateCenter() // 将图形移动到画布中央
const data = lf.getGraphData()
console.log(data, 'data')
})
</script>
<style>
#logic-flow {
width: 100%;
height: 500px;
border: 1px solid #dcdcdc;
}
</style>
基础边
-
- 直线 - line (内置)
-
- 直角折线 - polyline (内置)
-
- 贝塞尔曲线 - bezier (内置)
<template>
<div id="logic-flow"></div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import LogicFlow from '@logicflow/core'
import { Control } from '@logicflow/extension'
import '@logicflow/core/lib/style/index.css'
import '@logicflow/extension/es/index.css'
// 自定义节点
import CustomRect from './customRect'
// 全局使用 每一个lf实例都具备 Control
LogicFlow.use(Control)
let lf: LogicFlow
// 图数据
const graphData = {
nodes: [
// 节点数据属性:节点1
{
id: '1',
type: 'rect',
x: 50,
y: 50,
text: { x: 100, y: 100, value: '方形' }, // 节点文本
properties: {
width: 80,
height: 80,
style: {
stroke: 'blue',
},
isPass: 'true', // 例如:在审批流场景,我们定义某个节点,这个节点通过了,节点为绿色,不通过节点为红色。
},
},
// 节点2
{
id: '2',
type: 'circle',
x: 200,
y: 300,
text: { x: 300, y: 300, value: '圆形' },
properties: {},
},
{
id: '3',
type: 'ellipse',
x: 500,
y: 60,
text: '椭圆',
},
{
id: '4',
type: 'polygon',
x: 100,
y: 200,
text: '多边形',
},
{
id: '5',
type: 'diamond',
x: 300,
y: 200,
text: '菱形',
},
{
id: '6',
type: 'text',
x: 500,
y: 200,
text: '纯文本节点',
},
{
id: '7',
type: 'html',
x: 100,
y: 320,
text: 'html节点',
},
// 节点数据属性:节点1
{
id: '8',
type: 'custom-rect', // 使用自定义节点类型
x: 50,
y: 50,
text: { x: 100, y: 100, value: '自定义方形' }, // 节点文本
properties: {
width: 80,
height: 80,
style: { stroke: 'red' },
isPass: 'true',
},
},
],
edges: [
// 边数据属性
{
id: '1',
type: 'polyline',
sourceNodeId: '1',
targetNodeId: '2',
text: { x: 139, y: 200, value: 'polyline直角折线' }, // 连线文本
properties: {},
},
{
id: '2',
sourceNodeId: '2',
targetNodeId: '3',
type: 'line',
text: 'line直线',
},
{
id: '3',
sourceNodeId: '3',
targetNodeId: '4',
type: 'bezier',
text: 'bezier贝塞尔曲线',
},
],
}
onMounted(() => {
lf = new LogicFlow({
container: document.querySelector('#logic-flow') as HTMLElement,
stopScrollGraph: true,
stopMoveGraph: true,
})
// 注册自定义节点,注册后才能使用自定义节点
lf.register(CustomRect)
lf.render(graphData)
lf.translateCenter() // 将图形移动到画布中央
const data = lf.getGraphData()
console.log(data, 'data')
})
</script>
<style>
#logic-flow {
width: 100%;
height: 500px;
border: 1px solid #dcdcdc;
}
</style>
自定义边
选择自定义边继承的内置边,和节点一样,LogicFlow 的边也支持基于继承的自定义机制。同样也只需同时继承view
和model
。 但是和节点不一样的是,由于边的编辑复杂度问题,绝大多数情况下,自定义边时不推荐自定义view
。 只需要在自定义edgeModel中样式类即可。
// 直线
import { LineEdge, LineEdgeModel } from '@logicflow/core'
// 折线
import { PolylineEdge, PolylineEdgeModel } from '@logicflow/core'
// 贝塞尔曲线
import { BezierEdge, BezierEdgeModel } from '@logicflow/core'
import { PolylineEdge, PolylineEdgeModel, LogicFlow } from '@logicflow/core';
import EdgeTextTheme = LogicFlow.EdgeTextTheme;
class SequenceModel extends PolylineEdgeModel {
// 设置边样式
getEdgeStyle() {
const style = super.getEdgeStyle();
const { properties } = this;
if (properties.isstrokeDashed) {
style.strokeDasharray = '4, 4';
}
style.stroke = 'orange';
return style;
}
// 设置边文本样式
getTextStyle() {
const style: EdgeTextTheme = super.getTextStyle();
style.color = '#3451F1';
style.fontSize = 20;
style.background = Object.assign({}, style.background, {
fill: '#F2F131',
});
return style;
}
// 设置 hover 轮廓样式
getOutlineStyle() {
const style = super.getOutlineStyle();
style.stroke = 'blue';
return style;
}
}
export default {
type: 'custom-line',
view: PolylineEdge,
model: SequenceModel,
};
<template>
<div id="logic-flow"></div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import LogicFlow from '@logicflow/core'
import { Control } from '@logicflow/extension'
import '@logicflow/core/lib/style/index.css'
import '@logicflow/extension/es/index.css'
// 自定义节点
import CustomRect from './customRect'
// 自定义边
import CustomLine from './customLine'
// 全局使用 每一个lf实例都具备 Control
LogicFlow.use(Control)
let lf: LogicFlow
// 图数据
const graphData = {
nodes: [
// 节点数据属性:节点1
{
id: '1',
type: 'rect',
x: 50,
y: 50,
text: { x: 100, y: 100, value: '方形' }, // 节点文本
properties: {
width: 80,
height: 80,
style: {
stroke: 'blue',
},
isPass: 'true', // 例如:在审批流场景,我们定义某个节点,这个节点通过了,节点为绿色,不通过节点为红色。
},
},
// 节点2
{
id: '2',
type: 'circle',
x: 200,
y: 300,
text: { x: 300, y: 300, value: '圆形' },
properties: {},
},
{
id: '3',
type: 'ellipse',
x: 500,
y: 60,
text: '椭圆',
},
{
id: '4',
type: 'polygon',
x: 100,
y: 200,
text: '多边形',
},
{
id: '5',
type: 'diamond',
x: 300,
y: 200,
text: '菱形',
},
{
id: '6',
type: 'text',
x: 500,
y: 200,
text: '纯文本节点',
},
{
id: '7',
type: 'html',
x: 100,
y: 320,
text: 'html节点',
},
// 节点数据属性:节点1
{
id: '8',
type: 'custom-rect', // 使用自定义节点类型
x: 50,
y: 50,
text: { x: 100, y: 100, value: '自定义方形' }, // 节点文本
properties: {
width: 80,
height: 80,
style: { stroke: 'red' },
isPass: 'true',
},
},
],
edges: [
// 边数据属性
{
id: '1',
type: 'polyline',
sourceNodeId: '1',
targetNodeId: '2',
text: { x: 139, y: 200, value: '连线' }, // 连线文本
properties: {},
},
{
id: '2',
sourceNodeId: '2',
targetNodeId: '3',
type: 'line',
text: 'line',
},
{
id: '3',
sourceNodeId: '3',
targetNodeId: '4',
type: 'bezier',
text: 'bezier',
},
{
id: '4',
sourceNodeId: '4',
targetNodeId: '5',
startPoint: {
x: 100,
y: 60,
},
endPoint: {
x: 500,
y: 50,
},
text: 'custom-line自定义边',
type: 'custom-line',
properties: {
isstrokeDashed: true, // 是否虚线
},
},
],
}
onMounted(() => {
lf = new LogicFlow({
container: document.querySelector('#logic-flow') as HTMLElement,
stopScrollGraph: true,
stopMoveGraph: true,
})
// 注册自定义节点,注册后才能使用自定义节点
lf.register(CustomRect)
// 注册自定义边,注册后才能使用自定义边
lf.register(CustomLine)
// 设置当节点直接由用户手动连接的默认边类型
lf.setDefaultEdgeType('sequence')
lf.render(graphData)
lf.translateCenter() // 将图形移动到画布中央
const data = lf.getGraphData()
console.log(data, 'data')
})
</script>
<style>
#logic-flow {
width: 100%;
height: 500px;
border: 1px solid #dcdcdc;
}
</style>
logic-flow 其他配置属性
- 背景相关
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 lf1 = new LogicFlow({
grid: true,
})
// 等同于默认属性如下
const lf2 = new LogicFlow({
grid: {
size: 20,
visible: true,
type: 'dot',
config: {
color: '#ababab',
thickness: 1,
},
},
})
- 事件相关
lf
实例上提供on
方法支持监听事件
lf.on("node:dnd-add", (data) => {});
LogicFlow 支持用逗号分割事件名
lf.on('node:click,edge:click', (data) => {})
自定义事件
除了 lf 上支持的监听事件外,还可以使用eventCenter 对象来监听和触发事件。eventCenter
是一个graphModel
上的一个属性。所以在自定义节点的时候,我们可以使用eventCenter
触发自定义事件
拖拽面板 (DndPanel)
自定义拖拽面板内容
lf.setPatternItems(patternItems)
lf.extension.dndPanel.setPatternItems(patternItems) 1.1.0
新增
- 设置拖拽面板组件内容
type PatternItem = {
type?: string;
text?: string;
label?: string;
icon?: string;
className?: string;
properties?: object;
callback?: () => void;
}
// lf.extension.dndPanel.setPatternItems = (patternItems:PatternItem[]) => void
lf.extension.dndPanel.setPatternItems(patternItems)
有了这些你搞起流程图来就方便很多了~~~