antv g6 学习笔记

5,253 阅读6分钟

官方文档地址:g6.antv.vision/zh/

G6介绍

G6 是一个图可视化引擎。它提供了图的绘制、布局、分析、交互、动画等图可视化的基础能力。旨在让关系变得透明,简单。让用户获得关系数据的 Insight

安装 & 引用

  1. 安装
npm install --save @antv/g6
  1. 引用
import G6 from '@antv/g6';

使用

  1. 创建dom容器
<div id="mountNode"></div>
  1. 数据 数据分为节点(nodes)和边(edges)两种类型分别代表节点和线
const data = {
  // 点集
  nodes: [
    {
      id: 'node1', // String,该节点存在则必须,节点的唯一标识
      x: 100, // Number,可选,节点位置的 x 值
      y: 200, // Number,可选,节点位置的 y 值
    },
    {
      id: 'node2', // String,该节点存在则必须,节点的唯一标识
      x: 300, // Number,可选,节点位置的 x 值
      y: 200, // Number,可选,节点位置的 y 值
    },
  ],
  // 边集
  edges: [
    {
      source: 'node1', // String,必须,起始点 id
      target: 'node2', // String,必须,目标点 id
    },
  ],
};

3.实例化

const graph = new G6.Graph({
  container: 'mountNode', // String | HTMLElement,必须,在 Step 1 中创建的容器 id 或容器本身
  width: 800, // Number,必须,图的宽度
  height: 500, // Number,必须,图的高度
});

4.配置数据源,渲染

graph.data(data); // 读取 Step 2 中的数据源到图上
graph.render(); // 渲染图

实例化具体的配置项可以参考这里

布局方式

  1. Graph布局包括以下几种布局方式:
  • Random Layout:随机布局;
  • Force Layout:经典力导向布局:
  • Circular Layout:环形布局;
  • Radial Layout:辐射状布局;
  • MDS Layout:高维数据降维算法布局;
  • Fruchterman Layout:Fruchterman 布局,一种力导布局;
  • Dagre Layout:层次布局;
  • Concentric Layout:同心圆布局,将重要(默认以度数为度量)的节点放置在布局中心;
  • Grid Layout:格子布局,将节点有序(默认是数据顺序)排列在格子上;
  • Combo Force Layout:V3.5 新增。适用于带有 combo 图的力导向布局,推荐有 combo 的图使用该布局。 具体的配置项可以参考这里
  1. TreeGraph布局包括以下几种布局方式:

点集

G6 的内置节点包括 circle,rect,ellipse,diamond,triangle,star,image,modelRect。 如果不能满足业务也可以用下面的自定义点集

自定义点集

使用G6.registerNode(nodeName, options, extendedNodeName)来自定义点集然后在实例化的时候传入

G6.registerNode(
  'nodeName',
  {
    /**
     * 绘制节点,包含文本
     * @param  {Object} cfg 节点的配置项
     * @param  {G.Group} group 图形分组,节点中的图形对象的容器
     * @return {G.Shape} 绘制的图形,通过 node.get('keyShape') 可以获取到
     */
    draw(cfg, group) {},
    /**
     * 绘制后的附加操作,默认没有任何操作
     * @param  {Object} cfg 节点的配置项
     * @param  {G.Group} group 图形分组,节点中的图形对象的容器
     */
    afterDraw(cfg, group) {},
    /**
     * 更新节点,包含文本
     * @override
     * @param  {Object} cfg 节点的配置项
     * @param  {Node} node 节点
     */
    update(cfg, node) {},
    /**
     * 更新节点后的操作,一般同 afterDraw 配合使用
     * @override
     * @param  {Object} cfg 节点的配置项
     * @param  {Node} node 节点
     */
    afterUpdate(cfg, node) {},
    /**
     * 设置节点的状态,主要是交互状态,业务状态请在 draw 方法中实现
     * 单图形的节点仅考虑 selected、active 状态,有其他状态需求的用户自己复写这个方法
     * @param  {String} name 状态名称
     * @param  {Object} value 状态值
     * @param  {Node} node 节点
     */
    setState(name, value, node) {},
    /**
     * 获取锚点(相关边的连入点)
     * @param  {Object} cfg 节点的配置项
     * @return {Array|null} 锚点(相关边的连入点)的数组,如果为 null,则没有锚点
     */
    getAnchorPoints(cfg) {},
  },
  'extendedNodeName',
);

自定义边集

