-

绘制Tutorial案例

本文将进行 Tutorial案例的简单绘制和配置。通过本文,你将知道创建一般图时一些常用的配置项及其作用。

基础绘制

创建容器

需要在 HTML 中创建一个用于容纳 G6 绘制的图的容器,通常为 div 标签。G6 在绘制时会在该容器下追加 canvas 标签,然后将图绘制在其中。

  1. <body>
  2. <div id="mountNode"></div>
  3. <!-- 引入 G6 -->
  4. <!-- ... -->
  5. </body>

数据准备

引入 G6 的数据源为 JSON 格式的对象。该对象中需要有节点(nodes)和边(edges)字段,分别用数组表示:

  1. <script>
  2. // console.log(G6.Global.version);
  3. const initData = {
  4. // 点集
  5. nodes: [{
  6. id: 'node1', // 节点的唯一标识
  7. x: 100, // 节点横坐标
  8. y: 200, // 节点纵坐标
  9. label: '起始点' // 节点文本
  10. },{
  11. id: 'node2',
  12. x: 300,
  13. y: 200,
  14. label: '目标点'
  15. }],
  16. // 边集
  17. edges: [
  18. // 表示一条从 node1 节点连接到 node2 节点的边
  19. {
  20. source: 'node1', // 起始点 id
  21. target: 'node2', // 目标点 id
  22. label: '我是连线' // 边的文本
  23. }
  24. ]
  25. };
  26. </script>

注意

  • nodes 数组中包含节点对象,唯一的 id 是每个节点对象中必要的属性,xy 用于定位;
  • edges 数组中包含边对象,sourcetarget 是每条边的必要属性,分别代表了该边的起始点 id 与 目标点 id
  • 点和边的更多属性参见:内置的节点内置的边

图实例化

图实例化时,至少需要为图设置容器、宽、高:

  1. <script>
  2. // const initData = { ... }
  3. const graph = new G6.Graph({
  4. container: 'mountNode', // 指定挂载容器
  5. width: 800, // 图的宽度
  6. height: 500 // 图的高度
  7. });
  8. </script>

图的渲染

数据的加载和图的渲染是两个步骤,可以分开进行。

  1. <script>
  2. // const initData = { ... }
  3. // const graph = ...
  4. graph.data(initData); // 加载数据
  5. graph.render(); // 渲染
  6. </script>

绘制结果

调用 graph.render() 方法之后,G6 引擎会根据加载的数据进行图的绘制。如果没有额外指定图实例的 renderer 属性配置,则默认采用 Canvas 进行绘制,结果如下: 绘制Tutorial案例 - 图1

真实数据加载

上文中,我们使用了仅含有两个节点和一条边的数据,直接将数据定义放在了代码中。而真实场景的数据通常是远程接口请求加载的。为了方便,我们已经给读者准备好了一份 json 数据文件,地址如下:https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json

加载远程数据

修改 index.html,通过 fetch 函数异步加载远程的数据源,并传入 G6 的图实例中:

  1. <script>
  2. // const graph = ...
  3. const main = async () => {
  4. const response = await fetch('https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json');
  5. const remoteData = await response.json();
  6. // ...
  7. graph.data(remoteData); // 加载远程数据
  8. graph.render(); // 渲染
  9. };
  10. main();
  11. </script>

fetch 函数允许我们发起网络请求,加载数据,而其异步的过程可以通过 async/await 进行更合理的控制。这里我们为了方便起见,将主要逻辑放在了 main 函数里面。如果读者对 fetch 和 async/await 的知识有疑问,可以参考:async functionFetch API

运行后,我们得到了下图结果: 绘制Tutorial案例 - 图2 乍看之下,图像有点奇怪,实际上数据已经正确的加载了进来。由于数据量比较大,节点和边都非常的多,显得内容比较杂乱。另外由于画布大小的限制,实际的图被画布截断了,目前只能看见部分内容,这个问题后文会继续解决。

请看下面摘取自 tutorial-data.json 的部分数据,我们发现数据中节点定义了位置信息 xy,并且很多节点的 xy 不在图的宽高(width: 800, height: 600)范围内:

  1. {
  2. "nodes": [
  3. { "id": "0", "label": "n0", "class": "c0", "x": 1000, "y": -100 },
  4. { "id": "1", "label": "n1", "class": "c0", "x": 300, "y": -10 }
  5. //...
  6. ],
  7. "edges": [
  8. //...
  9. ]
  10. }

由于 G6 在读取数据时,发现了数据中带有位置信息(xy),就会按照该位置信息进行绘制,这是为了满足按照原始数据绘制的需求设计的。但为优化超出屏幕到问题,G6 提供了图的两个相关配置项:

  • fitView:设置是否将图适配到画布中;
  • fitViewPadding:画布上四周的留白宽度。

我们将实例化图的代码更改为如下形式:

  1. const graph = new G6.Graph({
  2. // ...
  3. fitView: true,
  4. fitViewPadding: [20, 40, 50, 20],
  5. });

上述代码将会生成如下图:绘制Tutorial案例 - 图3

可以看到,图像已经可以自动适配画布的大小,完整的显示了出来。

常用配置

本文使用到的配置以及后续 Tutorial 将会使用到到常用配置如下:

配置项类型选项 / 示例默认说明
rendererString'canvas' | 'svg''canvas'绘制图的方式是 canvas 还是 SVG。
fitViewBooleantrue | falsefalse是否将图适配到画布大小,可以防止超出画布或留白太多。
fitViewPaddingNumber | Array20 | [ 20, 40, 50, 20 ]0画布上的四周留白宽度。
animateBooleantrue | falsefalse是否启用图的动画。
modesObject{ default: [ 'drag-node', 'drag-canvas' ]}null图上行为模式的集合。由于比较复杂,按需参见:G6 中的 mode
defaultNodeObject{ shape: 'circle', color: '#000', style: { …… }}null节点默认的属性,包括节点的一般属性和样式属性(style)。
defaultEdgeObject{ shape: 'polyline', color: '#000', style: { …… }}null边默认的属性,包括边的一般属性和样式属性(style)。
nodeStateStylesObject{ hover: { …… }, select: { …… }}null节点在除默认状态外,其他状态下的样式属性(style)。例如鼠标放置(hover)、选中(select)等状态。
edgeStateStylesObject{ hover: { …… }, select: { …… }}null边在除默认状态外,其他状态下的样式属性(style)。例如鼠标放置(hover)、选中(select)等状态。

完整代码

至此,完整代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Tutorial Demo</title>
  6. </head>
  7. <body>
  8. <div id="mountNode"></div>
  9. <script src="https://gw.alipayobjects.com/os/antv/pkg/_antv.g6-3.1.0/build/g6.js"></script>
  10. <script>
  11. const graph = new G6.Graph({
  12. container: 'mountNode',
  13. width: 1000,
  14. height: 600,
  15. renderer: 'svg',
  16. fitView: true,
  17. fitViewPadding: [ 20, 40, 50, 20 ]
  18. });
  19. const main = async () => {
  20. const response = await fetch('https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json');
  21. const remoteData = await response.json();
  22. graph.data(remoteData);
  23. graph.render();
  24. };
  25. main();
  26. </script>
  27. </body>
  28. </html>

⚠️注意 若需更换数据,请替换 'https://gw.alipayobjects.com/os/basement_prod/6cae02ab-4c29-44b2-b1fd-4005688febcb.json&#39; 为新的数据文件地址。