在Vue中使用Antv G6

11,668 阅读7分钟

1. 前言

笔者最近在做一些可视化方面的任务,具体的需求就是要在页面上绘制出树状的关系图。在参考并且对比了社区的主流方案后,最后选择了Antv G6。在使用的过程也遇到了一些问题,就想写篇博客记录一下。

2. 介绍

Antv G6是蚂蚁数据可视化团队开源的一个图可视化引擎。它在高定制能力的基础上,提供了一系列设计优雅、便于使用的图可视化解决方案。能帮助开发者搭建属于自己的图可视化、图分析、或图编辑器应用。

3. 搭建

项目使用Vue-cli搭建,仍然使用Vue2.x的版本。搭建时的配置按照实际的需求来即可,这边我们选择默认的配置。具体配置可以看vue-cli这里不展开了。然后是下载Antv g6,最后在需要使用的文件引入即可。

#step1: 创建项目
vue create antv-demo

#step2: 在项目目录中,使用如下命令下载Antv g6
npm install --save @antv/g6

#step3: 引入Antv g6
import G6 from '@antv/g6';

4. 核心概念

在正式使用之前,我们先来了解一下Antv G6中的一些核心概念。下面这个是官方提供的思维导图。由于有些功能笔者也没有深入的使用,故这里不做介绍,大家可以在官网中查阅。

4.1 Graph

在G6中,Graph对象可以说是图的载体,它包含图的所有元素,并且挂载了图的各种操作。Graph也有生命周期这一概念,初始化 —> 加载数据 —> 渲染 —> 更新 —> 销毁。要想实现图的可视化,我们的第一步就是实例化一个Graph对象。

//实例化Graph
const graph = new G6.Graph({
    container: "", // 指定图画布的容器,可以直接传容器的id也可以传一个DOM 对象
    width: 800,// 画布宽高
    height: 800
})

执行上面这段代码后,返回一个Graph对象,我们后续的各种操作都需要通过它进行。另外上面这些只是初始化时的必要配置项,更多的配置请在官网查阅。

4.2 图元素

图元素包括节点(Node)、边(Edge)、Combo(类似于Node Group)这三类。每个图元素都可以由多个Shape组成,但是他们都只能由一个KeyShape。这里提到的Shape其实就是简单的图形,比如说矩形,圆形,文本等等。G6中内置了很多节点,边和Combo,此外G6还提供了自定义的能力,通过自己搭配和组合 shape 进行节点/边/ Combo 的自定义。图元素具有很多公共的通用属性和通用方法,而且不同的图元素还有特殊的一些属性、方法。

4.3 图布局

我们的图元素需要以怎样的布局展示在画板上。G6内置多种的布局算法,可以计算出每个图元素的坐标信息。布局的算法仅仅是计算出元素的x、y,不处理渲染的任务,因此我们也可以引用外部的算法计算坐标,再让G6渲染。

4.4 交互与事件

G6提供比较丰富的交互能力,这里涉及几个比较重要的概念我们分开介绍。

4.4.1 Behavior

Behavior是G6提供的定义图上交互事件的机制,比如说拖拽,缩放等,这些都是内置的Behavior,此外我们还可以注册自定义Behavior。使用它的时候要于交互模式一起使用。

4.4.2 交互模式 Mode

我们可以通过设置mode去管理Behavior。至于为什么会出现这个概念,我们可以想象一个场景,当用户选择了编辑模式是需要拖拽节点的,而只读模式则不需要这个交互。所以G6提供了这样的一种机制去管理。默认就是default模式。

4.4.3 状态 State

G6 中的 state,指的是节点或边的状态。经常会出现触发某种事件/交互后要改变某种状态这样的场景。我们就可以通过设置State实现,另外我们也可以给不同的State配置样式。

4.4.4 监听和绑定事件

