UNPKG

@antv/g6

Version:

graph visualization frame work

1 lines 55.4 kB
{"expireTime":9007200828528711000,"key":"transformer-remark-markdown-html-1efb3ed12d623110b841517107a9d245-gatsby-remark-prettiergatsby-remark-prismjsgatsby-remark-external-linksgatsby-remark-autolink-headersgatsby-remark-reading-time-","val":"<h2 id=\"背景\"><a href=\"#%E8%83%8C%E6%99%AF\" aria-label=\"背景 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>背景</h2>\n<p>大多数图数据在可视化时被展示成点-线图(Node-link Diagram)的形式。点-线图特别适用于如交通网络图一类的关系数据的展示,这种数据的节点通常带有地理位置信息,例如迁徙图、移民图、航线图等。<br /><img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648650-020a5d61-c8d9-4ab2-a325-1d1f95c82f94.png#align=left&#x26;display=inline&#x26;height=200&#x26;name=image.png&#x26;originHeight=1182&#x26;originWidth=1426&#x26;search=&#x26;size=1819531&#x26;status=done&#x26;width=241\" alt=\"image.png\"><img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648684-9731bc35-1a1d-44cd-9d9c-633199c542c6.png#align=left&#x26;display=inline&#x26;height=197&#x26;name=image.png&#x26;originHeight=1086&#x26;originWidth=2426&#x26;search=&#x26;size=2823231&#x26;status=done&#x26;width=439\" alt=\"image.png\"></p>\n<blockquote>\n<p>(左)图 1. 法国航线图。(右)图 2. 美国航线图。</p>\n</blockquote>\n<p><img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648704-c470528e-a2ba-4749-8521-cd4754bd5875.png#align=left&#x26;display=inline&#x26;height=134&#x26;name=image.png&#x26;originHeight=754&#x26;originWidth=2282&#x26;search=&#x26;size=2012559&#x26;status=done&#x26;width=406\" alt=\"image.png\"><img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648656-b2fc8176-6bb4-459e-b10d-e04946e3734c.png#align=left&#x26;display=inline&#x26;height=141&#x26;name=image.png&#x26;originHeight=1030&#x26;originWidth=2266&#x26;search=&#x26;size=1570587&#x26;status=done&#x26;width=311\" alt=\"image.png\"></p>\n<blockquote>\n<p>(左)图 3. 世界网络 IXP 对等图。(右)图 4. 美国移民图。</p>\n</blockquote>\n<h2 id=\"问题\"><a href=\"#%E9%97%AE%E9%A2%98\" aria-label=\"问题 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>问题</h2>\n<p>虽然点-线图提供了直观的可视化,但是当数据存在大量节点和边时,视觉混乱(Visual Clutter)很快成为严重的问题。点-线图中的视觉混乱通常是边缘拥塞的直接结果,而在如交通网络一类数据中,节点位置通常具有明确定义的含义,并不总是可以修改节点位置以减少视觉混乱,如图 1~4 四个例子。因此,学术界诸多研究者设计了各种通过优化边的方式减轻上述视觉混乱,其中边绑定(Edge Bundling)方法被广泛研究和应用。各种边绑定的方法总结在【<a href=\"https://yuque.antfin-inc.com/shiwu.wyy/go1ec6/znmtuw\" target=\"_self\" rel=\"nofollow\">链接</a>】。</p>\n<p>例如下面这一个复杂的美国航线数据集,节点代表美国城市,带有坐标和经纬度信息;一条边代表一条航线:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"nodes\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">{</span>\n        <span class=\"token property\">\"x\"</span><span class=\"token operator\">:</span> <span class=\"token number\">-922.24444</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"y\"</span><span class=\"token operator\">:</span> <span class=\"token number\">347.29444</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"lon\"</span><span class=\"token operator\">:</span> <span class=\"token number\">-92.224444</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"lat\"</span><span class=\"token operator\">:</span> <span class=\"token number\">34.729444</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token property\">\"x\"</span><span class=\"token operator\">:</span> <span class=\"token number\">-922.24444</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"y\"</span><span class=\"token operator\">:</span> <span class=\"token number\">347.29444</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"1\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"lon\"</span><span class=\"token operator\">:</span> <span class=\"token number\">-92.224444</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"lat\"</span><span class=\"token operator\">:</span> <span class=\"token number\">34.729444</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    ...\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"edges\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token punctuation\">{</span>\n        <span class=\"token property\">\"source\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"0\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"target\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"21\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"e0\"</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token property\">\"source\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"2\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"target\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"13\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"e1\"</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      ...\n    <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>如果使用 G6 简单地将节点和边渲染出来,将会得到如下结果:<br /><img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648654-2890e390-4f54-4e64-a371-99eede5e739c.png#align=left&#x26;display=inline&#x26;height=512&#x26;name=image.png&#x26;originHeight=922&#x26;originWidth=1994&#x26;search=&#x26;size=1416365&#x26;status=done&#x26;width=1107.777807123868\" alt=\"image.png\"></p>\n<blockquote>\n<p>图 5. G6 渲染原始数据结果</p>\n</blockquote>\n<p>我们发现简单地将该数据渲染后的结果航线纵横交错,穿梭在密集的城市当中,视觉上十分混乱,即难以看清细节,也不能发现航线的总体趋势。</p>\n<h2 id=\"期待效果\"><a href=\"#%E6%9C%9F%E5%BE%85%E6%95%88%E6%9E%9C\" aria-label=\"期待效果 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>期待效果</h2>\n<p>我们希望可以通过边绑定的方法降低图 5 的视觉混乱,从而清晰图的整体走势、结构,突出航线频繁的城市,它们可能是重要的交通枢纽,并展示更多的统计信息,以便观察者进行分析。借助 G6,我们可以实现如下效果。通过边绑定,边的交错混乱情况被降低,颜色映射航班的飞行方向(出发(橙红色)与降落(青色))。节点大小表示到达与离开该城市的航班总数量,每个节点使用了饼图展示达到(橙红色)和离开(青色)航班的比例。并增加 hover 的交互,使用 tooltip 展示每个城市的经纬度。<br /><img src=\"https://cdn.nlark.com/yuque/0/2019/gif/156681/1564995648666-448000ab-e568-4859-96b8-d191685c79fa.gif#align=left&#x26;display=inline&#x26;height=451&#x26;name=airline-bundling-tooltip.gif&#x26;originHeight=451&#x26;originWidth=1002&#x26;search=&#x26;size=479148&#x26;status=done&#x26;width=1002\" alt=\"airline-bundling-tooltip.gif\"></p>\n<blockquote>\n<p>期待效果图及 tooltip 效果。</p>\n</blockquote>\n<h2 id=\"实现步骤\"><a href=\"#%E5%AE%9E%E7%8E%B0%E6%AD%A5%E9%AA%A4\" aria-label=\"实现步骤 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>实现步骤</h2>\n<h3 id=\"统计必要信息\"><a href=\"#%E7%BB%9F%E8%AE%A1%E5%BF%85%E8%A6%81%E4%BF%A1%E6%81%AF\" aria-label=\"统计必要信息 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>统计必要信息</h3>\n<p>首先,我们使用简单的 JS 根据数据统计每个节点的总度数(degree,即出入该城市的航线总数)、出度(outDegree,即飞出该城市的航线数)、入度(inDegree,即飞入该城市成航线数),为后续映射到节点上做好准备。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> nodes <span class=\"token operator\">=</span> data<span class=\"token punctuation\">.</span>nodes<span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> edges <span class=\"token operator\">=</span> data<span class=\"token punctuation\">.</span>edges<span class=\"token punctuation\">;</span>\nnodes<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  n<span class=\"token punctuation\">.</span>y <span class=\"token operator\">=</span> <span class=\"token operator\">-</span>n<span class=\"token punctuation\">.</span>y<span class=\"token punctuation\">;</span>\n  n<span class=\"token punctuation\">.</span>degree <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n  n<span class=\"token punctuation\">.</span>inDegree <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n  n<span class=\"token punctuation\">.</span>outDegree <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// compute the degree of each node</span>\n<span class=\"token keyword\">const</span> nodeIdMap <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nnodes<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">node</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  nodeIdMap<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> node<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nedges<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> source <span class=\"token operator\">=</span> nodeIdMap<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>source<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> target <span class=\"token operator\">=</span> nodeIdMap<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  source<span class=\"token punctuation\">.</span>outDegree<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n  target<span class=\"token punctuation\">.</span>inDegree<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n  source<span class=\"token punctuation\">.</span>degree<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n  target<span class=\"token punctuation\">.</span>degree<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> maxDegree <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">9999</span><span class=\"token punctuation\">,</span>\n  minDegree <span class=\"token operator\">=</span> <span class=\"token number\">9999</span><span class=\"token punctuation\">;</span>\nnodes<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>maxDegree <span class=\"token operator\">&lt;</span> n<span class=\"token punctuation\">.</span>degree<span class=\"token punctuation\">)</span> maxDegree <span class=\"token operator\">=</span> n<span class=\"token punctuation\">.</span>degree<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>minDegree <span class=\"token operator\">></span> n<span class=\"token punctuation\">.</span>degree<span class=\"token punctuation\">)</span> minDegree <span class=\"token operator\">=</span> n<span class=\"token punctuation\">.</span>degree<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> sizeRange <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">20</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> degreeDataRange <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>minDegree<span class=\"token punctuation\">,</span> maxDegree<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// 将范围是 degreeDataRange 的 degree 属性映射到范围 sizeRange 上后,</span>\n<span class=\"token comment\">// 写入到 nodes 中元素的‘size’属性中</span>\n<span class=\"token function\">scaleNodeProp</span><span class=\"token punctuation\">(</span>nodes<span class=\"token punctuation\">,</span> <span class=\"token string\">'size'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'degree'</span><span class=\"token punctuation\">,</span> degreeDataRange<span class=\"token punctuation\">,</span> sizeRange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<p><code class=\"language-text\">scaleNodeProp()</code> 方法将指定的节点属性 <code class=\"language-text\">refPropName</code> 根据给定数值范围 <code class=\"language-text\">outRange</code> 归一化,映射到另一个属性 <code class=\"language-text\">propName</code> 上:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">/**\n * 映射属性\n * @param  {array} nodes          对象数组\n * @param  {string} propName      写入的属性名称\n * @param  {string} refPropName   被归一化的属性名称\n * @param  {array} dataRange      被归一化的属性的值范围 [min, max]\n * @param  {array} outRange       写入的属性的值范围 [min, max]\n */</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">scaleNodeProp</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">nodes<span class=\"token punctuation\">,</span> propName<span class=\"token punctuation\">,</span> refPropName<span class=\"token punctuation\">,</span> dataRange<span class=\"token punctuation\">,</span> outRange</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> outLength <span class=\"token operator\">=</span> outRange<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">-</span> outRange<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> dataLength <span class=\"token operator\">=</span> dataRange<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">-</span> dataRange<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  nodes<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">n</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    n<span class=\"token punctuation\">[</span>propName<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">[</span>refPropName<span class=\"token punctuation\">]</span> <span class=\"token operator\">-</span> dataRange<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">*</span> outLength<span class=\"token punctuation\">)</span> <span class=\"token operator\">/</span> dataLength <span class=\"token operator\">+</span> outRange<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n</code></pre></div>\n<p>通过上面两段代码,我们已经将归一化的度数映射到节点大小 <code class=\"language-text\">size</code> 上。</p>\n<h3 id=\"实例化边绑定插件\"><a href=\"#%E5%AE%9E%E4%BE%8B%E5%8C%96%E8%BE%B9%E7%BB%91%E5%AE%9A%E6%8F%92%E4%BB%B6\" aria-label=\"实例化边绑定插件 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>实例化边绑定插件</h3>\n<p>G6 中提供的边绑定插件是基于 FEDB(<a href=\"http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.212.7989&#x26;rep=rep1&#x26;type=pdf\" target=\"_self\" rel=\"nofollow\">Force-Directed Edge Bundling for Graph Visualization</a>)一文的实现。可以通过调节参数调整边绑定的效果。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> edgeBundling <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bundling</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  bundleThreshold<span class=\"token punctuation\">:</span> <span class=\"token number\">0.6</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 绑定的容忍度。数值越低,被绑定在一起的边相似度越高,即被绑在一起的边更少。</span>\n  <span class=\"token constant\">K</span><span class=\"token punctuation\">:</span> <span class=\"token number\">100</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 绑定的强度</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<h3 id=\"自定义饼图节点\"><a href=\"#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%A5%BC%E5%9B%BE%E8%8A%82%E7%82%B9\" aria-label=\"自定义饼图节点 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>自定义饼图节点</h3>\n<p>在第一步中,我们已经为节点大小 size 映射了每个节点的总度数。为了更详细展示每个城市飞出和飞入航班的比例,我们希望在每个节点上显示一个类似于饼图的效果。例如<img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648747-ae1d21c9-64ed-494b-8835-c5b096fba7e2.png#align=left&#x26;display=inline&#x26;height=45&#x26;name=image.png&#x26;originHeight=148&#x26;originWidth=158&#x26;search=&#x26;size=17728&#x26;status=done&#x26;width=48\" alt=\"image.png\"> ,桔红色扇形代表飞入该城市的航班比例,青色代表飞出该城市的航班比例。G6 原生的 circle 、rect 等节点形状不能满足这一需求,但 G6 提供了节点的扩展机制,通过下面的代码片段,可以在 G6 中注册一个自定义的节点:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> lightBlue <span class=\"token operator\">=</span> <span class=\"token string\">'rgb(119, 243, 252)'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> lightOrange <span class=\"token operator\">=</span> <span class=\"token string\">'rgb(230, 100, 64)'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 注册自定义名为 pie-node 的节点类型</span>\n<span class=\"token constant\">G6</span><span class=\"token punctuation\">.</span><span class=\"token function\">registerNode</span><span class=\"token punctuation\">(</span>\n  <span class=\"token string\">'pie-node'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">{</span>\n    <span class=\"token function-variable function\">drawShape</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">cfg<span class=\"token punctuation\">,</span> group</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> radius <span class=\"token operator\">=</span> cfg<span class=\"token punctuation\">.</span>size <span class=\"token operator\">/</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 节点半径</span>\n      <span class=\"token keyword\">const</span> inPercentage <span class=\"token operator\">=</span> cfg<span class=\"token punctuation\">.</span>inDegree <span class=\"token operator\">/</span> cfg<span class=\"token punctuation\">.</span>degree<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 入度占总度数的比例</span>\n      <span class=\"token keyword\">const</span> inAngle <span class=\"token operator\">=</span> inPercentage <span class=\"token operator\">*</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 入度在饼图中的夹角大小</span>\n      <span class=\"token keyword\">const</span> outAngle <span class=\"token operator\">=</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> <span class=\"token number\">2</span> <span class=\"token operator\">-</span> inAngle<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 出度在饼图中的夹角大小</span>\n      <span class=\"token keyword\">const</span> inArcEnd <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>radius <span class=\"token operator\">*</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">cos</span><span class=\"token punctuation\">(</span>inAngle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> radius <span class=\"token operator\">*</span> Math<span class=\"token punctuation\">.</span><span class=\"token function\">sin</span><span class=\"token punctuation\">(</span>inAngle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//入度饼图弧结束位置</span>\n      <span class=\"token keyword\">let</span> isInBigArc <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n        isOutBigArc <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>inAngle <span class=\"token operator\">></span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        isInBigArc <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n        isOutBigArc <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n      <span class=\"token comment\">// 定义代表入度的扇形形状</span>\n      <span class=\"token keyword\">const</span> fanIn <span class=\"token operator\">=</span> group<span class=\"token punctuation\">.</span><span class=\"token function\">addShape</span><span class=\"token punctuation\">(</span><span class=\"token string\">'path'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n        attrs<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n          path<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'M'</span><span class=\"token punctuation\">,</span> radius<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'A'</span><span class=\"token punctuation\">,</span> radius<span class=\"token punctuation\">,</span> radius<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> isInBigArc<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> inArcEnd<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> inArcEnd<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'L'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'B'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n          lineWidth<span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n          fill<span class=\"token punctuation\">:</span> lightOrange<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token comment\">// 定义代表出度的扇形形状</span>\n      <span class=\"token keyword\">const</span> fanOut <span class=\"token operator\">=</span> group<span class=\"token punctuation\">.</span><span class=\"token function\">addShape</span><span class=\"token punctuation\">(</span><span class=\"token string\">'path'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n        attrs<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n          path<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'M'</span><span class=\"token punctuation\">,</span> inArcEnd<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> inArcEnd<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'A'</span><span class=\"token punctuation\">,</span> radius<span class=\"token punctuation\">,</span> radius<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> isOutBigArc<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> radius<span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'L'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n            <span class=\"token punctuation\">[</span><span class=\"token string\">'B'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n          <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n          lineWidth<span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n          fill<span class=\"token punctuation\">:</span> lightBlue<span class=\"token punctuation\">,</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token comment\">// 返回 keyshape</span>\n      <span class=\"token keyword\">return</span> fanIn<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">'single-shape'</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<p>这样,我们就在 G6 中注册了一个名为 pie-node 的节点类型。</p>\n<h3 id=\"实例化图\"><a href=\"#%E5%AE%9E%E4%BE%8B%E5%8C%96%E5%9B%BE\" aria-label=\"实例化图 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>实例化图</h3>\n<p>在这一步中,我们在实例化图时,并为之指定边绑定插件、节点类型(刚才自定义的 pie-node)、节点样式、边样式(渐变色)。</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> edgeBundling <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Bundling</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  bundleThreshold<span class=\"token punctuation\">:</span> <span class=\"token number\">0.6</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 绑定的容忍度。数值越低,被绑定在一起的边相似度越高,即被绑在一起的边更少。</span>\n  <span class=\"token constant\">K</span><span class=\"token punctuation\">:</span> <span class=\"token number\">100</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 绑定的强度</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> graph <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">G6<span class=\"token punctuation\">.</span>Graph</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  container<span class=\"token punctuation\">:</span> <span class=\"token string\">'mountNode'</span><span class=\"token punctuation\">,</span>\n  width<span class=\"token punctuation\">:</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">,</span>\n  height<span class=\"token punctuation\">:</span> <span class=\"token number\">800</span><span class=\"token punctuation\">,</span>\n  plugins<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>edgeBundling<span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 加入插件</span>\n  fitView<span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  defaultNode<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    size<span class=\"token punctuation\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span>\n    color<span class=\"token punctuation\">:</span> <span class=\"token string\">'steelblue'</span><span class=\"token punctuation\">,</span>\n    fill<span class=\"token punctuation\">:</span> <span class=\"token string\">'steelblue'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  nodeStyle<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">default</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      lineWidth<span class=\"token punctuation\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n      fill<span class=\"token punctuation\">:</span> <span class=\"token string\">'steelblue'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  edgeStyle<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">default</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      lineWidth<span class=\"token punctuation\">:</span> <span class=\"token number\">0.7</span><span class=\"token punctuation\">,</span>\n      strokeOpacity<span class=\"token punctuation\">:</span> <span class=\"token number\">0.1</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// 设置边透明度,在边聚集的部分透明度将会叠加,从而具备突出高密度区域的效果</span>\n      stroke<span class=\"token punctuation\">:</span> <span class=\"token string\">'l(0) 0:'</span> <span class=\"token operator\">+</span> llightBlue16 <span class=\"token operator\">+</span> <span class=\"token string\">' 1:'</span> <span class=\"token operator\">+</span> llightOrange16<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<p>这里出发端的颜色为 <code class=\"language-text\">llightBlue16</code>,结束端的颜色为 <code class=\"language-text\">llightOrange16</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> llightBlue16 <span class=\"token operator\">=</span> <span class=\"token string\">'#C8FDFC'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> llightOrange16 <span class=\"token operator\">=</span> <span class=\"token string\">'#FFAA86'</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<p>为了配合节点和边的颜色,这里将页面的 body 的颜色设置为黑色:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>style</span><span class=\"token punctuation\">></span></span><span class=\"token style\"><span class=\"token language-css\">\n  <span class=\"token selector\">body</span><span class=\"token punctuation\">{</span>\n    <span class=\"token property\">background</span><span class=\"token punctuation\">:</span> <span class=\"token function\">rgb</span><span class=\"token punctuation\">(</span>0<span class=\"token punctuation\">,</span> 0<span class=\"token punctuation\">,</span> 0<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>style</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h3 id=\"执行绑定和渲染\"><a href=\"#%E6%89%A7%E8%A1%8C%E7%BB%91%E5%AE%9A%E5%92%8C%E6%B8%B2%E6%9F%93\" aria-label=\"执行绑定和渲染 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>执行绑定和渲染</h3>\n<p>有了 graph 实例和 edgeBundling 实例后,我们执行下面代码进行绑定操作和图的数据读入及渲染:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\">edgeBundling<span class=\"token punctuation\">.</span><span class=\"token function\">bundling</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 执行插件的绑定操作</span>\ngraph<span class=\"token punctuation\">.</span><span class=\"token function\">data</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ngraph<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n</code></pre></div>\n<h4 id=\"设置-tooltip-与交互操作\"><a href=\"#%E8%AE%BE%E7%BD%AE-tooltip-%E4%B8%8E%E4%BA%A4%E4%BA%92%E6%93%8D%E4%BD%9C\" aria-label=\"设置 tooltip 与交互操作 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>设置 tooltip 与交互操作</h4>\n<p>使用 tooltip,可以在鼠标 hover 到节点上时展示该节点的其他属性值。首先在 html 中设定 tooltip 的样式:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>style</span><span class=\"token punctuation\">></span></span><span class=\"token style\"><span class=\"token language-css\">\n  <span class=\"token selector\">.g6-tooltip</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">border</span><span class=\"token punctuation\">:</span> 1px solid #e2e2e2<span class=\"token punctuation\">;</span>\n    <span class=\"token property\">border-radius</span><span class=\"token punctuation\">:</span> 4px<span class=\"token punctuation\">;</span>\n    <span class=\"token property\">font-size</span><span class=\"token punctuation\">:</span> 12px<span class=\"token punctuation\">;</span>\n    <span class=\"token property\">color</span><span class=\"token punctuation\">:</span> #545454<span class=\"token punctuation\">;</span>\n    <span class=\"token property\">background-color</span><span class=\"token punctuation\">:</span> <span class=\"token function\">rgba</span><span class=\"token punctuation\">(</span>255<span class=\"token punctuation\">,</span> 255<span class=\"token punctuation\">,</span> 255<span class=\"token punctuation\">,</span> 0.9<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token property\">padding</span><span class=\"token punctuation\">:</span> 10px 8px<span class=\"token punctuation\">;</span>\n    <span class=\"token property\">box-shadow</span><span class=\"token punctuation\">:</span> <span class=\"token function\">rgb</span><span class=\"token punctuation\">(</span>174<span class=\"token punctuation\">,</span> 174<span class=\"token punctuation\">,</span> 174<span class=\"token punctuation\">)</span> 0px 0px 10px<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>style</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>然后,在上一步实例化 <code class=\"language-text\">graph</code> 时,增加一个名为 <code class=\"language-text\">modes</code> 的配置项到参数中,如下写法启动了 <code class=\"language-text\">drag-canvas</code> 画图拖动操作、<code class=\"language-text\">zoom-canvas</code> 画布放缩操作,以及 <code class=\"language-text\">tooltip</code>,在 <code class=\"language-text\">formatText</code> 函数中指定了 <code class=\"language-text\">tooltip</code> 显示的文本内容:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"> modes<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n   <span class=\"token keyword\">default</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span> <span class=\"token string\">'drag-canvas'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'zoom-canvas'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n     type<span class=\"token punctuation\">:</span> <span class=\"token string\">'tooltip'</span><span class=\"token punctuation\">,</span>\n     <span class=\"token function\">formatText</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">model</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">const</span> text <span class=\"token operator\">=</span> <span class=\"token string\">'Longitude: '</span> <span class=\"token operator\">+</span> model<span class=\"token punctuation\">.</span>lon <span class=\"token operator\">+</span> <span class=\"token string\">'\\n Latitude: '</span> <span class=\"token operator\">+</span> model<span class=\"token punctuation\">.</span>lat<span class=\"token punctuation\">;</span>\n       <span class=\"token keyword\">return</span> text<span class=\"token punctuation\">;</span>\n     <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n     <span class=\"token function-variable function\">shouldUpdate</span><span class=\"token punctuation\">:</span> <span class=\"token parameter\">e</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n       <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span>\n     <span class=\"token punctuation\">}</span>\n   <span class=\"token punctuation\">}</span><span class=\"token punctuation\">]</span>\n <span class=\"token punctuation\">}</span></code></pre></div>\n<p>这样,当鼠标移动到节点上时,带有经纬度信息的 <code class=\"language-text\">tooltip</code> 将会出现:<br /><img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648674-8bc9a379-d48b-48d7-b63d-3e414768c8a9.png#align=left&#x26;display=inline&#x26;height=146&#x26;name=image.png&#x26;originHeight=262&#x26;originWidth=666&#x26;search=&#x26;size=229546&#x26;status=done&#x26;width=370.00000980165294\" alt=\"image.png\"></p>\n<blockquote>\n<p>tooltip</p>\n</blockquote>\n<p>同时,可以拖拽和放缩画布:<img src=\"https://cdn.nlark.com/yuque/0/2019/gif/156681/1564995648669-120d675c-04ac-40a6-8b28-3872327960d1.gif#align=left&#x26;display=inline&#x26;height=699&#x26;name=airline-bundling-interact.gif&#x26;originHeight=699&#x26;originWidth=1002&#x26;search=&#x26;size=2613127&#x26;status=done&#x26;width=1002\" alt=\"airline-bundling-interact.gif\"></p>\n<blockquote>\n<p>缩放和拖动画布。</p>\n</blockquote>\n<h2 id=\"分析\"><a href=\"#%E5%88%86%E6%9E%90\" aria-label=\"分析 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>分析</h2>\n<p><img src=\"https://cdn.nlark.com/yuque/0/2019/png/156681/1564995648703-5630a47e-250c-4fc3-845a-3f1fe176e2c9.png#align=left&#x26;display=inline&#x26;height=487&#x26;name=image.png&#x26;originHeight=876&#x26;originWidth=1984&#x26;search=&#x26;size=1674617&#x26;status=done&#x26;width=1102.2222514211403\" alt=\"image.png\"></p>\n<blockquote>\n<p>最终效果图。节点大小代表飞入及飞出该城市航线总数。节点饼图展示飞出与飞入航线比例统计信息(橙红色为飞入,青色为飞出)。边的渐变色代表航班的飞行方向。起始端:青色;结束端:橙红色。</p>\n</blockquote>\n<p>最后,让我们一起分析如下的最终结果图给我们带来的信息:</p>\n<ul>\n<li>大节点主要集中在中偏东部,根据其经纬度,可以推测这些城市有:亚特兰大、纽约、芝加哥、休斯顿、堪萨斯等,这些城市都是美国重要的交通枢纽;</li>\n<li>美国东部的线桔红色居多,说明东部城市的飞入航班较多;</li>\n<li>相反,西部城市的飞出航班较多;</li>\n<li>整体飞行方向从东至西;</li>\n<li>东部的航线也较之于西部更加密集、频繁;</li>\n<li>西海岸由西雅图和波特兰飞往洛杉矶的航班较多。</li>\n</ul>\n<p>上述发现很容易被解释:美国东部是美国的经济、政治集中区域。</p>"}