# 樹圖
## 需求
主要是展示分層結構形數據,例如展示中國部分城市:
上海,西安,寶雞,北京,杭州,溫州
## 分析
首先建議閱讀[樹圖-中文](https://github.com/xswei/d3-hierarchy)
首先分析城市的層級,比如北京屬于直轄,西安屬于陜西。
``` javascript
var data = {
"name": "中國",
"children": [
{"name": "北京"},
{"name": "陜西",
"children": [
{"name": "寶雞"},
{"name": "西安"}
]
},
{"name": "上海"},
{"name": "浙江",
"children": [
{"name": "杭州"},
{"name": "溫州"}
]
},
]
}
```
為此我們可以得到這樣的數據結構。
我們簡要回顧餅圖制作,餅圖繪制需要使用d3.pie將數據轉化為利于繪制,之后使用d3.arc繪制。
層次類圖的繪制思路是相似的:
1. 將數據進行層次化,簡單來說就是為每個節點加入更多屬性:
* node .data - 為構造函數指定的關聯數據。
* node .depth - 根節點為零,每個后代生成增加1。
* node .height - 葉節點為零,與內部節點的任何后代葉的最大距離。
* node .parent - 父節點,或根節點為null。
* node .children - 子節點數組(如果有); 未定義葉節點。
* node .value - 節點及其后代的總和值; 可選的,見節點的.sum和節點 .Count之間。
2. 將層次化好的數據,通過如d3.tree等進行布局。簡單來說:就是通過設定當前繪制區域的大小,然后計算各節點的位置,大小等用于繪制的數據。
3. 通過繪制節點連線即可。
## 繪制
``` javascript
//創建svg
var svg = d3.select('#root')
.append('svg')
.attr('width', 600)
.attr('height', 600)
.style("background-color","rgb(142, 137, 137)");
var margin=[100,100,100,100]
var color = d3.scaleOrdinal(d3.schemeCategory20)
//模擬數據:
var data = {
"name": "中國",
"children": [
{"name": "北京"},
{"name": "陜西",
"children": [
{"name": "寶雞"},
{"name": "西安"}
]
},
{"name": "上海"},
{"name": "浙江",
"children": [
{"name": "杭州"},
{"name": "溫州"}
]
},
]
}
//將數據進行層次化
var dataSet = d3.hierarchy(data)
console.log(dataSet)
//創建樹布局
var tree = d3.tree()
.size([400,400])
//所有的節點
var node =tree(dataSet)
console.log(node)
//拿到所有節點
var nodes = node.descendants()
//可以拿到所有的連線點
var links = node.links()
//此處注意得到所有位置點是從上到下的
//而我們經常使用的是從左到右
//所以我們應該在繪制時顛倒x和y值
//分組
var nodeG = svg.append('g')
.attr('transform','translate(100,100)')
var linksG = svg.append('g')
.attr('transform','translate(100,100)')
// 繪制節點
nodeG.selectAll('circle').data(nodes)
.enter()
.append('circle')
.attr('cx',function(d){return d.x})
.attr('cy',function(d){return d.y})
.attr('r',20)
.attr('fill',function(d,i){color(i)})
//繪制連線
var line = d3.linkHorizontal()
.x(function (d) {console.log(d); return d.x })
.y(function (d) { return d.y })
linksG.selectAll('path')
.data(links)
.enter()
.append('path')
.attr('d',line)
.attr('fill','none')
.attr('stroke','#eee')
```
細節提示:
1. 在設置圖表垂直向下,或者水平向右的控制上沒有相關函數處理,但我們可以在繪制時調換xy,在調換xy處,需要同時調換d3.tree設置的寬高。
2. 繪制線條時應考慮:
* d3.linkVertical - 創建一個新的垂直 link 生成器.
* d3.linkHorizontal - 創建一個新的水平的 link 生成器.
3. 繪制連線是注意path應該將fill屬性設置為none。并設置stroke值。
4. 如圖實例tree0,注意層級關系,應該將link放置在node前繪制。
## 實例
[tree0](https://doter1995.github.io/d3-start-course/tree/tree-0.html)

[tree1](https://doter1995.github.io/d3-start-course/tree/tree-1.html)