除了上述的事件管理能力外,我们还可以直接对某个事件或者时机的监听。在G6中事件可以被分成以下几类:

  • 画布、图形层次的事件,mousedown,mouseup,click,mouseenter,mouseleave 等;

  • 节点/边 上的事件,node:mousedown,edge:click 等,以 type:eventName 为事件名称;

  • 时机事件:

    • 节点/边增删改时的事件, 例如:beforeadditem,afteradditem 等;
    • 节点/边状态改变时的事件:beforerefreshitem 与 afterrefreshitem;
    • 布局时机:beforelayout 与 afterlayout。

上面就是基本的一些概念,接下来我们开始实战的环节。

5.使用

这里我们实现一个简单的demo,用darge布局实现一个树状的结构,这里简单封装了一个GraphVisual的类去实现graph的初始化和渲染。至于为什么不采用TreeGraph,这个会在下一节提到。

5.1 实例化Graph

通过传入的参数实例化Graph,除了一些必要的配置外,我们还定义了节点和边的样式,指定了图的布局算法,还有交互方式。

initGraph(){
    const container = this.container
    const {width, height, direction} = this.config
    const graph = new G6.Graph({
      container,
      width,
      height,
      modes: {
        default: ['drag-canvas', 'zoom-canvas'] //指定默认模式下的交互方式
      },
      defaultEdge: {
        type: 'line' //指定边的类型
      },
      defaultNode: {
        type: 'rect',
        size: [60, 30],
        //指定边链接的点
        anchorPoints: [[0.5, 0], [0.5, 1]]
      },
      //设置图布局算法
      layout: {
        type: 'dagre',
        rankdir: direction,
        ranksep: 20,
        nodesep: 20
      }
    })
    this.graph = graph
 }

5.2 数据处理和渲染

初始化的图数据,是一个包括 nodes 数组和 edges 数组的对象,我们要将数据转化成这种形式。再通过graph的data方法绑定,最后调用graph的render方法将元素渲染到画板上。

const data = {
  nodes: [
    {
      id: 'node1',
      label: 'node1',
    },
    {
      id: 'node2',
      label: 'node2',
    },
  ],
  edges: [
    {
      source: 'node1',
      target: 'node2',
    },
  ],
}

this.graph.data(data)
this.graph.render()

5.3 在Vue中使用

通过ref获得dom对象,并将data一起传入到GraphVisual中。最后我们预览一下运行的结果。

<template>
  <div id="app" ref="container"/>
</template>

<script>
import {treeData} from './data'
import {GraphVisual} from './utils/MatchVisual'
export default {
  name: 'App',
  components: {},
  data() {
    return {
      treeData
    }
  },
  mounted(){
    new GraphVisual(this.$refs.container, this.treeData)
  }
}
</script>

由于Antv G6的api比较多,可以实现的图种类也很丰富。这里笔者就不详细去用demo实现介绍了,感兴趣的可以查看官网上的样例。

6. 之前使用遇到的问题

6.1 性能问题

笔者之前在做将1000+的节点数据渲染成树图结构的时候,首屏渲染耗时去到6,7秒。刚开始的时候没有搞清楚问题出在哪里。官方提供的一个性能demo,在节点数量50000+的情况下才出现,交互上的卡顿,而且首屏的加载也不过8s左右。后来在github的issue上找到了答案,实现的时候edge使用的是polyline类型,由于polyline 自动巡径算法复杂度很高,导致了渲染性能的问题。后面采用了自定义实现polyline的方式,现在的渲染速度已经在1s内了。

6.2 布局问题

同样是在做树图布局的时候遇到的问题。在数据的层级比较多的情况下,最后一层的节点总是会重叠在一起。按照官方的一些布局配置也没有解决。最后用了一个比较粗暴的办法,直接设定节点的占位宽度。可能有更好的解决办法不过我暂时还没有找到。

6.3 TreeGraph

树图布局提供了很强大的能力,基本可以满足树图的需求。不过目前TreeGraph还不可以搭配combo去使用,在前一节我们也提到了为什么不使用TreeGraph,就是出于这个原因考虑的。参考了一些布局demo后决定改用dagre, 基本可以还原TreeGraph。

7. 写在最后

由于笔者的经验不是很丰富,接触Antv G6也没有很久,如果在文章中有出错的地方,欢迎大家指出。