AntV G6 实际案例分享

此文章是AntV G6从零到一(Vue)的下篇博客,本文主要分享实际案例,关于AntV G6的详细内容,请参考上篇文章。

需求

本次实现的案例如下图的结构:

分析

观察UI图发现:整体结构是流程图 ;节点与节点之间具有组合 的功能;节点总体是文本加图形的上下结构;边不是G6默认边;右下角的加减号代表具有放大缩小功能。

所以接下来需要做的工作就比较清晰了:

  • 实现自定义节点
  • 实现自定义边
  • 实现组合(Combo)
  • 图布局配置
  • 整体封装

实现

自定义节点

js 复制代码
// 图片对象
const imgData = {oppositeE, oppositeR, fileE, fileR, taskE, taskR, programE, programR, entityE, entityR, kalfaE, kalfaR};
  // 注册节点
  G6.registerNode(
    'lk-node-one',
    {
      options: {
        style: {
          cursor: 'pointer',
        }
      },
      // 绘制完成以后的操作,用户可继承现有的节点或边,在 `afterDraw()` 方法中扩展图形或添加动画
      // cfg 节点的配置项
      // group 图形分组,节点中图形对象的容器
      afterDraw(cfg, group) {
        group.addShape('image', {
          // 属性配置
          attrs: {
            x: -10,
            y: -55,
            fill: '#fff',
            width: 40,
            height: 40,
            // 根据nodeType显示不同图片
            img: imgData[cfg.nodeType],
            cursor: 'pointer',
          },
          // // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
          name: 'image-shape',
        });
      },
      // 调整锚点 anchorPoint,确定节点与边的相交的位置
      getAnchorPoints() {
        return [
          [0, 0.5], // 左侧中间
          [1, 0.5], // 右侧中间
        ];
      },
    },
    'rect'
  );

自定义边

js 复制代码
G6.registerEdge('lk-line-one', {
    /** 
    * 绘制节点
    * @param {Object} cfg 节点的配置项 
    * @param {G.Group} group 图形分组,节点中图形对象的容器 
    * @return {G.Shape} 返回一个绘制的图形作为 keyShape 
    */
    draw(cfg, group) {
      // 开始节点
      const startPoint = cfg.startPoint;
      // 结束节点
      const endPoint = cfg.endPoint;
      // 图形
      const shape = group.addShape('path', {
        // 属性
        attrs: {
          // 描边颜色
          stroke: '#4e5568',
          // path是svg里面的path,M是移动画笔,moveto的缩写,L是lineto的缩写,线移动
          // 大写代表绝对定位,小写代表相对定位
          path: [
            ['M', startPoint.x + 10, startPoint.y],
            ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y], // 三分之一处
            ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y], // 三分之二处
            ['L', endPoint.x, endPoint.y],
          ],
          // 描边宽度
          lineWidth: 1,
          // 开始箭头,画圆
          startArrow: {
            // path是svg里面的path,M是移动画笔,moveto的缩写,L是lineto的缩写,线移动,a是弧形
            path: 'M 0,0 a 4 4,0,1,1, 4 4 a 4 4, 0,1,1, 4, -4',
          },
          // 结束箭头,画箭头
          endArrow: {
            // 自定义箭头指向(0, 0),尾部朝向 x 轴正方向的 path
            path: 'M 0,0 l -8,6 l 0,0 l 8,-6 l -8,-6 l 0,0 l 8,6 Z',
          },
        },
        // 在 G6 3.3 及之后的版本中,必须指定 name,可以是任意字符串,但需要在同一个自定义元素类型中保持唯一性
        name: 'edge-shape',
      });
      return shape;
    },
  });

实现组合(Combo)

文档中关于Combo的章节在这里。其中的使用方式是渲染数据中的nodes数据的comboId字段和combos数据中配置的id相匹配。

