可视化工具D3.js教程 入门 (第十三章)—— 树状图
首先我们还是说下 这章要用到的知识点,我在这里只是简单的罗列一下,如需详细了解,请戳这里查看中文官方文档
d3.hierarchy - 从给定的层次结构数据构造一个根节点并为各个节点指定深度等属性.
node.sum - 评估和汇总定量值.
d3.tree - 创建一个新的整齐(同深度节点对齐)的树布局.
tree - 将指定的层次数据布局为整齐的树布局.
tree.size - 设置布局尺寸.
tree.separation - 设置两个相邻的节点之间的间距.
node.descendants - 从当前节点开始返回其后代节点数组.
node.links - 返回当前节点所在子树的所有边.
d3.linkHorizontal 创建一个新的水平的 link
生成器.
接下来咱们直接绘图:
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tree</title> <!--<script src="https://d3js.org/d3.v5.min.js"></script>--> <script src="./d3.min.js"></script> </head> <body> <svg width="1000" height="700"></svg> </body> <script> //数据 var data = { name: "中国", children: [ { name: "浙江", children: [ {name: "杭州", value: 100}, {name: "宁波", value: 100}, {name: "温州", value: 100}, {name: "绍兴", value: 100} ] }, { name: "广西", children: [ { name: "桂林", children: [ {name: "秀峰区", value: 100}, {name: "叠彩区", value: 100}, {name: "象山区", value: 100}, {name: "七星区", value: 100} ] }, {name: "南宁", value: 100}, {name: "柳州", value: 100}, {name: "防城港", value: 100} ] }, { name: "黑龙江", children: [ {name: "哈尔滨", value: 100}, {name: "齐齐哈尔", value: 100}, {name: "牡丹江", value: 100}, {name: "大庆", value: 100} ] }, { name: "新疆", children: [ {name: "乌鲁木齐"}, {name: "克拉玛依"}, {name: "吐鲁番"}, {name: "哈密"} ] } ] }; var margin = 60; var svg = d3.select("svg"); var width = svg.attr("width"); var height = svg.attr("height"); //创建分组 var g = svg.append("g") .attr("transform","translate("+ margin +","+ margin +")"); //创建一个层级布局 var hierarchyData = d3.hierarchy(data) .sum(function (d,i) { return d.value; }); // 返回的节点和每一个后代会被附加如下属性: // node.data - 关联的数据,由 constructor 指定. // node.depth - 当前节点的深度, 根节点为 0. // node.height - 当前节点的高度, 叶节点为 0. // node.parent - 当前节点的父节点, 根节点为 null. // node.children - 当前节点的孩子节点(如果有的话); 叶节点为 undefined. // node.value - 当前节点以及 descendants(后代节点) 的总计值; 可以通过 node.sum 和 node.count 计算. console.log(hierarchyData); //创建一个树状图 var tree = d3.tree() .size([width-400,height-200]) .separation(function (a,b) { return (a.parent==b.parent?1:2)/a.depth;//一种更适合于径向布局的变体,可以按比例缩小半径差距: }); //初始化树状图数据 var treeData = tree(hierarchyData) console.log(treeData);//这里的数据treeData与hierarchyData 相同 //获取边和节点 var nodes = treeData.descendants(); var links = treeData.links(); console.log(nodes); console.log(links); //创建贝塞尔曲线生成器 var link = d3.linkHorizontal() .x(function(d) { return d.y; })//生成的曲线在曲线的终点和起点处的切线是水平方向的 .y(function(d) { return d.x; }); //绘制边 g.append('g') .selectAll('path') .data(links) .enter() .append('path') .attr('d',function (d,i) { var start = {x:d.source.x,y:d.source.y}; var end = {x:d.target.x,y:d.target.y}; return link({source:start,target:end}); }) .attr('stroke','pink') .attr('stroke-width',1) .attr('fill','none'); //创建节点与文字分组 var gs = g.append('g') .selectAll('.g') .data(nodes) .enter() .append('g') .attr('transform',function (d,i) { return 'translate('+ d.y +','+ d.x +')'; }); //绘制文字和节点 gs.append('circle') .attr('r',10) .attr('fill','blue') .attr('stroke-width',1) .attr('stroke','pink'); gs.append('text') .attr('x',function (d,i) { return d.children?-60:10;//有子元素的话 当前节点的文字前移40 }) .attr('y',-5) .attr('dy',10) .text(function (d,i) { return d.data.name; }) </script> </html>
效果: