Extend 扩展接口

Extend 介绍

extend 顾名思义是扩展的意思。Graphin 支持 3 种扩展类型:扩展自定义布局,扩展自定义节点,扩展自定义图标。

Graphin 内置了布局,节点 与图标。除此之外,Graphin 给用户提供了扩展机制,用户可以方便的通过 extend 配置自定义布局,节点与图表。

扩展是通过 props.extend 实现的:

  1. <Graphin
  2. data={data}
  3. extend={{
  4. nodeShape: extendNodeShapeFunction,
  5. icon: extendIconFunction,
  6. layout: extendLayoutFunction,
  7. }}
  8. />

下面让我们来看如何具体自定义布局,节点和图标。

扩展布局

让我们来实现一个简单的随机布局作为例子。

本节的最终效果可以查看:Edit extendLayout

首先我们要定义一个 layout 函数:

  1. import Graphin, { Data, GraphinProps, LayoutOption } from '@antv/graphin';
  2. const layout = (graphin: Graphin, props: GraphinProps) => {
  3. return [
  4. {
  5. name: 'custom',
  6. desc: '自定义随机布局',
  7. icon: 'home',
  8. layout: (data: Data, options: LayoutOption): { data: Data } => {
  9. const nodes = data.nodes.map(node => {
  10. return {
  11. ...node,
  12. x: Math.round(Math.random() * 800),
  13. y: Math.round(Math.random() * 500),
  14. };
  15. });
  16. return {
  17. data: {
  18. nodes,
  19. edges: props.data.edges,
  20. },
  21. };
  22. },
  23. },
  24. ];
  25. };
  26. export default layout;

这个 layout 函数返回一个数组,每个数组都是一个自定义 layout 配置。layout 配置中最关键的就是 layout 方法,这个方法接受 data 作为参数,然后返回修改过的 data 数据。修改的就是每个节点上的 x 和 y 属性,也就是给每个节点附上了位置信息。

接下来我们在 Graphin 的 extend.layout 中传入这个函数,并制定 layout.name 为 custom,就可以使用这个自定义 layout 了。

  1. import layout from "./layout"
  2. <Graphin
  3. data={data}
  4. layout={
  5. name: "custom"
  6. }
  7. extend={{
  8. layout
  9. }}
  10. />

extend.layout 函数的 API 参见文档

扩展节点

扩展节点指的是扩展 NodeShape,也就是 G6 中节点的渲染形状和样式。

在 Graphin 中,我们支持通过 JSON 配置的形式来配置 NodeShape。让开发者不用使用 G6 的 API,声明式的对 NodeShape 进行扩展。

比如我们要注册一个新的 RectNode 类型的 NodeShape。首先我们要定义一个 NodeShape 函数:

  1. import { Node } from '@antv/graphin';
  2. const renderRectNode = (node: Node) => {
  3. const style: Style = {
  4. ...defaultStyles,
  5. ...node.style,
  6. };
  7. const badgeNumber = node.data.properties.length;
  8. return {
  9. shape: 'RectNode',
  10. shapeComponents: [
  11. {
  12. shape: 'rect',
  13. attrs: {
  14. id: 'rect-container',
  15. x: 0,
  16. y: 0,
  17. width: style.containerWidth,
  18. height: style.containerWidth,
  19. fill: style.containerFill,
  20. stroke: style.containerStroke,
  21. cursor: 'pointer',
  22. lineWidth: 2,
  23. radius: 2,
  24. },
  25. selected: {
  26. 'rect-container': {
  27. fill: style.highlightFill,
  28. },
  29. },
  30. },
  31. ],
  32. };
  33. };

这个函数返回的是一个 JSON schema,是对 Shape 的描述。主要包括 shapeComponents 和 state。

shapeComponents 是一个数组,每一项是一个 Shape 的样式描述。其中 shape 的值是 G6 中的内置 shape。shape 类型和 attrs 的详情见 G6 文档

state 则是对 G6 中 behavior 中 state 的抽象。state 的 key 是 G6 的 behavior 中 setItemState 的状态。value 也一个 map,key 是 shapeComponents 中 shape 的 id。value 是 attrs 对象。因此 state 对象是对不同状态下 shapeComponents 的属性的描述。通过这个 API,我们可以声明式的对 NodeShape 的样式和组成进行编写,更符合 React 的编程范式。

NodeShape 拓展的 Demo 可以查看:Edit extendNodeShape

extend.nodeShape 函数的具体 API 请参考文档

扩展图标

Graphind 的 icon 机制使用 iconfont 实现。并且 Graphin 内置了 graphin 这个 fontFamily(Graphin 的内置图标)。如果想使用自定义的 图标,可以使用 extend.icon API 进行扩展。

Graphin 使用的 G6 的 iconfont 方案。使用 unicode 方式。具体可以参考 G6 文档

首先我们要把自定义的图标导入到一个 iconfont 项目中。

以下假设开发者使用的 iconfont.cn 这个字体图标平台。使用其他 iconfont 平台也是可以的。

之后引入 CSS。打开 iconfont 下自己的字体项目,将 unicode tab 下的 font-face 这段 CSS 复制到项目的 CSS 中: Extend 扩展接口 - 图3 使用 icon 时,unicode 的方式可读性很差,不太友好。因此我们可以给 Graphin 提供一个 icon 的 name 和 unicode 的映射。

iconfont.cn 刚好提供了这样的映射,我们可以点击上图中的下载到本地,找到一个 .json 后缀的文件。

最后我们通过 props.extend.icon 传入新的 fontFamily 和 name-unicode 映射,对 Graphin 的图标进行扩展。同时在 data 的 node.style 中传入对应的 icon 和 fontFamily。icon 的值是 iconfont 中的 icon 的 name。

  1. import json from './font.json'; // iconfont 网站上下载的 name-unicode 映射文件。
  2. const data = {
  3. nodes: [
  4. {
  5. id: 'foo',
  6. style: {
  7. icon: "phonecall",
  8. fontFamily: "iconfont"
  9. }
  10. }
  11. ]
  12. }
  13. <Graphin
  14. data={data}
  15. extend={{
  16. icon: () => {
  17. return [
  18. {
  19. fontFamily: 'iconfont', // 注意这边的 fontFamily 需要和上面 CSS 的 fontFamily 对应
  20. map: fonts.glyphs,
  21. },
  22. ];
  23. },
  24. }}
  25. />;

如果使用的 iconfont 平台没有 name-unicode 映射文件,可以自己构造一个,数据结构是 { name: string; unicode_decimal: number; }[ ]

完整的例子请查看:

Edit extend-font