Blog

流程图实现方案探索

time: 2022-01-29 14:59:54
author: heyunjiang

背景

最近又有需求要做流程图设计,之前使用 antv/x6 搞了自动布局,效果不是太满意。
后来又了解到 mxgraph,没有找到相关实现的 demo,不过 draw.io 倒是其较好的一款实现。
之前团队有人分享过,可以直接使用 draw.io 的 iframe 内嵌方式,感觉不太优雅。
现在又有相关需求,业务团队指定要使用 jsplumb 实现,先了解一下 jsplumb 项目特点

  1. github star: 6.8k
  2. 是否持续更新:最近一次更新是 10 小时前,项目还在持续更新
  3. 文档支持:最近的中文文档是2年前的,最新版本需要查看官方英文版本,但是英文版本的文档又比较烂,需要结合文档、demo、源码一起来看
  4. 实现功能:jsplumb 实现了基本的核心功能,包括自定义节点、锚点、endPoint、overlay、连线、拖拽,其中连接线支持直线、贝塞尔曲线、流程图折线等
  5. 实现效果:所有样式需要开发者自行开发,可以基于 jsplumb 开发一套流程图库
  6. 项目欠缺点:复杂节点自定义布局算法缺失,节点布局需要用户自定义控制

1 流程图实现要点

  1. 节点:开始、结束、判断、自定义
  2. 连接线:直线、折线、贝塞尔曲线
  3. 连接线 overlay:箭头、label
  4. 锚点:是否可以连线
  5. endpoint:连接点
  6. 拖拽:节点拖拽、连线拖拽、基础组件库组件拖拽生成
  7. 渲染动画
  8. 自动布局:数据驱动,自动布局

2 现有方案对比

3 jsplumb demo

<template>
  <div class="container">
    <div ref="item_left" class="item"></div>
    <div ref="item_right" class="item item2"></div>
  </div>
</template>
<script>
import * as jsPlumbBrowserUI from '@jsplumb/browser-ui'
import { BezierConnector } from '@jsplumb/connector-bezier'
export default {
  name: 'process',
  components: {},
  mixins: [],
  props: {},
  data() {
    return {
      instance: null,
    }
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {
    this.init()
  },
  methods: {
    init() {
      const instance = jsPlumbBrowserUI.newInstance({
        container: this.$el,
        dragOptions: {
          containment: 'parent',
        },
        connector: {
          type: BezierConnector.type,
          options: {
            curviness: 50,
          },
        },
      })
      this.instance = instance
      jsPlumbBrowserUI.ready(() => {
        this.render()
        this.bindEvent()
      })
    },
    render() {
      this.instance.addEndpoint(this.$refs.item_left, {
        source: true,
        endpoint: 'Dot',
      })
      this.instance.addEndpoint(this.$refs.item_right, {
        target: true,
        endpoint: 'Dot',
      })
      this.instance.connect({
        source: this.$refs.item_left,
        target: this.$refs.item_right,
      })
    }
  },
}
</script>
<style lang="scss" scoped>
.container {
  position: relative;
  height: 100%;
}
.item {
  position: absolute;
  display: inline-block;
  height: 50px;
  width: 50px;
  border: 1px solid #ccc;
}
.item2 {
  left: 100px;
}
</style>

参考文章

jsPlumb 官网