为了账号安全,请及时绑定邮箱和手机立即绑定

g6 核心

标签:
动效动画


https://img3.sycdn.imooc.com/5fef287c0001767718041310.jpg


      // 创建 G6 图实例
      const graph = new G6.Graph({
        container: 'mountNode', // 指定图画布的容器 id,与第 9 行的容器对应
        // 画布宽高
        width: 800,
        height: 500,
      });
      // 读取数据
      graph.data(data);
      // 渲染图
     graph.render();
	//监听
	graph.on()

Graph 对象的生命周期为:初始化 —> 加载数据 —> 渲染 —> 更新 —> 销毁。

必要配置项

上面代码中实例化 Graph 的部分使用了三个必要的配置项:

  • container

  • widthheight

常用配置项

使用 canvas 或 svg 渲染

  • renderer

自适应画布

  • fitView

  • fitViewPadding

  • fitCenter

全局元素配置

  • defaultNode

  • defaultEdge

  • nodeStateStyles

  • edgeStateStyles

布局相关

  • layout

交互行为相关

  • modes

动画相关

  • animate

  • animateCfg

插件

  • plugins

图形

每个图元素由图形(Shape) 组成,且都会有自己的唯一关键图形(keyShape)。

图形 Shape

  • circle:圆;

  • rect:矩形;

  • ellipse:椭圆;

  • polygon:多边形;

  • fan:扇形;

  • image:图片;

  • marker:标记;

  • path:路径;

  • text:文本;

  • dom(svg):DOM

各图形 Shape 的通用方法

attr(name)

获取实例的属性值。

attr(name, value)

更新实例的单个绘图属性。

attr({...})

批量更新实例绘图属性。

KeyShape

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg

group

  • addGroup(cfgs)

  • addShape(type, cfgs)


变换

  • 获取当前矩阵:getMatrix();

  • 设置矩阵:setMatrix(matrix) 或 attr('matrix', matrix);

  • 重置矩阵:resetMatrix()。

图元素

图的元素(Item)包含图上的节点 Node 、边 Edge 和 Combo 三大类。

  • 样式属性,通过 style 字段对象进行配置,和元素的关键图形相关,例如 fillstroke

  • 其他属性,例如 idtype,不能在元素状态改变是进行改变,可通过 graph.updateItem 进行手动更新。

节点

G6 的内置节点包括 circle,rect,ellipse,diamond,triangle,star,image,modelRect。这些内置节点的默认样式分别如下图所示。
https://img4.sycdn.imooc.com/5fef287f0001083e15280206.jpg

定义方式

// 1  
defaultNode: {
    type: 'circle',
    // 其他配置
  }

//2
graph.node((node) => {
  return {
    id: node.id,
    type: 'rect',
    style: {
      fill: 'blue',
    },
  };
});

graph.data(data);
graph.render();

//3
const data = {
  nodes: [
    {
      id: 'node_circle',
      x: 100,
      y: 100,
      type: 'circle',
      label: 'circle',
    },]
}

自定义

G6.registerNode(
  'nodeName',
  {
    options: {
      style: {},
      stateStyles: {
        hover: {},
        selected: {},
      },
    },
    /**
     * 绘制节点,包含文本
     * @param  {Object} cfg 节点的配置项
     * @param  {G.Group} group 图形分组,节点中图形对象的容器
     * @return {G.Shape} 返回一个绘制的图形作为 keyShape,通过 node.get('keyShape') 可以获取。
     * 关于 keyShape 可参考文档 核心概念-节点/边/Combo-图形 Shape 与 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) {},
    /**
     * 响应节点的状态变化。
     * 在需要使用动画来响应状态变化时需要被复写,其他样式的响应参见下文提及的 [配置状态样式] 文档
     * @param  {String} name 状态名称
     * @param  {Object} value 状态值
     * @param  {Node} node 节点
     */
    setState(name, value, node) {},
    /**
     * 获取锚点(相关边的连入点)
     * @param  {Object} cfg 节点的配置项
     * @return {Array|null} 锚点(相关边的连入点)的数组,如果为 null,则没有控制点
     */
    getAnchorPoints(cfg) {},
  },
  // 继承内置节点类型的名字,例如基类 'single-node',或 'circle', 'rect' 等
  // 当不指定该参数则代表不继承任何内置节点类型
  extendedNodeName,
);

