joint绘制流程图

joint绘制流程图

首先给个效果图,以防你们点进来发现不是自己想要的东西
在这里插入图片描述
这里调试的时候是按手机大小写的,所以看起来有点小,问题不大。
我在这用的是joint工具进行绘制。
第一步当然是安装这个工具,毋庸置疑

npm install jointjs --save

安装完后,别的资料有说要用在main.js里加入

window.$ = require('jquery');
window.joint = require('jointjs');

搞一下全局变量,我没用这个,所以忽略这一步,直接在页面里引用

import * as joint from 'jointjs'

测试数据如下

history: {
        1: 1,
        2: 1,
        3: 1,
        4: 9,
        5: 1
      },
      nodes: [
        {
          id: 1,
          name: '流程2',
          nodeX: 292,
          nodeY: 84
        },
        {
          id: 2,
          name: '流程1',
          nodeX: 46,
          nodeY: 289
        },
        {
          id: 3,
          name: '流程3',
          nodeX: 292,
          nodeY: 465
        },
        {
          id: 4,
          name: '流程4',
          nodeX: 524,
          nodeY: 347
        },
        {
          id: 5,
          name: '流程5',
          nodeX: 292,
          nodeY: 19
        },
        {
          id: 6,
          name: '流程6',
          nodeX: 292,
          nodeY: 231
        },
        {
          id: 7,
          name: '流程7',
          nodeX: 292,
          nodeY: 231
        }
      ],
      routes: [
        {
          fromNodeId: 1,
          toNodeId: 2,
          toDescribe: '1-2'
        },
        {
          fromNodeId: 2,
          toNodeId: 3,
          toDescribe: '2-3'
        },
        {
          fromNodeId: 3,
          toNodeId: 5,
          toDescribe: '3-5'
        },
        {
          fromNodeId: 5,
          toNodeId: 4,
          toDescribe: '5-4'
        },
        {
          fromNodeId: 4,
          toNodeId: 6,
          toDescribe: '4-6'
        },
        {
          fromNodeId: 6,
          toNodeId: 7,
          toDescribe: '6-7'
        },
        {
          fromNodeId: 7,
          toNodeId: 1,
          toDescribe: '7-1'
        }
      ],

以上是用的数据,就放到data里的return中即可,小伙伴们在写代码需要调用后端数据,可以在mounted里先请求后端接口获取数据
完整代码与注解如下

<template>
  <div>
    <Button size="small" type="primary" @click="changeSize('big')">
      放大
    </Button>
    <Button size="small" type="primary" @click="changeSize('small')">
      缩小
    </Button>
    <div id="aa"></div>
  </div>
</template>
<script>
import * as joint from 'jointjs'
export default {
  name: 'About',
  components: {},
  data() {
    return {
      history: {},
      nodes: [],
      routes: [],
      // 图
      graph: new joint.dia.Graph(),
      // 页面
      paper: '',
      // 宽度
      width: document.body.clientWidth,
      // 颜色选区
      color: ['#ffffff', '#07de62', '#f5f65e', '#ff546c']
    }
  },
  async mounted() {
  	//我这边是直接用测试数据,要请求后端可以在这加个方法,如下
  	//这里可以加个loding
  	//const result = await 服务.方法(传递的数据)
  	//加载完去除loding
  	//if (result.data === null) {
    //  return
    //}
    //const { history, nodes, routes } = result.data
    //调用下面的papers方法
    this.paper = this.papers()
    // 绘制节点
    const nodesList = []
    for (const i in this.nodes) {
      nodesList.push(
        this.rectStatue(
          this.nodes[i].nodeX,
          this.nodes[i].nodeY,
          100,
          this.heightNode(this.nodes[i].name).height,
          this.heightNode(this.nodes[i].name).text
        )
      )
      this.graph.addCells([nodesList[i]])
    }
    // 绘制图片
    for (const i in this.routes) {
      const formIndex = this.nodes.findIndex((item) => {
        return item.id === this.routes[i].fromNodeId
      })
      const toIndex = this.nodes.findIndex((item) => {
        return item.id === this.routes[i].toNodeId
      })
      const link = this.link(
        nodesList[formIndex],
        nodesList[toIndex],
        this.routes[i].toDescribe
      )
      this.graph.addCells([link])
    }
    for (const i in this.history) {
      const index = this.nodes.findIndex((item) => {
        return item.id === Number(i)
      })
      let num = 0
      if (this.history[i] > 3) {
        num = 3
      } else {
        num = this.history[i]
      }
      nodesList[index].attr({ rect: { fill: this.color[num] } })
    }
    /**
     * 初始化页面的时候找到第一个节点的位置,将画板移动到第一个节点的位置
     */
    this.paper.translate(-this.nodes[0].nodeX + this.width / 2, 0)
    // 拖动画板移动函数
    this.movePaper()
    this.changeSize('init')
  },
  methods: {
    /**
     * 手指按下的事件拖动画板的移动
     * @type {{startMove: number, origin: *, startY: number, startX: number}}
     */
    movePaper() {
      const self = {
        startX: 0,
        startY: 0,
        origin: this.paper.options.origin,
        startMove: 0
      }
      const that = this
      this.paper.on({
        'blank:pointerdown': function (evt, x, y) {
          self.startX = x
          self.startY = y
          self.startMove = true
        },
        'blank:pointermove': function (evt, x, y) {
          if (self.startMove) {
            var diffX = x - self.startX + self.origin.x
            var diffY = y - self.startY + self.origin.y
            that.paper.translate(diffX, diffY)
          }
        },
        'blank:pointerup': function (evt, x, y) {
          self.startMove = false
        }
      })
    },
    changeSize(type) {
      const { sy } = this.paper.scale()
      if (type === 'big') {
        this.paper.scale(sy + 0.1)
        console.log((sy + 0.1).toFixed(1) + '倍')
      } else if (type === 'small') {
        if (sy.toFixed(1) === '0.5') {
          console.log('已缩小到最小倍数')
          return
        }
        this.paper.scale(sy - 0.1)
        console.log((sy - 0.1).toFixed(1) + '倍')
      } else if (type === 'init') {
        this.paper.scale(sy - 0.2)
      }
    },
    heightNode(text) {
      const breakedText = joint.util.breakText(text, { width: 100 })
      const lineNum = breakedText.split('\n').length
      return {
        height: lineNum === 1 ? lineNum * 30 : lineNum * 20,
        text: breakedText
      }
    },
    link(source, target, text) {
      return new joint.shapes.standard.Link({
        source: { id: source.id },
        target: { id: target.id },
        labels: [
          {
            position: 0.5,
            attrs: {
              text: {
                text: text || '',
                'font-weight': 'bold',
                'font-size': '12px'
              }
            }
          }
        ],
        router: { name: 'manhattan' }
      })
    },
    rectStatue(x, y, width, height, text) {
      return new joint.shapes.basic.Rect({
        position: { x: x, y: y },
        size: { width: width, height: height },
        attrs: {
          rect: { fill: 'white' },
          text: { text: text, fill: 'black' }
        }
      })
    },
    papers() {
      const ElementView = joint.dia.ElementView.extend({
        pointerdown: function () {
          this._click = true
          joint.dia.ElementView.prototype.pointerdown.apply(this, arguments)
        },
        pointermove: function (evt, x, y) {
          this._click = false
        },
        pointerup: function (evt, x, y) {
          this._click = true
          if (this._click) {
            this.notify('cell:click', evt, x, y)
          } else {
            joint.dia.ElementView.prototype.pointerup.apply(this, arguments)
          }
        }
      })
      return new joint.dia.Paper({
        el: document.getElementById('aa'),
        width: document.body.clientWidth,
        height: window.innerHeight - 50,
        model: this.graph,
        gridSize: 1,
        elementView: ElementView
      })
    }
  }
}
</script>
<style>
</style>

