D3.js實現(xiàn)樹形圖的繪制教程詳解
數(shù)據(jù)
const data = {
"name": "中國",
"children": [
{"name": "北京"},
{"name": "陜西",
"children": [
{"name": "寶雞"},
{"name": "西安"}
]
},
{"name": "上海"},
{"name": "浙江",
"children": [
{"name": "杭州"},
{"name": "溫州"}
]
},
]
}層次化
d3.hierarchy
- d3.hierarchy(data[, children]) - 從給定的層次結(jié)構(gòu)數(shù)據(jù)構(gòu)造一個根節(jié)點并為各個節(jié)點指定深度等屬性.
- node.ancestors - 從當前節(jié)點開始返回其祖先節(jié)點數(shù)組.
- node.descendants - 從當前節(jié)點開始返回其后代節(jié)點數(shù)組.
- node.leaves - 返回當前節(jié)點為根節(jié)點的子樹的葉節(jié)點.
- node.find - 查找指定節(jié)點.
- node.path - 返回從當前節(jié)點到指定目標節(jié)點的最短路徑.
- node.links - 返回當前節(jié)點所在子樹的所有邊.
- node.sum - 評估和匯總定量值.
- node.sort - 排序所有的后代兄弟節(jié)點.
- node.count - 統(tǒng)計葉節(jié)點的個數(shù).
- node.each - 廣度優(yōu)先遍歷當前子樹.
- node.eachAfter - 后續(xù)遍歷當前子樹.
- node.eachBefore - 前序遍歷當前子樹.
- node.copy - 拷貝一個當前節(jié)點為根節(jié)點的子樹的副本.
const dataSet = d3.hierarchy(data) console.log(dataSet)

返回的節(jié)點和每一個后代會被附加如下屬性:
- node.data - 關(guān)聯(lián)的數(shù)據(jù)
- node.depth - 當前節(jié)點的深度, 根節(jié)點為
0. - node.height - 當前節(jié)點的高度, 葉節(jié)點為
0. - node.parent - 當前節(jié)點的父節(jié)點, 根節(jié)點為
null. - node.children - 當前節(jié)點的孩子節(jié)點(如果有的話); 葉節(jié)點為
undefined.
d3.hierarchy默認子節(jié)點取得是children屬性,當然也可以自定義: d3.hierarchy(data, d => d.child)。
d3.stratify
對于扁平數(shù)據(jù),我們可以用d3.stratify來實現(xiàn)數(shù)據(jù)的層次化:
let data = [
{"name": "Eve", "parent": ""},
{"name": "Cain", "parent": "Eve"},
{"name": "Seth", "parent": "Eve"},
{"name": "Enos", "parent": "Seth"},
{"name": "Noam", "parent": "Seth"},
{"name": "Abel", "parent": "Eve"},
{"name": "Awan", "parent": "Eve"},
{"name": "Enoch", "parent": "Awan"},
{"name": "Azura", "parent": "Eve"}
]
const dataSet = d3.stratify()
.id(function(d) { return d.name; })
.parentId(function(d) { return d.parent; })
(data)

樹布局
- d3.tree - 創(chuàng)建一個新的整齊(同深度節(jié)點對齊)的樹布局.
- tree - 將指定的層次數(shù)據(jù)布局為整齊的樹布局.
- tree.size - 設(shè)置布局尺寸.
- tree.nodeSize - 設(shè)置節(jié)點尺寸.
- tree.separation - 設(shè)置兩個相鄰的節(jié)點之間的間距.
//創(chuàng)建樹布局 const tree = d3.tree().size([300, 300]) console.log(tree) //所有的節(jié)點 const nodes = tree(dataSet) console.log(nodes) console.log(nodes.descendants()) // 返回所有節(jié)點
d3.tree 對 hierarchy 進行布局,并為 root 以及它的每一個后代附加兩個屬性:
- node.x - 節(jié)點的 x- 坐標
- node.y - 節(jié)點的 y- 坐標
經(jīng)過布局之后,我們就可以獲取到對應的節(jié)點(node)信息和連線(link)信息:


繪制
繪制節(jié)點
const node = group.selectAll('.node')
.data(nodes.descendants())
.enter()
.append('g')
.attr('class', function(d) {
return 'node' + (d.children ? ' node--internal' : ' node--leaf');
})
.attr('transform', function(d) {
return 'translate(' + d.y + ',' + d.x + ')';
})
node.append('circle')
.attr('r', 20)
.attr('fill', (d, i) => color(i))
繪制節(jié)點文字
node.append('text')
.attr("dy", ".33em")
.attr("font-size","12px")
.attr("text-anchor", "middle") // 文字居中
.attr('fill', '#fff')
.text(d => d.tata.name)
繪制連線
const link = group.selectAll('.link')
.data(nodes.links())
.enter()
.append('path')
.attr('class', 'link')
.attr('d', d3.linkHorizontal() // linkVertical() 垂直 linkHorizontal() 水平
.x(function(d) { return d.y; })
.y(function(d) { return d.x; })
)
.attr('fill', 'none')
.attr('stroke', '#ccc')
需要注意下的是,x和y是反著來的,如果不反著賦值,效果如下圖,還有水平和垂直,大家都可以動手試試效果。

最后
樹形圖的繪制可以總結(jié)為:
- 處理數(shù)據(jù),層次化
- 構(gòu)建樹形布局,確定節(jié)點位置和連線數(shù)據(jù)
- 繪制節(jié)點和連線
以上就是D3.js實現(xiàn)樹形圖的繪制教程詳解的詳細內(nèi)容,更多關(guān)于D3.js樹形圖的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
javascript 中關(guān)于array的常用方法詳解
這篇文章主要介紹了javascript 中關(guān)于array的常用方法的相關(guān)資料,需要的朋友可以參考下2017-05-05
JavaScript實現(xiàn)向右伸出的多級網(wǎng)頁菜單效果
這篇文章主要介紹了JavaScript實現(xiàn)向右伸出的多級網(wǎng)頁菜單效果,通過javascript調(diào)用頁面元素屬性的動態(tài)改變實現(xiàn)向右展開菜單效果,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08
用innerHTML?。Ψ柛敝到o文本框后會變成&的方法
用innerHTML &符號副值給文本框后會變成&的方法...2007-07-07
使用indexOf等在JavaScript的數(shù)組中進行元素查找和替換
使用slice、replace、indexOf等等在JavaScript的數(shù)組中進行元素的查找和替換,感興趣的朋友可以學習下2013-09-09
JavaScript中const關(guān)鍵字的用法及特性
該文章講解了JavaScript中const關(guān)鍵字的用法以及它的一些特性,該關(guān)鍵字用于創(chuàng)建常量,即一旦賦值之后就不能再修改,但是,使用?const創(chuàng)建的對象和數(shù)組卻可以被修改,本文通過講解“賦值”和“變異”之間的重要區(qū)別,詳細解釋了這一現(xiàn)象,需要的朋友可以參考下2023-05-05

