Custom Edge

4 min read

G6 provides abundant Built-in Edges. Besides, the custom machanism allows the users to design their own type of edges. An edge with complex graphics shapes, complex interactions, fantastic animations can be implemented easily.

In this document, we will introduce the custom edge by four examples:
1. Register a bran-new edge;
2. Register an edge by extending a built-in edge;
3. Register an edge with interactions and styles;
4. Register an edge with custom arrow.

1. Register a Bran-new Edge

Now, we are goint to register a perpendicular polyline:

img img img

(Left) Straight line edge. (Center) A custom polyline edge. (Right) The result after modifying the link points of the end nodes.

Register a Custom Edge

G6.registerEdge('hvh', {
  draw(cfg, group) {
    const startPoint = cfg.startPoint;
    const endPoint = cfg.endPoint;
    const shape = group.addShape('path', {
      attrs: {
        stroke: '#333',
        path: [
          ['M', startPoint.x, startPoint.y],
          ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y], // 1/3
          ['L', endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y], // 2/3
          ['L', endPoint.x, endPoint.y],
        ],
      },
    });
    return shape;
  },
});

Now, we have registered a custom edge named 'hvh' whose result is shown in the center of the figure above. The default startPoint and endPoint in the custom edge are the intersection of the edge and the end nodes.

To achieve the result shown in the right of the figure, we modify the anchorPoints (link points) of the end nodes to change the positions of startPoint and endPoint.

Modify the anchorPoints in Data

Now, we modify anchorPoints in the node data, and then assign shape to 'hvh' in edge data as shown below.

const data = {
  nodes: [
    {
      id: 'node1',
      x: 100,
      y: 200,
      anchorPoints: [
        [0, 0.5],
        [1, 0.5],
      ],
    },
    {
      id: 'node2',
      x: 200,
      y: 100,
      anchorPoints: [
        [0, 0.5],
        [1, 0.5],
      ],
    },
    {
      id: 'node3',
      x: 200,
      y: 300,
      anchorPoints: [
        [0, 0.5],
        [1, 0.5],
      ],
    },
  ],
  edges: [
    {
      id: 'edge1',
      target: 'node2',
      source: 'node1',
      shape: 'hvh',
    },
    {
      id: 'edge2',
      target: 'node3',
      source: 'node1',
      shape: 'hvh',
    },
  ],
};

2. Extend the Built-in Edge

In this section, we add animation to a built-in edge by afterDraw.

img
G6.registerEdge(
  'line-growth',
  {
    afterDraw(cfg, group) {
      const shape = group.get('children')[0];
      const length = shape.getTotalLength();
      shape.animate(
        {
          onFrame(ratio) {
            const startLen = ratio * length;
            const cfg = {
              lineDash: [startLen, length - startLen],
            };
            return cfg;
          },
          repeat: true,
        },
        2000,
      );
    },
  },
  'cubic',
);

3. Custom Edge with Interaction Styles

In this section, we implement a type of edge with the interaction styles below:

  • Widen the edge by clicking. Restore it by clicking again;
  • Turn to red by mouse hovering. Restore it by mouse leaving.

The result:

img
⚠️Attention: when the edge is too thin to be hitted by mouse, set `lineAppendWidth` to enlarge the hitting area.
// Extend a new type of edge by extending line edge
G6.registerEdge(
  'custom-edge',
  {
    // Response the states change
    setState(name, value, item) {
      const group = item.getContainer();
      const shape = group.get('children')[0]; // The order is determined by the ordering of been draw
      if (name === 'active') {
        if (value) {
          shape.attr('stroke', 'red');
        } else {
          shape.attr('stroke', '#333');
        }
      }
      if (name === 'selected') {
        if (value) {
          shape.attr('lineWidth', 3);
        } else {
          shape.attr('lineWidth', 2);
        }
      }
    },
  },
  'line',
);

// Select by clicking, cancel by clicking again
graph.on('edge:click', ev => {
  const edge = ev.item;
  graph.setItemState(edge, 'selected', !edge.hasState('selected')); // Switch the 'selected' state
});

graph.on('edge:mouseenter', ev => {
  const edge = ev.item;
  graph.setItemState(edge, 'active', true);
});

graph.on('edge:mouseleave', ev => {
  const edge = ev.item;
  graph.setItemState(edge, 'active', false);
});

4. Register Edge with Custom Arrow

The default end arrows might not meet the requirements sometimes. You can register an edge with a custom arrow by the custom mechanism of G6.

img

(Left) Built-in arrow of G6. (Right) A custom edge with custom arrow.

G6.registerEdge('line-arrow', {
  draw(cfg, group) {
    const { startPoint, endPoint } = cfg;
    const keyShape = group.addShape('path', {
      attrs: {
        path: [
          ['M', startPoint.x, startPoint.y],
          ['L', endPoint.x, endPoint.y],
        ],
        stroke: 'steelblue',
        lineWidth: 3,
        startArrow: {
          path: 'M 10,0 L -10,-10 L -10,10 Z',
          d: 10,
        },
        endArrow: {
          path: 'M 10,0 L -10,-10 L -10,10 Z',
          d: 10,
        },
      },
    });
    return keyShape;
  },
});