建立一個網路拓撲的結構圖,可視覺化呈現階層分類的資料。
範例:
const tree = data => {
const root = d3.hierarchy(data);
root.dx = 10;
root.dy = 200;
return d3.tree().nodeSize([root.dx, root.dy])(root);
}
const root = tree(data);
d3.hierarchy(data)
就是之前提到過,d3
會協助遍歷結構型的資料,可產出相關深度等等資料。
root.dx = 10;
root.dy = 200;
dx
如果設定為100,每一個資料水平階層會相當的寬。
dy
如果設定為20,每一個資料垂直階層會相當的窄。
以上就是針對圖階層的長度寬度。
範例
const node = g.append("g")
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", d => `translate(${d.y},${d.x})`)
root.descendants
可協助將資料轉成具有x, y
定位的拓撲圖,這時候其實已經完成八成,因為位置已經有了,只差繪製。
下半部開始閱讀。
範例:
console.clear();
const width = 800;
const height = 600;
const treeData = {
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "value": 3938},
{"name": "CommunityStructure", "value": 3812},
{"name": "HierarchicalCluster", "value": 6714},
{"name": "MergeEdge", "value": 743}
]
},
{
"name": "graph",
"children": [
{"name": "BetweennessCentrality", "value": 3534},
{"name": "LinkDistance", "value": 5731},
{"name": "MaxFlowMinCut", "value": 7840},
{"name": "ShortestPaths", "value": 5914},
{"name": "SpanningTree", "value": 3416}
]
},
{
"name": "optimization",
"children": [
{"name": "AspectRatioBanker", "value": 7074}
]
}
]
},
{
"name": "animate",
"children": [
{"name": "Easing", "value": 17010},
{"name": "FunctionSequence", "value": 5842},
{
"name": "interpolate",
"children": [
{"name": "ArrayInterpolator", "value": 1983},
{"name": "ColorInterpolator", "value": 2047},
{"name": "DateInterpolator", "value": 1375},
{"name": "Interpolator", "value": 8746},
{"name": "MatrixInterpolator", "value": 2202},
{"name": "NumberInterpolator", "value": 1382},
{"name": "ObjectInterpolator", "value": 1629},
{"name": "PointInterpolator", "value": 1675},
{"name": "RectangleInterpolator", "value": 2042}
]
},
{"name": "ISchedulable", "value": 1041},
{"name": "Parallel", "value": 5176},
{"name": "Pause", "value": 449},
{"name": "Scheduler", "value": 5593},
{"name": "Sequence", "value": 5534},
{"name": "Transition", "value": 9201},
{"name": "Transitioner", "value": 19975},
{"name": "TransitionEvent", "value": 1116},
{"name": "Tween", "value": 6006}
]
},
{
"name": "data",
"children": [
{
"name": "converters",
"children": [
{"name": "Converters", "value": 721},
{"name": "DelimitedTextConverter", "value": 4294},
{"name": "GraphMLConverter", "value": 9800},
{"name": "IDataConverter", "value": 1314},
{"name": "JSONConverter", "value": 2220}
]
},
{"name": "DataField", "value": 1759},
{"name": "DataSchema", "value": 2165},
{"name": "DataSet", "value": 586},
{"name": "DataSource", "value": 3331},
{"name": "DataTable", "value": 772},
{"name": "DataUtil", "value": 3322}
]
},
{
"name": "display",
"children": [
{"name": "DirtySprite", "value": 8833},
{"name": "LineSprite", "value": 1732},
{"name": "RectSprite", "value": 3623},
{"name": "TextSprite", "value": 10066}
]
},
{
"name": "flex",
"children": [
{"name": "FlareVis", "value": 4116}
]
}
]
}
// 此部分才是重點
const tree = data => {
const root = d3.hierarchy(data);
root.dx = 10;
root.dy = 20;
return d3.tree().nodeSize([root.dx, root.dy])(root);
}
// 將資料轉為tree的格式
const root = tree(treeData);
const svg = d3.select('svg').attr('width', width).attr('height', height);
const g = svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("transform", `translate(50, 250)`);
// link是點跟點連線的灰色線條
const link = g.append("g")
.attr("fill", "none")
.attr("stroke", "#555")
.attr("stroke-opacity", 0.4)
.attr("stroke-width", 1.5)
.selectAll("path")
.data(root.links())
.join("path")
.attr("d", d3.linkHorizontal()
.x(d => d.y)
.y(d => d.x));
// 這部分是畫上圓圈的部分,透過`descendants`推測出目前資料的`x, y`位置。
const node = g.append("g")
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", d => `translate(${d.y},${d.x})`)
.each(data => console.log('data', data))
node.append("circle")
.attr("fill", d => d.children ? "#555" : "#999")
.attr("r", 2.5);
node.append("text")
.attr("dy", "0.31em")
.attr("x", d => d.children ? -6 : 6)
.attr("text-anchor", d => d.children ? "end" : "start")
.text(d => d.data.name)
.clone(true).lower()
.attr("stroke", "white");
這種圖目前我還沒有實際使用上,但可能對大量資料蒐集分析需要快速縱觀全局的時候,可能可以派得上用場。