连接方式

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg


// 接入点
    anchorPoints: [
        [0, 1],
        [0.5, 1],
      ],

jsx写法

<[group|shape] [key]="value" style={{ [key]: value }}>
  <[more tag] /> ...
  <text>value</text>
</[group|shape]>


  • line:直线,不支持控制点;

  • polyline:折线,支持多个控制点;

  • arc:圆弧线;

  • quadratic:二阶贝塞尔曲线;

  • cubic:三阶贝塞尔曲线;

  • cubic-vertical:垂直方向的三阶贝塞尔曲线,不考虑用户从外部传入的控制点;

  • cubic-horizontal:水平方向的三阶贝塞尔曲线,不考虑用户从外部传入的控制点;

  • loop:自环。

定义方式: 与节点类似

箭头:

//默认
style: {
  endArrow: true,
  startArrow: true
}
//内置 6种
endArrow: {
// 使用内置箭头路径函数,参数为箭头的 宽度、长度、偏移量(默认为 0,与 d 对应)
path: G6.Arrow.triangle(10, 20, 25),
d: 25
}
// 自定义箭头
// 只有内置箭头和自定义箭头可以配置样式
style: {
  endArrow: {
    path: 'M 0,0 L 20,10 L 20,-10 Z',
    d: 5,
    fill: '#f00',
    stroke: '#0f0',
    opacity: 0.5,
    lineWidth: 3,
    // ...
  },
}

自定义:同节点


combo

G6 的内置 Combo 包括 circle 和 rect 两种类型

对于熟悉图可视化类库的用户来说,节点分组是非常实用的一个功能

G6 已经存在一个节点分组 Node Group 功能,但它的机制无法支持一些较复杂的功能,例如:带有节点分组的图布局、自定义 Combo、嵌套节点分组的均匀 padding、节点与分组的边、分组与分组的边、空的节点分组等

V3.5 推出了全新的节点分组 Combo 机制,能够支持所有常用功能

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg



{
  nodes: [
    {
      id: 'node1',
      comboId: 'comboA' // node1 属于 comboA
    },
    {
      id: 'node2',
      comboId: 'comboB' // node2 属于 comboB
    },
    {
      id: 'node3' // node3 不属于任何 combo
    },
    // ...
  ],
  edges: [
    // ...
  ],
  combos: [
    { // 定义 comboA
      id: 'comboA',
      label: 'A',
      parentId: 'comboC'
    },
    { // 定义 comboB
      id: 'comboB',
      parentId: 'comboB'
    },
    { // 定义 comboC,这是一个空的 combo
      id: 'comboC'
    },
    // ...
  ]
}

其他内容:类似与节点





高级样式

