🎄Hi~ 大家好,我是小鑫同学,一位长期从事前端开发的编程爱好者,我将使用更为实用的案例输出更多的编程知识,同时我信奉分享是成长的唯一捷径,在这里也希望我的每一篇文章都能成为你技术落地的参考~

🚀技术&代码分享

  • 我在 IT200 总结技术学习;
  • 我在 1024Code 在线编写代码;
  • 我在 掘金 分享技术文章;
  • 我在 Github 参与开源学习;

😇推荐几个好用的工具

进入正题

LogicFlow 是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端研发自定义开发各种逻辑编排场景,如流程图、ER图、BPMN流程等。在工作审批配置、机器人逻辑编排、无代码平台流程配置都有较好的应用。

这一节将讲解快速上手 LogicFlow 流程图编辑框架的自定义边(Edge),Edge 就是连接 NodeNode 之间的元素。项目整体基于Vue3+Vite3+Ts4开发,为帮助还为熟练使用 Vue3 和 Typescript 语法的小伙伴提供便利,如果你已经很熟练在Vue3中的开发习惯,建议直接访问 LogicFlow 将获取完整的入门指南。

1. 认识自定义边(Edge)模板:

同上一节的自定义业务节点模板一样,Edge 同样是需要继承自内置的 XxxNodeXxxEdgeModel 类,并且导出 typeviewmodel 三个选项,我相信上一节的代码你能运行成功,这一节就更加简单。

下面这段代码继承自内置的 PolylineEdgePolylineEdgeModel 实现本节的自定义 Edge

// 源码位置:./src/CustomEdge.ts
import { PolylineEdge, PolylineEdgeModel } from "@logicflow/core";

class CustomEdgeNode extends PolylineEdge {
    // 官网指示:由于边的编辑复杂度问题,绝大多数情况下,自定义边时不推荐自定义view
}

class CustomEdgeModel extends PolylineEdgeModel {

}

export default {
    type: "CustomEdge",
    view: CustomEdgeNode,
    model: CustomEdgeModel,
}

2. 优先进行注册和使用:

优先进行注册的原因和上一节中提到的一样,这里就不再赘述了,请接着往下操作吧。

2.1 注册自定义 Edge:

注册过程依旧是两个步骤:

  • 第一要将上面编写的 CustomEdge.ts 导入到 App.vue
  • 第二要将 CustomEdge 对象通过 lf 实例中的 register() 函数在 render() 前注册;
// 导入自定义 Edge
import CustomEdge from "./CustomEdge";

// 准备两个Node,并使用自定义Edge来连接它们俩
const graphData = {}

onMounted(() => {
  // 在执行 render 前进行注册
  lf.value.register(CustomEdge);
  lf.value.render();
})

2.2 如何使用自定义 Edge:

Node 的定义相同,但是要将自定义的 Edge 放置到 edges 中,区别是 edge 需要明确 源节点 ID目标节点 ID 两个值,通过这两个值来定位被 Edge 连接的到底是谁,type 同样需要指定为自定义 Edgetype 属性值;

// 准备两个Node,并使用自定义Edge来连接它们俩
const graphData = {
  nodes: [
    {
      id: '242b1b6c-1721-4b10-b4ad-c895094cf332',
      type: 'rect',
      x: 100,
      y: 100
    },
    {
      id: 'e59d6ecd-68f7-4d50-8e3f-29e67b6e5f16',
      type: 'circle',
      x: 300,
      y: 200
    }
  ],
  edges: [
    {
      sourceNodeId: '242b1b6c-1721-4b10-b4ad-c895094cf332',
      targetNodeId: 'e59d6ecd-68f7-4d50-8e3f-29e67b6e5f16',
      type: 'CustomEdge',
    }
  ]
}

3. 自定义 Edge 的 Text & Outline 的风格:

对于 Edge 风格的自定义同样是通过重写不同的函数来实现,如重写:getEdgeStyle()getTextStyle()getOutlineStyle(),还有最后对箭头风格的自定义;

class CustomEdgeModel extends PolylineEdgeModel {
  
    getEdgeStyle() {
      const style = super.getEdgeStyle();
      const { properties } = this;
      if (properties.isActived) {
          style.strokeDasharray = "4 4";
      }
      style.stroke = "orange";
      return style;
  }
  
  getTextStyle() {
      const style = super.getTextStyle();
      style.color = "#3451F1";
      style.fontSize = 20;
      style.background && (style.background.fill = "#F2F131");
      return style;
  }
  
