antV G6 自定义节点 实现流程图 + 小地图功能

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <title>Tutorial Demo</title>
</head>
<style>
  .g6-minimap-container {
    border: none;
    position: absolute !important;
    right: 0px;
    bottom: 0px;
    background-color: #effcf6;
  }

  .g6-minimap-viewport {
    border: 1px solid #999 !important;
  }
</style>

<body>
  <div style="height:800px;position: relative;">
    <div id="container" style="height: 100%;"></div>
  </div>
  <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.7.1/dist/g6.min.js"></script>
  <script>
    const data = {
      id: '0',
      label: '深圳市',
      anchorPoints: [
        [1, 0.5],
      ],
      children: [
        {
          id: '1',
          label: '宝安区',
          anchorPoints: [
            [1, 0.5],
            [0, 0.5]],
          children: [
            { id: '2', label: '第三个', anchorPoints: [[0, 0.5]], type: 'addCustomNode' },
            { id: '3', label: '第四个', anchorPoints: [[0, 0.5]], type: 'addCustomNode' },
          ]
        },
        {
          id: '4',
          label: '龙岗区',
          anchorPoints: [
            [1, 0.5],
            [0, 0.5]],
          children: [
            {
              id: '5',
              label: '第六个',
              anchorPoints: [
                [1, 0.5],
                [0, 0.5]],
                  type: 'subCustomNode',
              children: [
                { id: '6', label: '第七个', },
                { id: '19', label: '第四个', anchorPoints: [[0, 0.5]], },
                { id: '20', label: '第四个', anchorPoints: [[0, 0.5]], },
              ]
            },
            {
              id: '7',
              label: '第六个',
              anchorPoints: [
                [1, 0.5],
                [0, 0.5]],
                type: 'subCustomNode',
              children: [
                { id: '8', label: '第七个', },
                //   { id: '15', label: '第四个', anchorPoints: [[0, 0.5]], },
                // { id: '16', label: '第四个', anchorPoints: [[0, 0.5]], },
                { id: '17', label: '第四个', anchorPoints: [[0, 0.5]], },
                { id: '18', label: '第四个', anchorPoints: [[0, 0.5]], },
              ]
            },
          ]
        },
        {
          id: '9',
          label: '宝安区',
          anchorPoints: [
            [1, 0.5],
            [0, 0.5]],
          children: [
            { id: '10', label: '第三个', anchorPoints: [[0, 0.5]], type: 'addCustomNode' },
            { id: '11', label: '第四个', anchorPoints: [[0, 0.5]],  type: 'addCustomNode' },
          ]
        },
        {
          id: '12',
          label: '福田区',
          anchorPoints: [[0, 0.5], [1, 0.5]],
          children: [
            { id: '13', label: '第三个', anchorPoints: [[0, 0.5]], type: 'addCustomNode' },
            { id: '14', label: '第四个', anchorPoints: [[0, 0.5]],  type: 'addCustomNode' },
          ]
        },
      ]
    }
  //   // 注册自定义节点
  G6.registerNode(
        'addCustomNode',
        {
      //  draw:(cfg, group)=> {
      //     return group.addShape('dom', {
      //         attrs: {
      //           width: cfg.size[0],
      //           height: cfg.size[1],
      //           // DOM's html
      //           html: `
      //           <div style="height:95%;border:1px solid #999;text-align:center;line-height:${cfg.size[1]}px">${cfg.label}
      //             <span style="width:40px;height:100%;float:right;font-size:32px;color:#999;border-left:1px solid #999">
      //               +
      //             <span>
      //           </div>
      //           `
      //         },
      //         draggable: true,
      //       });
      //     },
     // 绘制节点
          drawShape: function drawShape(cfg, group) {
            const shapeType = this.shapeType;
            const style = Object.assign({}, this.getShapeStyle(cfg), {
              stroke: '#c5c6c6',
              width: 200,
              height: 40
            })
            const shape = group.addShape(shapeType, {
              attrs: style,
              name: 'key-shape',
            });
            group.addShape('path', {
              attrs: {
                path:[['M',80,-16],['L',80,17]],
                stroke: '#c5c6c6',
              },
            });
            group.addShape('rect', {
              attrs: {
                x: 80,
                y: -19,
                width: 38,
                height: 38,
                fill: '#fff',
                // stroke: '#8c8ba1',
                cursor: 'pointer',
              },
              name: 'add-rect-shape',
            });
            group.addShape('path', {
              attrs: {
                path: [['M', 95, 0], ['L', 105, 0]],
                stroke: '#8c8ba1',
                cursor: 'pointer',
              },
              name: 'rect-shape',
            });
            group.addShape('path', {
              attrs: {
                path: [['M', 100, -5], ['L', 100, 5]],
                stroke: '#8c8ba1',
              },
            });
            return shape;
        }
      },'rect');
      G6.registerNode(
          'subCustomNode',
          {
            // 绘制节点
            drawShape: function drawShape(cfg, group) {
              const shapeType = this.shapeType;
              const style = Object.assign({}, this.getShapeStyle(cfg),{
                stroke: '#c5c6c6',
                width:200,
                height:40
              })
              const shape = group.addShape(shapeType, {
                attrs: style,
                name: 'key-shape',
              });
              group.addShape('rect', {
                attrs: {
                  x:80,
                  y:-19,
                  width: 38,
                  height:38,
                  fill: '#fff',
                  cursor: 'pointer',
                },
                name: 'rect-shape',
              });
              group.addShape('path', {
                attrs: {
                  path: [['M', 80, -16], ['L', 80, 17]],
                  stroke: '#c5c6c6',
                  cursor: 'pointer',
                },
                name: 'rect-shape',
              });
              group.addShape('path', {
                attrs: {
                  path: [['M', 95, 0], ['L', 105, 0]],
                  stroke: '#8c8ba1',
                  cursor: 'pointer',
                },
                name: 'subCustomNode-shape',
              });
              return shape;
            }
          }, 'rect');
  G6.registerEdge(
  'line',
    {
      getPath(points) {
        const startPoint = points[0];
        const endPoint = points[1];
        return [
          ['M', startPoint.x + 10, startPoint.y],
          ['L', endPoint.x - 10, endPoint.y],
        ];
      },
      afterDraw(cfg, group) {
        // 获取图形组中的第一个图形,在这里就是边的路径图形
        const shape = group.get('children')[0];
        // 获取路径上的起点坐标
        const quatile = shape.getPoint(0);
        // 在起点终点上放置一个圆形
        group.addShape('circle', {
          attrs: {
            r: 3,
            stroke: '#c5c6c6',
            x: quatile.x - 2,
            y: quatile.y,
          },
        });
        const quatileEnd = shape.getPoint(1);
        group.addShape('circle', {
          attrs: {
            r: 3,
            stroke: '#c5c6c6',
            x: quatileEnd.x + 3,
            y: quatileEnd.y,
          },
        });
      },
      update: undefined,
    },
    'line'
  );
  const minimap = new G6.Minimap({
      size: [150, 100],
  });
    const initTree = (data) => {
      // 画布宽高
      const width = document.getElementById('container').scrollWidth || 800;
      const height = document.getElementById('container').scrollHeight || 800;
      const graph = new G6.TreeGraph({
        // 图的  DOM 容器,可以传入该 DOM 的 id 或者直接传入容器的 HTML 节点对象。
        container: 'container',
        // 指定画布宽度,单位为 'px'。
        width,
        // 指定画布高度,单位为 'px'。
        height,
        // 是否开启画布自适应。开启后图自动适配画布大小。
        fitView: true,
        fitViewPadding: [10, 10, 10, 10],
        //    v3.5.1 后支持。开启后,图将会被平移,图的中心将对齐到画布中心,但不缩放。优先级低于 fitView
        fitCenter: true,
        // 最小缩放比例
        minZoom: 0.8,
        // 最大缩放比例
        maxZoom: 2,
        // 指定边是否连入节点的中心
        // linkCenter: true,
        // 设置画布的模式
        modes: {
          default: [
            {
              // 只适用于树图,展开或收起子树
              type: 'collapse-expand',
              // trigger:收起和展开节点分组的方式。支持 'click' 和 'dblclick' 两种方式。默认为 'dblclick',即双击。
              trigger: 'click',
              // onChange:收起或展开的回调函数。警告:V3.1.2 版本中将移除;
              onChange: async function onChange(item, collapsed) {
                // const data = item.get('model').data;
                const { _cfg } = item
                console.log(item);
                const dataItem = item.getModel();
                dataItem.collapsed = collapsed;
                item.updatePosition(_cfg)
                return true;
              },
            },
            // 拖拽画布;
            'drag-canvas',
            // 缩放画布;
            'zoom-canvas',
          ],
        },
        //  renderer: "svg",
        // 默认状态下节点的配置,比如 type, size, color。会被写入的 data 覆盖。
        defaultNode: {
          type: 'rect',
          // size 是单个数字,表示直径
          // size: 16,
          // 指定边连入节点的连接点的位置(相对于该节点而言),可以为空。例如: [0, 0],代表节点左上角的锚点,[1, 1],代表节点右下角的锚点
          // anchorPoints: [
          //   [1,0.5],
          //   [0,0.5],
          //   [0, 0.5]
          // ],
          // 节点样式
          style: {
            // 节点填充色
            fill: '#fff',
            // 节点的描边颜色,''就是没颜色的意思
            stroke: '#c5c6c6',
            // 那个小手
            cursor: 'pointer',
            radius: 2,
          },
          // Object 类型。配置标签文本
          labelCfg: {
            // 标签的样式属性。
            style: {
              // 文本颜色
              fill: '#000',
              // 文本字体大小
              fontSize: 14,
            },
          },
        },
        // 默认状态下边的配置,比如 type, size, color。会被写入的 data 覆盖。
        defaultEdge: {
          // 指定边的类型,可以是内置边的类型名称,也可以是自定义边的名称。默认为 'line'
          type: 'line',
          // 边的样式属性
          style: {
            // 边的颜色
            stroke: '#ccc',
          },
        },
        // 布局配置项,使用 type 字段指定使用的布局方式
        layout: {
          // 布局名称
          type: 'compactBox',
          // layout 的方向。
          direction: 'LR', // H / V / LR / RL / TB / BT
          // 节点 id 的回调函数
          getId: function getId(d) {
            return d.id;
          },
          // 节点高度的回调函数
          getHeight: function getHeight() {
            return 16;
          },
          // 节点宽度的回调函数
          getWidth: function getWidth() {
            return 16;
          },
          // 节点纵向间距的回调函数
          getVGap: function getVGap() {
            return 20;
          },
          // 节点横向间距的回调函数
          getHGap: function getHGap() {
            return 120;
          },
        },
         plugins: [minimap],
        // 动画
        animate: true,
      });
      // 设置各个节点样式及其他配置,以及在各个状态下节点的 KeyShape 的样式
      // 该方法必须在 render 之前调用,否则不起作用
      // 使用 graph.node(nodeFn) 配置 > 数据中动态配置 > 实例化图时全局配置
      graph.node(function (node) {
        return {
          label: node.label,
          size: [160, 40],
          labelCfg: {
            style: {
              textAlign: 'center',
            },
          },
        };
      });
      graph.on('add-rect-shape:click', (evt) => {
        const { item } = evt;
        console.log(item);
        // graph.updateItem(item, {
        //   label: '点击了局部',
        //   labelCfg: {
        //     style: {
        //       fill: '#003a8c',
        //       fontSize: 16,
        //     },
        //   },
        // });
      });
      // 初始化的图数据
      graph.data(data);
      // 根据提供的数据渲染视图。
      graph.render();
      // 让画布内容适应视口
      graph.fitView();
    }
    initTree(data)
  </script>
</body>

</html>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值