本示例是基於Typescript 和 D3 五版本繪製樹狀圖。
網上絕大多數都是D3 3版本,四版本也有一些示例,比較少,5版本幾乎沒有。這裏是結合TS 和 D3 5版本的一個示例:
直接上代碼:
/**
* create by yanle
* create time 2018-10-30 15:21
*/
import {hierarchy, tree} from "d3-hierarchy";
import {DefaultLinkObject, line, Link, linkHorizontal, linkVertical} from "d3-shape";
import {select, selectAll} from "d3-selection";
class Demo8 {
private treeData: any = {
"name": "中國",
"children":
[
{
"name": "浙江",
"children":
[
{"name": "杭州"},
{"name": "寧波"},
{"name": "溫州"},
{"name": "紹興"}
]
},
{
"name": "廣西",
"children":
[
{
"name": "桂林",
"children":
[
{"name": "秀峯區"},
{"name": "疊彩區"},
{"name": "象山區"},
{
"name": "七星區",
"children":
[
{"name": "哈爾濱"},
{"name": "齊齊哈爾"},
{"name": "牡丹江"},
{"name": "大慶"}
]
}
]
},
{"name": "南寧"},
{"name": "柳州"},
{"name": "防城港"}
]
},
{
"name": "黑龍江",
"children":
[
{"name": "哈爾濱"},
{"name": "齊齊哈爾"},
{"name": "牡丹江"},
{"name": "大慶"}
]
},
{
"name": "新疆",
"children":
[
{"name": "烏魯木齊"},
{"name": "克拉瑪依"},
{"name": "吐魯番"},
{"name": "哈密"}
]
}
]
};
main() {
let width: number = 900;
let height: number = 1400;
let treeWidth: number = width - 50;
let treeHeight: number = height - 50;
let treeMain = tree()
.size([width, treeWidth - 300])
.separation(function (a, b) {
return (a.parent === b.parent) ? 1 : 2
});
const hierarchyData = hierarchy(this.treeData).sum(function (d) {
return d.value
});
// 這樣寫是爲了 讓數據橫向顯示 x, y 互換
const renderLink: Link<any, DefaultLinkObject, [number, number]> = linkHorizontal().x(function (d: any) {
return d.y
}).y(function (d: any) {
return d.x
});
const lineMain = line();
// 創建svg
let svg = select('body')
.append('svg')
.attr('width', treeWidth)
.attr('height', treeHeight)
.append('g')
.attr('transform', 'translate(40, 0)');
let g = svg.append('g').attr('transform', 'translate(40, 40)');
treeMain(hierarchyData);
const nodes = hierarchyData.descendants();
const links = hierarchyData.links();
// 繪製線
g.selectAll('.link')
.data(links)
.enter()
.append('path')
.attr('class', 'link')
.attr("fill", "none") // 這個是取消默認填充色
.attr("stroke", "#000") // 給與一個自己的 外框填充色
.attr('d', function (d: any) {
return renderLink(d)
});
// 繪製節點
g.selectAll('.node')
.data(nodes)
.enter()
.append('g')
.attr('class', 'node')
.attr('transform', function (d: any) { // 這樣寫是爲了 讓數據橫向顯示
return `translate(${d.y}, ${d.x})`
});
g.selectAll('.node')
.append('circle')
.attr('r', 5)
.attr('fill', 'green');
// 繪製文字
g.selectAll('.node')
.append('text')
.attr('dy', 3)
.attr('x', function (d: any) {
return d.children ? -8 : 8;
})
.attr('text-anchor', function (d: any) {
return d.children ? 'end' : 'start'
})
.text(function (d: any) {
return d.data.name
})
.style('font-size', '18px')
}
}
export default Demo8;
相關api介紹:
api | 說明 :- | :- **d3.hierarchy** | **從給定的層次結構數據構造一個根節點併爲各個節點指定深度等屬性.** node.ancestors | 從當前節點開始返回其祖先節點數組. node.descendants | 從當前節點開始返回其後代節點數組. node.leaves | 返回當前節點爲根節點的子樹的葉節點. node.path | 返回從當前節點到指定目標節點的最短路徑. node.links | 返回當前節點所在子樹的所有邊. node.sum | 評估和彙總定量值. node.sort | 排序所有的後代兄弟節點. node.count | 統計葉節點的個數. node.each | 廣度優先遍歷當前子樹. node.eachAfter | 後續遍歷當前子樹. node.eachBefore | 前序遍歷當前子樹. node.copy | 拷貝一個當前節點爲根節點的子樹的副本. **d3.stratify** | **創建一個新的分層操作.** stratify | 根據扁平數據創建一個分層數據. stratify.id | 設置節點 id 訪問器. stratify.parentId | 設置父節點 id 訪問器. **d3.cluster** | **創建一個新的集羣(系統樹圖)佈局.** cluster | 將指定的數據佈局爲系統樹圖. cluster.size | 設置佈局尺寸. cluster.nodeSize | 設計節點尺寸. cluster.separation | 設置兩個葉節點之間的間距. **d3.tree** | **創建一個新的整齊(同深度節點對齊)的樹佈局.** tree | 將指定的層次數據佈局爲整齊的樹佈局. tree.size | 設置佈局尺寸. tree.nodeSize | 設置節點尺寸. tree.separation | 設置兩個相鄰的節點之間的間距.
具體項目請見github: https://github.com/yanlele/D3.js-learning