AntV-G6:实现带有描边的圆形图片节点(头像框效果)

需求描述

需要实现类似下图中的G6力导向图:节点填充圆形图片,且需要描边
头像框节点效果

实现思路

思路一

参考G6圆形内置节点,可实现在带有描边的圆形节点上添加图片效果,但图片不支持裁剪(如果是方形图片会盖住圆形节点的描边);

思路二

参考G6图片内置节点(要观察裁剪效果,需将在线示例中的配置项defaultNode.clipCfg.show改为true),可实现裁剪图片效果,但该类型节点不支持添加描边;

最终思路

使用自定义节点:

  1. 首先尝试使用自定义DOM节点实现,优点是实现节点样式非常自由,缺点是后续修改节点都要直接操作DOM,适用于需要实现特殊展示效果、偏重展示的场景;
  2. 笔者的应用场景需要支持较多交互操作,因此最终实现思路是将头像框拆成三个图层:带描边的圆形节点、裁剪为圆形的图片节点、底部文字节点,可将以下参考代码拷贝到文末的官网示例中调试运行~

参考代码

import G6 from '@antv/g6';

/**
 * 注册自定义节点
 */
G6.registerNode(
  'avatar', 
  {
    draw: (cfg, group) => {
      const nodeSize = cfg.size
      let offset = -nodeSize / 2 // 节点偏移量,-节点尺寸/2
      let nodeRadius = nodeSize / 2
      // 带描边的圆形节点
      group.addShape('circle', {
        draggable: true,
        attrs: {
          x: 0,
          y: 0,
          r: nodeRadius,
          stroke: '#9fc8fe', // 描边
          lineWidth: 2 // 描边宽度
        },
      });
      // 图片节点,需调用setClip实现裁剪
      const shape = group.addShape('image', {
        draggable: true,
        attrs: {
          x: offset,
          y: offset,
          width: nodeSize,
          height: nodeSize,
          img: cfg.img
        },
        zIndex: 2,
      });
      // 裁剪图片,支持 circle、rect、ellipse、Polygon 及自定义 path clip
      shape.setClip({
        type: 'circle', 
        attrs: {
          r: nodeSize / 2 - 1,
          x: 0,
          y: 0,
        },
      })
      // 文字节点(文字居中:x-0,textAlign-center;显示在节点下方:y-节点高度)
      group.addShape('text', {
        attrs: {
          x: 0,
          y: nodeSize,
          width: nodeSize,
          height: cfg.fontHeight,
          lineHeight: cfg.fontHeight,
          textAlign: `center`,
          fontSize: 24,
          text: cfg.label,
          fill: '#555',
          stroke: 'red'
        },
        zIndex: 1, // 排到最底层
      });
      return shape;
    }
  },
  'circle'
);

/** 数据 */
const data = {
  nodes: [
    {
      id: 'node1',
      x: 10,
      y: 100,
      label: '节点A',
      img: "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ch6rTrCxb6YAAAAAAAAAAABkARQnAQ",
    },
    {
      id: 'node2',
      x: 200,
      y: 100,
      label: '节点B',
      img: "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*95GYRI0zPx8AAAAAAAAAAABkARQnAQ",
    },
  ],
  edges: [
    {
      source: 'node1',
      target: 'node2',
      style: {
        // endArrow: true,
        lineWidth: 1, // 线宽
        stroke: '#BCBCBC', // 线的颜色
        endArrow: { // 设置终点箭头
          // 使用内置箭头路径函数,参数为箭头的 宽度、长度、偏移量(默认为 0,与 d 对应)
          path: G6.Arrow.triangle(18, 24, 26),
          d: 12,
          fill: '#6d81d2' // 箭头填充为实体有颜色
      }
    },

    },
  ],
};

const container = document.getElementById('container');
const width = container.scrollWidth;
const height = (container.scrollHeight || 500) - 100;

const descriptionDiv = document.createElement('div');
descriptionDiv.innerHTML = `实现带描边的圆形图片(头像框)节点效果~`;
container.appendChild(descriptionDiv);

const graph = new G6.Graph({
  container: 'container',
  width,
  height,
  // renderer: 'svg', // 渲染模式默认为canvas,如果使用svg模式,边的箭头显示会有问题
  linkCenter: true, // 设置边连入节点的中心(箭头指向节点中心)
  layout: {
    type: 'force', // force力导布局
    linkDistance: 200, // 指定边距离
  },
  defaultNode: { // 节点通用配置
    type: 'avatar',
    size: 80,
    fontHeight: 20
  },
  defaultEdge: { // 边通用配置
    type: 'quadratic', // 指定边的形状为二阶贝塞尔曲线
    size: 1,
  }
});

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

在线运行

可以拷贝到以下官网示例,在线运行调试:
G6自定义节点-DOM节点

参考网址

[1] G6圆形内置节点
[2] G6图片内置节点
[3] G6自定义节点-DOM节点

猜你喜欢

转载自blog.csdn.net/qq_36604536/article/details/128319470