g6/packages/site/docs/manual/customize/edgeExtension.zh.md
Aaron e08c299a69
docs: update v5 site docs (#5162)
* docs: remove readme and navigation in site

* docs: remove v4 core concept docs

* docs: update history and lod plugin docs

* chore: update dumirc config

* docs: add api shape overview doc

* docs: update manual docs

* docs: update manual and tutorial docs

* chore: update dumirc

* docs: remove design sector

* docs: update docs meta data

* docs: update api docs
2023-11-20 09:50:36 +08:00

7.7 KiB
Raw Blame History

title order
自定义边 2

示例

import { Graph as BaseGraph, extend, Extensions } from '@antv/g6';

// 自定义变类型,继承一个已有的边类型或边基类 Extensions.BaseEdge
class CustomNode extends Extensions.LineEdge {
  // 覆写方法,可覆写的类方法见下文
}

const Graph = extend(BaseGraph, {
  // 注册自定义边
  edges: {
    'custom-edge': CustomEdge,
  },
});

const graph = new Graph({
  // ... 其他配置
  edge: {
    type: 'custom-edge', // 使用注册的节点
  },
});

覆写方法

draw

:::info{title=提示} 大多数情况下并不需要覆写 draw 方法,更常用的做法是覆写 drawKeyShapedrawLabelShape 等方法,这些方法将在下文介绍。 :::

G5 5.0 移除了 updateafterUpdate 方法。现在只需要复写 draw 方法和 afterDraw 方法G6 将自动根据更新的属性增量更新图形。

draw 方法通过调用 this.drawKeyShape 等方法分别绘制边各部分。

你可以参考 line-edge 类型边的 draw 方法进行覆写。

afterDraw

draw 函数完成之后执行的逻辑,也可以用于绘制更多的图形,返回值和 draw 方法一致。在内置的节点类型中,没有对它进行实现。

drawKeyShape

绘制主图形(keyShape),该图形是必须的,例如直线边的主图形是一条直线(line) 以及首尾箭头(arrow),曲线边的主图形则将直线换成了曲线路径(path)。

覆写 drawKeyShape 方法绘制直线边的示例如下:

public drawKeyShape(
  model: EdgeDisplayModel,
  sourcePoint: Point,
  targetPoint: Point,
  shapeMap: EdgeShapeMap,
) {
  const { keyShape: keyShapeStyle } = this.mergedStyles;
  const { startArrow, endArrow, ...others } = keyShapeStyle;
  const lineStyle = {
    ...others,
    x1: sourcePoint.x,
    y1: sourcePoint.y,
    z1: sourcePoint.z || 0,
    x2: targetPoint.x,
    y2: targetPoint.y,
    z2: targetPoint.z || 0,
    isBillboard: true,
  };
  // 绘制箭头
  this.upsertArrow('start', startArrow, others, model, lineStyle);
  this.upsertArrow('end', endArrow, others, model, lineStyle);
  // 绘制并返回图形
  return this.upsertShape('line', 'keyShape', lineStyle, shapeMap, model);
}

若要绘制曲线或折线,drawKeyShape 中应当根据控制点,计算路径。例如内置的 quadratic-edgedrawKeyShape 方法:

public drawKeyShape(
  model: EdgeDisplayModel,
  sourcePoint: Point,
  targetPoint: Point,
  shapeMap: EdgeShapeMap,
) {
  const { keyShape: keyShapeStyle } = this.mergedStyles as any;
  const { startArrow, endArrow, ...others } = keyShapeStyle;

  // 根据弧度位置、弧度等信息计算控制点
  const controlPoint = this.getControlPoints(
    sourcePoint,
    targetPoint,
    keyShapeStyle.curvePosition,
    keyShapeStyle.controlPoints,
    keyShapeStyle.curveOffset,
  )[0];
  const lineStyle = {
    ...others,
    path: [
      ['M', sourcePoint.x, sourcePoint.y],
      ['Q', controlPoint.x, controlPoint.y, targetPoint.x, targetPoint.y],
    ],
  };
  // 绘制箭头
  this.upsertArrow('start', startArrow, others, model, lineStyle);
  this.upsertArrow('end', endArrow, others, model, lineStyle);
  // 绘制并返回图形
  return this.upsertShape('path', 'keyShape', lineStyle, shapeMap, model);
}

其中,this.getControlPoints 可以进行复写,从而自定义控制点计算逻辑,见 getControlPoints

drawHaloShape

绘制主图形轮廓图形(haloShape),通常在 selected, active 状态下显示。

若需要覆写,则可以参考 BaseEdge.drawHaloShape

drawLabelShape

绘制文本图形(labelShape

若需要覆写,则可以参考 BaseEdge.drawLabelShape

drawLabelBackgroundShape

绘制文本图形的背景框图形(labelBackgroundShape

若需要覆写,则可以参考 BaseEdge.drawLabelBackgroundShape

drawOtherShapes

绘制上述内容之外的图形,可以在 drawOtherShapes 中完成,例如额外创建一个圆形:

public drawOtherShapes(
  model: EdgeDisplayModel,
  shapeMap: EdgeShapeMap,
) {
  return {
    extraShape: upsertShape(
      'circle',
      'other-circle-shape',
      {
        r: 4,
        fill: '#0f0',
        x: -20,
        y: 0,
      },
      shapeMap,
    ),
  };
}

成员属性及方法

getControlPoints

获取控制点,通常用于计算路径。例如折线边的控制点是拐点,曲线边的控制点是曲线的控制点。

当继承 Extensions.PolylineEdge、Extensions.QuadraticEdge、Extensions.CubicEdge、Extensions.CubicHorizontalEdge、Extensions.CubicVerticalEdge 时,可以通过复写 getControlPoints 来修改控制点的逻辑。

Extensions.PolylineEdgegetControlPoints 类型为:

(
  /** 边的渲染数据 */
  model: EdgeDisplayModel,
  /** 边的起点 */
  sourcePoint: Point,
  /** 边的终点 */
  targetPoint: Point,
) =>
/** 计算后的控制点 */
{
  x: number;
  y: number;
  z?: number;
}[]

Extensions.QuadraticEdgeExtensions.CubicEdgeExtensions.CubicHorizontalEdgeExtensions.CubicVerticalEdgegetControlPoints 类型为:

(
  /** 边的起点 */
  startPoint: Point,
  /** 边的终点 */
  endPoint: Point,
  /** 控制点的投影在两端点连线上的百分比,范围 0 到 1 */
  percent: number,
  /** 数据中控制点配置 */
  controlPoints: Point[],
  /** 弧度距离 */
  offset: number,
) =>
/** 计算后的控制点 */
{
  x: number;
  y: number;
  z?: number;
}[];

getPath

Extensions.PolylineEdge 的成员方法,仅在继承它来实现自定义边时可复写。由于折线的自动寻径算法比较复杂,因此单独抽出了这个函数。也由于算法复杂性,折线边的性能稍差。如果有确定的折线边绘制规则,可以通过继承内置折线边,自定义 getPath 方法覆盖自动寻径的逻辑。函数类型为:

(
  /** 边的渲染数据 */
  model: EdgeDisplayModel,
  /** 起点和终点 */
  points: Point[],
  /** 折线拐点的弧度 */
  radius: number,
  /** 折线弯折的配置 */
  routeCfg?: RouterCfg,
  /** 是否使用 A* 算法 */
  auto?: boolean,
) =>
  /** 路径 */
  string;
RouterCfg
type RouterCfg = {
  name: 'orth' | 'er';
  /** 线与点之间的间距 */
  offset?: number;
  /** 网格大小 */
  gridSize?: number;
  /** 最大旋转角度(弧度) */
  maxAllowedDirectionChange?: number;
  /** 允许的边的方向 */
  directions?: any[];
  /** 起点和终点的权重 */
  penalties?: {};
  /** 是否使用简单的折线拐点寻径算法 */
  simple?: boolean;
  /** 计算两点之间距离的函数 */
  distFunc?: (p1: PolyPoint, p2: PolyPoint) => number;
  /** 简化的寻径函数 */
  fallbackRoute?: (p1: PolyPoint, p2: PolyPoint, startNode?: Node, endNode?: Node, cfg?: RouterCfg) => PolyPoint[];
  /** 最大循环次数 */
  maximumLoops?: number;
  /** 是否自动避开障碍物,默认为 false */
  enableObstacleAvoidance?: boolean;
};