结合给定数据使用JointJS自动绘制元素

这篇博客展示了如何结合数据利用JointJS库和DAGRE布局算法在Vue应用中创建流程图。首先导入所需模块,然后定义数据结构,接着在Vue组件的`mounted`钩子中初始化画布和图形元素,监听点击事件。最后,通过`render`方法绘制节点和链接,并调用`doLayout`进行布局。示例代码详细地解释了每个步骤。
摘要由CSDN通过智能技术生成

我们给定一串数据,然后结合数据用 JointJS 在画布中绘制出元素

data.js

export default [{
  id: 1,
  type: 'start',
  name: '事件',
  prev: [],
  next: [2, 5, 6]
}, {
  id: 2,
  type: 'field',
  name: '字段1',
  prev: [1],
  next: [4]
}, {
  id: 4,
  type: 'field',
  name: '字段2',
  prev: [2],
  next: [3]
}, {
  id: 5,
  type: 'field',
  name: '字段3',
  prev: [1],
  next: [4]
}, {
  id: 6,
  type: 'field',
  name: '字段4',
  prev: [1],
  next: [4]
}, {
  id: 3,
  type: 'end',
  name: '结束',
  prev: [4],
  next: []
}]

vue 文件

<template>
  <div class="canvas" ref="canvas"></div>
</template>
import {dia, layout, shapes} from 'jointjs'
import dagre from 'dagre'
import graphlib from '@dagrejs/graphlib'
import data from "./data"
export default {
  data() {
    return {
      graph: null,
      paper: null,
      items: data,
      nodeSet: {}
    }
  },
  mounted() {
    this.init()
    this.render()
  },
  methods: {
    init() {
      const canvasRect = this.$refs.canvas.getClientRects()[0]
      this.graph = new dia.Graph()
      this.paper = new dia.Paper({
        el: this.$refs.canvas,
        model: this.graph,
        width: canvasRect.width,
        height: canvasRect.height,
        gridSize: 1
      })
      // See https://resources.jointjs.com/docs/jointjs/v3.3/joint.html#dia.Paper.events
      this.paper.on('element:pointerclick', (cell) => {
        Object.keys(this.nodeSet).forEach(item => {
          if (this.nodeSet[item].id === cell.model.id) {
            console.log(item) // 当前点击元素id
            console.log(data[item]) // 当前点击元素内容
          }
        })
      })
    },
    render() {
      const {nodes, links, nodeSet} = this

      nodes.forEach((node) => {
        const option = {
          size: {
            width: 100,
            height: 40
          },
          attrs: {
            body: {
              fill: '#ddd',
              strokeWidth: 1,
              stroke: '#ccc'
            },
            label: {
              text: node.name,
              fill: '#333'
            }
          }
        }
        let item
        if (node.type === 'start' || node.type === 'end') {
          item = new shapes.standard.Ellipse(option)
        } else {
          item = new shapes.standard.Rectangle(option)
        }
        item.addTo(this.graph)

        nodeSet[node.id] = item
      })

      links.forEach(([from, to]) => {
        const link = new shapes.standard.Link({
          source: nodeSet[from],
          target: nodeSet[to],
          attrs: {
            line: {
              stroke: '#aaa'
            }
          }
        })
        link.addTo(this.graph)
      })
      this.doLayout()
    },
    doLayout() {
      layout.DirectedGraph.layout(this.graph, {
        dagre: dagre,
        graphlib: graphlib,
        setLinkVertices: false,
        rankDir: 'LR', //节点方向 有几个选项 "TB" (top-to-bottom) / "BT" (bottom-to-top) / "LR" (left-to-right) / "RL" (right-to-left)
        align: 'DL',
        rankSep: 50,
        marginX: 60,
        marginY: 60,
        nodeSep: 50,
        edgeSep: 20
      })
    }
  },
  computed: {
    nodes() {
      const nodes = []

      this.items.forEach(item => {
        nodes.push(item)
      })

      return nodes
    },
    links() {
      const links = []

      this.items.forEach(item => {
        item.next.forEach(p => {
          links.push([item.id, p])
        })
      })

      return links
    }
  }
}
</script>

效果
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值