js 复制代码
export const graphData = {
  nodes: [
    {id: '0', nodeType: 'opposite', label: '统一DPI'},
    {id: '1', nodeType: 'fileE', label: '4G XDR_S1MME', comboId: 'preNode'},
    {id: '2', nodeType: 'entityR', label: 'fact_pscp_s1mme_front', comboId: 'preNode'},
    {id: '3', nodeType: 'taskR', label: 'fact_pscp_s1mme_front_sync', comboId: 'coreNode'},
    {id: '4', nodeType: 'entityR', label: 'lte_cm_projdata', comboId: 'coreNode'},
  ],
  edges: [
    {source: '0', target: '1'},
    {source: '1', target: '2'},
    {source: '2', target: '3'},
    {source: '3', target: '4'},
  ],
  combos: [
    // 前置节点
    {
      id: 'preNode',
      // 显示文本
      label: '前置节点',
      // 类型
      type: 'rect',
      size: 320,
      padding: 30,
      style: {
        stroke: '#4761f0',
        lineWidth: 1,
        lineDash: 5,
        fill: 0,
      },
      labelCfg: {
        style: {
          fill: '#4761f0',
          fontSize: 14,
        },
      },
    },
    // 核心节点
    {
      id: 'coreNode',
      label: '核心节点',
      type: 'rect',
      size: 320,
      padding: 30,
      style: {
        stroke: '#4761f0',
        lineWidth: 1,
        lineDash: 5,
        fill: 0,
      },
      labelCfg: {
        style: {
          fill: '#4761f0',
          fontSize: 14,
        },
      },
    },
  ],
};

图布局配置

js 复制代码
new G6.Graph({
    // 传入的渲染节点id
    container: id,
    // 传入的DOM ref
    width: ref.clientWidth,
    height: ref.clientHeight,
    // 自适应画布
    fitView: true,
    // 自适应画布时四周留白像素值,fitView为true时生效
    fitViewPadding: 40,
    layout: {
      // 布局类型
      type: 'dagre',
      // 从左至右布局
      rankdir: 'LR',
      // 对齐到右下角
      align: 'DR',
      // 是否保留布局连线的控制点
      controlPoints: true,
      // nodesep 节点竖直间距
      nodesepFunc: () => 20,
      // ranksep 节点水平方向层间距
      ranksepFunc: () => 20,
    },
    // 交互管理,一个mode是多种行为Behavior的组合
    modes: {
      default: ['zoom-canvas', 'drag-canvas'],
    },
    renderer: 'svg', // 使用 Dom node 的时候需要使用 svg 的渲染形势
    // 默认节点配置
    defaultNode: {
      type: 'lk-node-one',
      size: [300, 50],
      style: {
        fill: '#ffffff',
        radius: 2,
      },
      labelCfg: {
        style: {
          fill: '#333333',
          fontSize: 18,
          cursor: 'pointer',
        },
      },
    },
    defaultEdge: {
      type: 'lk-line-one',
    },
    fitCenter: true,
  });

整合封装

最后只需要将所有的配置封装到一个js文件中即可:

代码

以上代码不包含图片物料,如果需要完整案例,请访问Demo。如下所示:

总结

以上就是此次AntV G6第二篇的案例分享,跟上篇文章不一样的是,此篇文章少了配置的讲解,直接展示思路和代码,总体处理步骤还是:节点、边、图布局、最后封装。

经过上一个案例《AntV G6从零到一(Vue)》的实践之后,这次的案例实践要轻松不少,也印证了熟能生巧的道理。

ok,就这样!下一篇文章再见!

相关推荐
Martin -Tang35 分钟前
vite和webpack的区别
前端·webpack·node.js·vite
迷途小码农零零发36 分钟前
解锁微前端的优秀库
前端
王解1 小时前
webpack loader全解析,从入门到精通(10)
前端·webpack·node.js
我不当帕鲁谁当帕鲁2 小时前
arcgis for js实现FeatureLayer图层弹窗展示所有field字段
前端·javascript·arcgis
那一抹阳光多灿烂2 小时前
工程化实战内功修炼测试题
前端·javascript
放逐者-保持本心,方可放逐2 小时前
微信小程序=》基础=》常见问题=》性能总结
前端·微信小程序·小程序·前端框架
毋若成5 小时前
前端三大组件之CSS,三大选择器,游戏网页仿写
前端·css
红中马喽5 小时前
JS学习日记(webAPI—DOM)
开发语言·前端·javascript·笔记·vscode·学习
Black蜡笔小新6 小时前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
秦jh_7 小时前
【Linux】多线程(概念,控制)
linux·运维·前端