使用registerEdge(edgeName, options, extendedEdgeName)自定义边集 然后在实例化的时候传入

G6.registerEdge(
  'edgeName',
  {
    /**
     * 绘制边,包含文本
     * @param  {Object} cfg 边的配置项
     * @param  {G.Group} group 图形分组,边中的图形对象的容器
     * @return {G.Shape} 绘制的图形,通过 node.get('keyShape') 可以获取到
     */
    draw(cfg, group) {},
    /**
     * 绘制后的附加操作,默认没有任何操作
     * @param  {Object} cfg 边的配置项
     * @param  {G.Group} group 图形分组,边中的图形对象的容器
     */
    afterDraw(cfg, group) {},
    /**
     * 更新边,包含文本
     * @override
     * @param  {Object} cfg 边的配置项
     * @param  {Edge} edge 边
     */
    update(cfg, edge) {},
    /**
     * 更新边后的操作,一般同 afterDraw 配合使用
     * @override
     * @param  {Object} cfg 边的配置项
     * @param  {Edge} edge 边
     */
    afterUpdate(cfg, edge) {},
    /**
     * 设置边的状态,主要是交互状态,业务状态请在 draw 方法中实现
     * 单图形的边仅考虑 selected、active 状态,有其他状态需求的用户自己复写这个方法
     * @param  {String} name 状态名称
     * @param  {Object} value 状态值
     * @param  {Edge} edge 边
     */
    setState(name, value, edge) {},
  },
  'extendedEdgeName',
);

绘制函数

使用draw(cfg, group)来自定义边集和点集 使用addGroup(cfg)来添加内置的边集

draw(cfg, group) {
    const styles = this.getShapeStyle(cfg);
    const { labelCfg = {} } = cfg;
    
    const w = styles.width;
    const h = styles.height;
    
    const keyShape = group.addShape("rect", {
    attrs: {
        ...styles,
        x: -w / 2,
        y: -h / 2,
        fill: cfg.depth == 1 ? "#3366ff" : "#fff",
        },
    });
    
    if (cfg.label) {
        group.addShape("text", {
            attrs: {
                // ...labelCfg.style,
                text: cfg.label,
                x: 50 - w / 2,
                y: 25 - h / 2,
                stroke: cfg.depth == 1 ? "#fff" : "#666",
                fontWeight: 100,
                fontSize: 10,
                textAlign: "center",
            },
            });
        }
        return keyShape;
    }

Event事件

使用如下形式进行交互事件的监听:

this.graph.on("node:mouseleave", (evt) => {
    const { item, target } = evt;
    this.show.button = false;
    this.graph.setItemState(item, "hover", false);
});

其中,事件对象 evt 的属性值有:

  • node:click 鼠标左键单击节点时触发
  • node:dblclick 鼠标双击左键节点时触发,同时会触发两次 node:click
  • node:mouseenter 鼠标移入节点时触发
  • node:mousemove 鼠标在节点内部移到时不断触发,不能通过键盘触发
  • node:mouseout 鼠标移出节点后触发
  • node:mouseover 鼠标移入节点上方时触发
  • node:mouseleave 鼠标移出节点时触发
  • node:mousedown 鼠标按钮在节点上按下(左键或者右键)时触发,不能通过键盘触发
  • node:mouseup 节点上按下的鼠标按钮被释放弹起时触发,不能通过键盘触发
  • node:dragstart 当节点开始被拖拽的时候触发的事件,此事件作用在被拖曳节点上
  • node:drag 当节点在拖动过程中时触发的事件,此事件作用于被拖拽节点上
  • node:dragend 当拖拽完成后触发的事件,此事件作用在被拖曳节点上
  • node:dragenter 当拖曳节点进入目标元素的时候触发的事件,此事件作用在目标元素上
  • node:dragleave 当拖曳节点离开目标元素的时候触发的事件,此事件作用在目标元素上
  • node:dragover 当拖曳节点在另一目标元素上移动时触发此事件,此事件作用在目标元素上
  • node:drop 被拖拽的节点在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上
  • node:contextmenu 用户在节点上右击鼠标时触发并打开右键菜单

Graph 实例常用的方法

方法含义
addChild(data, parent)在指定的父节点下添加子树。
updateChild(data, parent)更新数据,差量更新子树。
removeChild(id)删除指定的子树。
save()获取图数据。

元素 实例常用的方法

方法含义
item.getModel()获取元素的数据模型
item.setState(state, enable)更新元素的状态。