用 vue + d3 畫一棵樹
ofollow,noindex">github pages

vue 和 d3 的角色
畫圖可分為兩步:
- 元素座標計算
- 資料繫結
座標計算只需要一些 api,本文使用 d3。
資料繫結既可以藉助 d3,也可以使用 vue。d3 通過操作 dom 實現,有點像 jQuery,d3 針對資料和 dom 的狀態提出了三個概念:Update、Enter、Exit,感興趣的可以看官網。本文使用 vue 做資料繫結
總結:使用 d3 提供的 api 計算元素座標,使用 vue 進行資料繫結
座標計算
一棵樹由節點和連線構成,只需要計算出這兩種元素的座標即可
畫一棵樹常見的有兩種資料結構,一種是巢狀的,一種是扁平的。如下:
// 巢狀的 var treeData = { name: '中國', children: [{ name: '北京', children: [{ name: '海淀' }, { name: '朝陽' }] }, { name: '上海' }] }; // 扁平的 var flattenData = [{ name: '中國', parent: '' }, { name: '北京', parent: '中國' }, { name: '上海', parent: '中國' }, { name: '海淀', parent: '北京' }, { name: '朝陽', parent: '北京' }] 複製程式碼
對於巢狀的資料,使用 d3.hierarchy() 計算座標,對於扁平的,使用 d3.stratify()。得到的結構如下(列舉根節點):
var hierarchyNode = { depth: 0 height: 2 parent: null x: 60 y: 0, data: { name: "中國", children: [] }, children: [] }; 複製程式碼
得到根節點後使用 descendants() 獲取所有節點資訊,links() 獲取所有連線資訊。節點的結構如上述,連線結構如下:
var link = { source: Node, target: Node } 複製程式碼
至此,已獲取到所有元素的座標
資料繫結
使用 svg
樹的節點就是 rect + text,如下:
<g :transform="rootTransform"> <rect :width="nodeWidth" :height="nodeHeight" :fill="nodeFill"></rect> <text :fill="nodeTextColor" text-anchor="middle" dominant-baseline="middle" :y="nodeHeight / 2" :x="nodeWidth / 2">{{node.data.name}}</text> </g> 複製程式碼
連線就是 path,如下:
<g> <path :d="getLinkPath(link)" :stroke="linkStroke" fill="none" :stroke-width="linkStrokeWidth"></path> </g> 複製程式碼