背景

 defaultNode: {
    position: 'left',
    style: {
      background: {
        fill: '#ffffff',
        stroke: 'green',
        padding: [3, 2, 3, 2],
        radius: 2,
        lineWidth: 3,
      },
    },


三种方式更新文本样式

// 1. 实例化默认
  defaultNode: {
    type: 'node',
    labelCfg: {
      style: {
        fill: '#fff',
        fontSize: 14,
      },
    },
  },
// 2.数据指定
const data = {
  nodes: [
    {
      id: 'node1',
      label: 'node1',
      labelCfg: {
        style: {
          fill: '#fff',
          fontSize: 12,
        },
      },
    },
  ],
};
// 3.update/updateItem

graph.updateItem(node, {
  // 节点的样式
  style: {
    stroke: 'blue',
  },
  // 节点上文本的样式
  labelCfg: {
    style: {
      fill: '#fff',
      fontSize: 12,
    },
  },
});

渐变色/纹理

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg

操作

更新样式

更新节点边: 三种方式


层级

所有节点会绘制在所有边的上层

先绘制图形在后绘制图形后边

toFront() 与 toBack()


显示/隐藏

show()/hide()


多条边

https://img1.sycdn.imooc.com/5acb3c8700013dc501600160.jpg

自定义边 edgeType




锁定/解锁

lock()unlock() 和 hasLocked()

不可拖动

不可缩放



图布局


一般布局

  • Random Layout:随机布局;

  • Force Layout:G6 4.0 支持的经典力导向布局,支持 GPU 并行计算;

  • Force Layout:引用 d3 的经典力导向布局;

  • Fruchterman Layout:Fruchterman 布局,一种力导布局;

  • Circular Layout:环形布局;

  • Radial Layout:辐射状布局;

  • MDS Layout:高维数据降维算法布局;

  • Dagre Layout:层次布局;

  • Concentric Layout:同心圆布局;

  • Grid Layout:网格布局;

  • Combo Force Layout:V3.5 新增。适用于带有 combo 图的力导向布局,推荐有 combo 的图使用该布局。

树图

  • CompactBox Layout:紧凑树布局;

  • Dendrogram Layout:树状布局(叶子节点布局对齐到同一层);

  • Indented Layout:缩进布局;

  • Mindmap Layout:脑图布局。


布局切换

  • updateLayout(params):布局方法或参数的切换;

graph.updateLayout({
          type: 'force', // 布局名称
          preventOverlap: true, // 布局参数,是否允许重叠
          nodeSize: 40, // 布局参数,节点大小,用于判断节点是否重叠
          linkDistance: 100, // 布局参数,边长
        });


  • changeData():数据的切换。

        graph.changeData(data2);


子图

子图布局独立与全局布局的思路,与 graph 不挂钩,直接使用实例化布局方法的方式,灌入子图数据,通过布局将位置写到相应数据中。这种机制还可供外部的全局布局使用,即使不用 G6 渲染,也可以计算节点布局后的位置

// 实例化布局
const subgraphLayout = new G6.Layout['force']({
  center: [500, 450],
});

// 初始化布局,灌入子图数据
subgraphLayout.init({
  nodes: subGraphNodes,
  edges: subGraphEdges,
});

// 执行布局
subgraphLayout.execute();

// 图实例根据数据更新节点位置
graph.positionsAnimate();


webworker

在大规模图可视化中,布局算法往往需要较大的计算量。




    workerEnabled: true, // 开启 Web-Worker


  • 树图不支持 Web-Worker 机制;

  • 子图布局机制暂不支持 Web-Worker 机制。

自定义布局

  getDefaultCfg() {
    return {};
  },
  /**
   * 初始化
   * @param {object} data 数据
   */
  init(data) {},
  /**
   * 执行布局
   */
  execute() {},
  /**
   * 根据传入的数据进行布局
   * @param {object} data 数据
   */
  layout(data) {},
  /**
   * 更新布局配置,但不执行布局
   * @param {object} cfg 需要更新的配置项
   */
  updateCfg(cfg) {},
  /**
   * 销毁
   */
  destroy() {},
});


布局预测



import { GraphLayoutPredict } from '@antv/vis-predict-engine'

const { predictLayout, confidence } = await GraphLayoutPredict.predict(data);
const graph = new G6.Graph({
  // 省略其他配置
    layout: {
    type: predictLayout
  }
})



交互与事件

监听/绑定

  • 画布、图形层次的事件,mousedownmouseupclickmouseentermouseleave 等;

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

  • 时机事件:

    • 节点/边增删改时的事件, 例如:beforeadditemafteradditem  等;

    • 节点/边状态改变时的事件:beforerefreshitem 与 afterrefreshitem

    • 布局时机:beforelayout 与 afterlayout


graph.on('click', (ev) => {
  const shape = ev.target;
  const item = ev.item;
  if (item) {
    const type = item.getType();
  }
});

graph.on('node:click', (ev) => {
  const shape = ev.target;
  const node = ev.item;
});


内置 behavior

ehavior 是 G6 提供的定义图上交互事件的机制。

G6 目前共提供了以下 14 个内置的 Behavior。