  getOutlineStyle() {
      const style = super.getOutlineStyle();
      style.stroke = "red";
      style.hover && (style.hover.stroke = "red");
      return style;
  }
}

当你完成了上面几个函数的重写后就得到的下面截图的效果:

4. 开启边(Edge)动画:

增加动画可以体现从一个 Node 到流向另一个 Node 的过程,在大多数的流程图编辑软件中都有这样的功能存在。

在LF中可以通过 lf.openEdgeAnimation(edgeId) 启动默认动画,也可以通过重写 getEdgeAnimationStyle() 函数来自定义动画的属性;

  • 开启默认动画:为需要开启动画的 Edge 增加 id 字段,并在执行渲染函数 render() 后开启动画:
const graphData = {
  edges: [
    {
        // 增加 id 字段
      id: '702a4d2f-b516-4769-adb0-5a4f4f5c07a9',
      sourceNodeId: '242b1b6c-1721-4b10-b4ad-c895094cf332',
      targetNodeId: 'e59d6ecd-68f7-4d50-8e3f-29e67b6e5f16',
      type: 'CustomEdge',
    }
  ]
}

onMounted(() => {
  lf.value.render(graphData);
  // 执行渲染后开启动画
  lf.value.openEdgeAnimation("702a4d2f-b516-4769-adb0-5a4f4f5c07a9");
})
  • 自定义动画属性:重写 getEdgeAnimationStyle() 函数设置动画属性,重写 setAttributes() 函数开启动画:
class CustomEdgeModel extends PolylineEdgeModel {

        // ... 省略部分代码
  
      setAttributes(): void {
        this.isAnimation = true;
    }
    
    getEdgeAnimationStyle() {
        const style = super.getEdgeAnimationStyle();
        style.strokeDasharray = "5 5";
        style.animationDuration = "10s";
        return style;
    }
}

5. 自定义节点间边(Edge)的类型:

默认 Edge 的类型可以在实例化 LF 时通过 edgeType 选项进行调整,也可以使用 lf.setDefaultEdgeType(edgeType) 函数来指定;除此之外,为了满足不同的业务节点使用不同类型的边来表示还可以通过实例化LF时通过设置 edgeGenerator 函数进行显示规则的定义。

  • 通过函数设置默认类型:
lf.value.setDefaultEdgeType("CustomEdge");
  • 通过选项设置默认类型:
lf.value = new LogicFlow({
  edgeType: "CustomEdge",
})
  • 按同节点类型设置不同的类型:
lf.value = new LogicFlow({
  edgeGenerator(sourceNode, targetNode, currentEdge?) {
    if (sourceNode.type === 'rect') return 'CustomEdge'
  },
})

6. 自定义箭头的类型:

通过 setTheme() 函数中提供的 arrow 选项,可以指定默认 Edge 箭头的风格;也可以在继承 PolylineEdge 后通过重写getEndArrow() 函数来实现更多显示风格。

  • 通过 setTheme() 函数设置剪头的风格:
f.value.setTheme({
  arrow: {
    offset: 4, // 箭头垂线长度
    verticalLength: 2, // 箭头底线长度
  }
})
  • 通过重写 getEndArrow() 函数,按 properties 传递的类型来实现不同的效果:
class CustomEdgeNode extends PolylineEdge {
    getEndArrow() {
        const { model } = this.props;
        const { properties: { arrowType } } = model;
        const { stroke, strokeWidth } = this.getArrowStyle();
        const pathAttr = {
            stroke,
            strokeWidth
        }
        if (arrowType === 'half') { // 半箭头
            return (
                h('path', {
                    ...pathAttr,
                    d: 'M 0 0 -10 5'
                })
            )
        }
        return h('path', {
            ...pathAttr,
            d: 'M 0 0 -10 -5 -10 5 z'
        })
    }
}

总结

这一节的内容就到此结束了,你的代码都运行起来了吗,文中缺少了一些运行的效果图,你可以直接访问我在1024code的项目在线预览效果来与你的代码进行对比学习。下一节将带来 LF 使用时更多的配置选项介绍。


如果看完觉得有收获,欢迎点赞、评论、分享支持一下。你的支持和肯定,是我坚持写作的动力~


前端小鑫同学
36 声望5 粉丝

Front-end development engineer. Focus on building web applications and websites using Vue.js, Angular, Typescript, and Node.js.