阅读 671

初识g6:编辑可视化流程图

最近接到有关制作流程图编辑器的需求,于是了解了一下关于@antv/g6相关的资料,了解到它更迭过很多版本,如今已经是3.6版本,每个版本api变化还是比较大的,由于只是当前需求不是很严格,所以选择了1.x版本,先来看看效果:

g6的引入

1.x版本中,暂时不支持npm安装,所以需要采用浏览器引入

<script src="https://gw.alipayobjects.com/os/antv/assets/g6/1.2.8/g6.min.js"></script>
复制代码

浏览器引入的方式引入会影响首屏加载,如果想按需引入,可以在当前目录下动态创建标签:

(() => {
  const script = document.createElement('script')
  script.src = '//gw.alipayobjects.com/os/antv/assets/g6/1.2.8/g6.min.js'
  const s = document.getElementsByTagName('script')[0]
  s.parentNode.insertBefore(script, s)
})()
复制代码

初始化g6容器

首先需要一个容器来放置我们的g6

<div id="flowChart"></div>
复制代码

页面挂载完成后调用initG6方法进行初始化:

initG6 () {
  const self = this
  self.Util = G6.Util
  let grid
  if (self.checked) {
    grid = {
      forceAlign: true, // 是否支持网格对齐
      cell: 25 // 网格大小
    }
  } else {
    grid = null
  }
  self.net = new G6.Net({
    id: 'flowChart', // 容器ID
    mode: 'edit',
    grid: grid,
    height: 700 // 画布高
  })
  /**
   *点击空白处
    */
  self.net.on('click', (ev) => {
    if (!self.Util.isNull(ev.item)) {
      self.isBlank = false
    } else {
      self.isBlank = true
      self.infoTitle = '画布'
    }
  })
  /**
   *点击节点或者边
    */
  self.net.on('itemclick', function (ev) {
    self.isNode = self.Util.isNode(ev.item) // 是否为Node
    self.activation = ev.item
    if (self.isNode) {
      /* 激活节点后节点名称input聚焦 */
      self.$nextTick(() => {
        self.$refs.inputFocus.$el.querySelector('input').focus()
      })
      self.infoTitle = '节点'
      self.name = ev.item.get('model').label
      self.func = ev.item.get('model').func
      self.account = ev.item.get('model').account || []
      self.workflow = ev.item.get('model').workflow
      self.nodeType = ev.item.get('model').nodeType
    } else {
      self.$nextTick(() => {
        self.$refs.textInput.$el.querySelector('input').focus()
      })
      self.infoTitle = '边'
      self.text = ev.item.get('model').label
      self.action = ev.item.get('model').action
    }
    self.color = self.oldColor
  })
  /**
   * 鼠标移入移出事件改变颜色
   */
  self.net.on('itemmouseenter', ev => {
    const item = ev.item
    self.oldColor = item.get('model').color // 获取节点颜色
    self.net.update(item, {
      color: '#108EE9'
    })
    self.net.refresh()
  })
  self.net.on('itemmouseleave', ev => {
    const item = ev.item
    self.net.update(item, {
      color: self.oldColor
    })
    self.net.refresh()
  })
  /**
   * 提示信息
   */
  self.net.tooltip(true)
  self.net.edge().tooltip((obj) => {
    return [
      ['label', obj.label || 'null'],
      ['color', obj.color]
    ]
  })
  self.net.node().tooltip((obj) => {
    return [
      ['label', obj.label],
      ['color', obj.color]
    ]
  })
  /**
   * 渲染
   */
  self.net.render()
}
复制代码

我们可以看到g6有两种类型:node节点和edge,即节点和边

node有以下几种shape:

  • circle 圆形
  • html html
  • rect 矩形
  • image 图片
  • rhombus 菱形
  • text 文本
  • tree-node 树节点

edge有以下几种:

  • line 直线
  • smooth 曲线
  • smoothArrow 箭头曲线
  • arrow 箭头
  • ...

另外还有很多handlerEvent,需要我们仔细看文档,对照需求添加响应事件

渲染/更新/保存

点击左侧图片,即可用beginAdd事件渲染出定义好的图

// 添加圆形
this.net.beginAdd('node', {
  shape: 'circle',
  nodeType: 1,
  label: 'Start',
  color: '#ff9d00',
  size: [74, 74]
})
复制代码

监听数据的变化,触发update方法,即可实现实时更新

update () {
  if (this.activation.get('type') === 'node') {
    this.net.update(this.activation, {
      label: this.name,
      func: this.func,
      account: this.account,
      workflow: this.workflow,
      nodeType: this.nodeType,
      color: this.color
    })
  } else {
    this.net.update(this.activation, {
      label: this.text,
      color: this.color,
      action: this.action
    })
  }
}
复制代码

需要注意的网格切换的时候,需要先销毁画布

const _saveData = this.net.save()
this.net.destroy() // 销毁画布
this.initG6()
this.net.read(_saveData)
this.net.render()
复制代码

保存只需要调用G6.Net().save()方法

console.log(this.net.save().source)
复制代码

这样,一个简单的流程图制作组件就完成了,当然g6的魅力远远不止这些,快快尝试吧!