drag-combo
collapse-expand-combo
drag-canvas
zoom-canvas
drag-node
click-select
tooltip
edge-tooltip
activate-relations
brush-select
lasso-select
collapse-expand
create-edge
shortcuts-call

自定义交互 Behavior

在交互行为上, G6 主要考虑了三个场景:

  • 展示关系数据;

  • 可视化建模;

  • 图分析。

在这些场景中只要用户可能无法一眼看清楚所有需要的信息,都需要进行交互,例如:

  • 图太大,需要缩放;

  • 单个节点上展示的信息太少,需要通过 tooltip 显示详情;

  • 对节点进行增删改查。


交互模式 Mode

  • default 模式中包含点击选中节点行为和拖拽画布行为;

  • edit 模式中包含点击节点弹出编辑框行为和拖拽节点行为。

  modes: {
    // 支持的 behavior
    default: ['drag-canvas', 'zoom-canvas'],
    edit: ['click-select'],
  },

// 解绑目前图模式的所有事件监听;
// 生成新的 Behavior ,进行事件初始化;
// 绑定新的行为对应的事件监听。
graph.setMode('edit');

graph.addBehaviors
graph.removeBehaviors


状态State

判断是否该使用 state 的原则很简单,从交互和业务两个层面来看:

  • 某个交互动作要改变节点或边的样式及属性;

  • 呈现给用户的内容会根据数据改变(如 1 代表成功,0 代表失败)。

满足上述条件其一,则应该使用 state。



在 G6 中,有两种方式配置不同状态的样式:

  • 在实例化 Graph 时,通过 nodeStateStyles 和 edgeStateStyles 对象定义;

  • 在节点/边数据中,在 stateStyles 对象中定义状态;


  • 设置状态:setItemState 

  • 取消状态:clearItemStates 

  • 更新状态:updateItem 



graph.setItemState(item, stateName, stateValue) 

graph.clearItemStates(item, 'selected');

// 实例化
 nodeStateStyles: {

  },

//数据
  stateStyles: {
      },

//updataItem
stateStyles: {
    // 修改 hover 状态下的样式
    hover: {
      opacity: 0.1,
      // 修改 name 为 'node-label' 的子图形 hover 状态下的样式
      'node-text': {
        stroke: 'blue',
      },
    },
  },

//优先级
item.hasState('active');



插件

  • Grid

  • Minimap

  • ImageMinimap

  • Edge Bundling

  • Menu

  • ToolBar

  • TimeBar

  • Tooltip

  • Fisheye

  • EdgeFilterLens


// 实例化 Image Minimap 插件
const imageMinimap = new G6.ImageMinimap({
  width: 200,
  graphImg: 'https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*eD7nT6tmYgAAAAAAAAAAAABkARQnAQ'
});
const graph = new G6.Graph({
  //... 其他配置项
  plugins: [imageMinimap], // 配置 imageMinimap 插件
});


图算法



计算nodes,edges x/y


动画

全局

//全局
 animate: true, // Boolean,切换布局时是否使用动画过度,默认为 false
graph.updateLayout(cfg) 布局的变化
graph.changeData() 数据的变化

元素

  • 节点上图形的动画

  • 增加带有动画的背景图形

  • 节点上部分图形的旋转动画

  • 圆点在沿着线运动

  • 虚线运动的效果

  • 线从无到有的效果

//开始
 shape.animate(
        (ratio) => {
          // 每一帧的操作,入参 ratio:这一帧的比例值(Number)。返回值:这一帧需要变化的参数集(Object)。
          // 先变大、再变小
          const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
          let radius = cfg.size;
          if (isNaN(radius)) radius = radius[0];
          // 返回这一帧需要变化的参数集,这里只包含了半径
          return {
            r: radius / 2 + diff,
          };
        },
        {
          // 动画重复
          repeat: true,
          duration: 3000,
          easing: 'easeCubic',
        },
      ); // 一次动画持续的时长为 3000,动画效果为 'easeCubic'
          
//结束
shape.stopAnimate();




点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
76
获赞与收藏
1245

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消