这篇文章给大家介绍一下如何用 G2 的 Tree Mark 去绘制如下的树图,该树图展示了 G2 的能力。
G2 的 Library
G2 的能力是通过 G2 的 Library 来体现的,这里先对 Library 进行简单的介绍。
G2 的 Library 本质上是一个函数,该函数会返回一个 JavaScript 对象,通过 ${namespace}.${name}
形式的 key 索引 G2 可视化需要的可视化组件。比如 stdlib:
javascript
function stdlib() {
return {
'mark.interval': Interval,
'mark.point': Point,
'scale.linear': Linear,
'scale.log': Log,
// ...
}
}
其中每个可视化组件都是一个函数,属于不同 namespace 的组件在可视化的过程中有不同的作用。比如上面的 scale 组件主要用于数据映射,mark 组件主要用来绘制图形。在使用 G2 的过程中,可以如下指定不同的 library 去获得不同的可视化能力。比如绘制地图:
javascript
import { Runtime, corelib, geolib, extend } from '@antv/g2';
// 对 Runtime 进行扩展
// 同时使用 corelib 和 geolib
const Chart = extend(runtime, {
...corelib(),
...geolib()
});
const chart = new Chart();
chart.geoPath(); // 绘制地图
包括 stdlib,G2 内置的 Library 如下:
- stdlib - 包含非 threedlib 的所有能力
- corelib - 基础可视化
- plotlib - 复杂统计可视化
- geolib - 地理可视化
- graphlib - 图可视化
- threedlib - 3D 可视化
接下来,我们就通过可视化来更好地了解它们。
准备数据
首先我们需要把 Library 的数据结构转换成如下 Tree Mark 需要的结构,一个拥有 name 和 children 的嵌套 JavaScritp 对象:
javascript
({
name: 'a',
children: [
{ name: 'b' },
{
name: 'c',
children: [{ name: 'c' }],
},
],
});
这里我们借助 d3.groups 函数将可视化组件按照它们的 namespace 进行分组,并且将每一个组作为一个节点,作为由 Library 的名字构成的根节点的孩子节点。具体的实现如下:
javascript
function dataOf(lib) {
const library = G2[lib]();
const groups = d3
.groups(Object.entries(library), ([key]) => key.split(".")[0])
.map(([name, nodes]) => ({
name,
value: nodes.length,
children: nodes.map(([d, f]) => ({
name: d.split(".")[1],
// 将打包后的函数片段的字符长度简单认为是代码大小
value: `${f}`.length
}))
}));
return { name: lib, children: groups };
}
计算高度
为了美观,我们希望保证每个叶子节点的高度稳定,所以我们需要根据节点的数量去计算最后可视化的高度。这里的每个叶子节点对应一个可视化组件,所以简单统计可视化组件数量即可,代码如下:
javascript
function heightOf(lib) {
const library = G2[lib]();
const count = Object.keys(library).length;
const padding = 20;
const nodeHeight = count < 10 ? 20 : 10;
return count * nodeHeight + padding * 2;
}
可视化
当数据和图表高度都准备好了,接下来就是最后的可视化了。这个过程很简单,只需要把数据交给 Tree Mark,然后通过 tree.style
去指定节点和边的样式即可,其中的布局和数据转化的工作,G2 内部已经帮你完成了。完整的代码如下:
javascript
const data = dataOf('stdlib');
const height = heightOf('stdlib');
const chart = new G2.Chart({
container:'container'
});
chart.options({
type: "view",
width,
height,
paddingLeft: 60,
paddingRight: 100,
// 绘制横向的树图
coordinate: { transform: [{ type: "transpose" }] },
children: [
{
type: "tree",
// 绑定数据
data: { value: data },
// 设置样式
style: {
nodeFill: (d) => (d.height === 0 ? "#999" : "#000"),
linkStroke: "#999",
labelText: (d) => d.data.name || "-",
labelFontSize: (d) => (d.height === 0 ? 7 : 12),
labelTextAlign: (d) => (d.height === 0 ? "start" : "end"),
labelPosition: (d) => (d.height !== 0 ? "left" : "right"),
labelDx: (d) => (d.height === 0 ? 5 : -5),
labelBackground: true,
labelBackgroundFill: "#fff"
}
}
]
});
chart.render();
小结
这篇文章给大家简单介绍了 G2 的 Library 和 Tree Mark 的使用,这里有可以交互的案例。针对如下相同的数据,还有更多的可视化方法。比如用 Treemap 去分析不同组件的大小:
用 CirclePack 去高效和清晰地去了解组件:
甚至将数据转换成图数据之后,用 ForceGraph 了解组件之间的关系:
大家可以简单看看如何用 G2 绘制这些效果,然后去可视化自己的数据吧!