应该不难看懂,有问题可以在下面留言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用 JointJS 绘制流程图并实现节点拖拽的示例代码: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JointJS 流程图示例</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jointjs@3.4.1/dist/joint.min.css"> <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/backbone@1.4.0/backbone-min.js"></script> <script src="https://cdn.jsdelivr.net/npm/jointjs@3.4.1/dist/joint.min.js"></script> </head> <body> <div id="paper"></div> <script> $(function() { var graph = new joint.dia.Graph(); var paper = new joint.dia.Paper({ el: $('#paper'), width: 600, height: 400, gridSize: 10, model: graph, }); var rect = new joint.shapes.standard.Rectangle(); rect.position(100, 100); rect.resize(100, 40); rect.attr({ body: { fill: 'lightblue', rx: 10, ry: 10, strokeWidth: 2, stroke: 'black', }, label: { text: 'Hello', fill: 'black', fontSize: 18, fontWeight: 'bold', textAnchor: 'middle', textVerticalAnchor: 'middle', } }); rect.addTo(graph); var circle = new joint.shapes.standard.Circle(); circle.position(300, 200); circle.resize(60, 60); circle.attr({ body: { fill: 'lightgreen', strokeWidth: 2, stroke: 'black', }, label: { text: 'World', fill: 'black', fontSize: 18, fontWeight: 'bold', textAnchor: 'middle', textVerticalAnchor: 'middle', } }); circle.addTo(graph); paper.on('cell:pointerdown', function(cellView) { // 记录鼠标按下时的节点位置 cellView.model.set('oldpos', cellView.model.get('position')); }); paper.on('cell:pointerup', function(cellView) { // 如果节点位置发生变化,则更新模型中的位置数据 var newPos = cellView.model.get('position'); var oldPos = cellView.model.get('oldpos'); if (newPos.x !== oldPos.x || newPos.y !== oldPos.y) { cellView.model.set('oldpos', newPos); } }); }); </script> </body> </html> ``` 在这个示例中,我们首先创建了一个画布对象 `paper` 和一个图形模型对象 `graph`。然后创建了两个图形节点,一个是矩形,一个是圆形,分别使用 `joint.shapes.standard.Rectangle` 和 `joint.shapes.standard.Circle` 类来创建。 我们为这两个节点设置了一些属性,如位置、大小、填充色、边框颜色等,还为节点添加了一个文本标签,用于显示节点的名称。 接下来,我们使用 `paper.on` 方法监听了 `cell:pointerdown` 和 `cell:pointerup` 两个事件,分别表示节点被拖拽时和拖拽结束时的处理。 在 `cell:pointerdown` 事件中,我们记录了鼠标按下时的节点位置,使用 `cellView.model.set('oldpos', cellView.model.get('position'))` 将其保存到节点模型的 `oldpos` 属性中。 在 `cell:pointerup` 事件中,我们判断节点的位置是否发生了变化,如果变化了,则更新模型中的位置数据,使用 `cellView.model.set('oldpos', newPos)` 更新 `oldpos` 属性。 这样,我们就实现了流程图中节点的拖拽功能。用户可以通过鼠标拖动节点来改变其位置,拖动结束时,节点的位置数据将被更新到模型中。 注意:本示例代码使用了 JointJS 3.x 版本的 API,如果使用其他版本的 JointJS 库,可能需要做一些修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值