【D3.js数据可视化系列教程】(二十七)--径向树

来源:互联网 发布:独立域名网站 编辑:程序博客网 时间:2024/05/16 17:36

径向树也就是环状的树

  1. 效果

  2. 技术分解

  2.1 定义树布局

指定布局大小和节点邻距

【司机提示】 树布局就是一个函数,用来对原始的层次状数据进行加工处理,而这个加工主要就是生成节点的坐标深度等数据。由这些数据结合对角线,圆等就可以绘制径向树了。

var tree = d3.layout.tree()    .size([360, 360])// 角度360度,半径360px    .separation(function(a, b) {     return (a.parent == b.parent ? 1 : 2) / a.depth; });// 父节点相同的节点邻距相等,不同的稍宽一点用来区分开    });

  2.2 定义径向对角线生成器

【司机提示】 径向对角线生成器也是一个函数,主要用来生成用以绘制连线数据。

var diagonal = d3.svg.diagonal.radial()    .projection(function(d) {     return [d.y, d.x / 180 * Math.PI];// 半径d.y和角度d.x / 180 * Math.PI(转换成弧度制)    });

  2.3 加载json数据

d3.json("tree.json", function(error, root) {  var nodes = tree.nodes(root),//返回值是一个数组,它代表​​所有节点计算的位置。每个节点上填充一些属性:      links = tree.links(nodes);//返回节点数组的连接数组  //...});

  2.4 为连线添加路径数据

var link = svg.selectAll(".link")  .data(links).enter().append("path")  .attr("class", "link")  .attr("d", diagonal);

  2.5 节点转换位置

transform是变换,本例中用于平移

var node = svg.selectAll(".node")  .data(nodes)  .enter().append("g")  .attr("class", "node")  .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })

  2.6 节点添加圆圈

node.append("circle")  .attr("r", 4.5);

  2.7 节点添加文字

node.append("text")  .attr("dy", ".31em")  .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })//小于180度的文字放在前面,否则放在后面  .attr("transform", function(d) { return d.x < 180 ? "translate(8)" : "rotate(180)translate(-8)"; })  .text(function(d) { return d.name; });

  3. JSON文件

很简单就是{}表示对象。[]表示数组。可以无限嵌套,可以无限重复

{ "name": "AAA", "children":  [    { "name": "BBB",     "children":       [        {"name": "CCC",         "children":         [            {"name": "DDD",              "children":                     [                            {"name": "EEE", "size": 73},                          {"name": "EEE", "size": 39},                          {"name": "EEE", "size": 67},                          {"name": "EEE", "size": 73},                          {"name": "EEE", "size": 39},                          {"name": "EEE", "size": 67},                          {"name": "EEE", "size": 73},                          {"name": "EEE", "size": 39},                          {"name": "EEE", "size": 67},                          {"name": "EEE", "size": 73},                          {"name": "EEE", "size": 39},                          {"name": "EEE", "size": 67},                          {"name": "EEE", "size": 73},                          {"name": "EEE", "size": 39},                          {"name": "EEE", "size": 67},                          {"name": "EEE", "size": 73}                     ]},                  {"name": "DDD", "size": 73},                  {"name": "DDD", "size": 39},                  {"name": "DDD", "size": 67},                  {"name": "DDD", "size": 73},                  {"name": "DDD", "size": 39},                  {"name": "DDD", "size": 67},                  {"name": "DDD", "size": 73},                  {"name": "DDD", "size": 39},                  {"name": "DDD", "size": 67},                  {"name": "DDD", "size": 73},                  {"name": "DDD", "size": 39},                  {"name": "DDD", "size": 67},                  {"name": "DDD", "size": 73},                  {"name": "DDD", "size": 39},                  {"name": "DDD", "size": 67},                  {"name": "DDD", "size": 73}        ]},          {"name": "CCC", "size": 67},          {"name": "CCC", "size": 73},          {"name": "CCC", "size": 39},          {"name": "CCC", "size": 67},          {"name": "CCC", "size": 73},          {"name": "CCC", "size": 39},          {"name": "CCC", "size": 67},          {"name": "CCC", "size": 73},          {"name": "CCC", "size": 39},          {"name": "CCC", "size": 67},          {"name": "CCC", "size": 73},          {"name": "CCC", "size": 39},          {"name": "CCC", "size": 67},          {"name": "CCC", "size": 73},          {"name": "CCC", "size": 39},          {"name": "CCC", "size": 67},          {"name": "CCC", "size": 73}    ]      },      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73},      {"name": "BBB", "size": 39},      {"name": "BBB", "size": 67},      {"name": "BBB", "size": 73} ]}

  4. 完整代码

<!DOCTYPE html><html>  <head>        <meta charset="utf-8">        <title>testD3-24-Reingold–Tilford Tree.html</title>        <script type="text/javascript" src="d3.js"></script>    <style>.node circle {  fill:yellow ;  stroke: red;  stroke-width: 1.5px;}.node {  font: 10px sans-serif ;}.link {  fill: green;  stroke: #ccc;  stroke-width: 1.5px;}</style></head><body><script type="text/javascript">var diameter = 960;//直径//(1)树指定径向布局大小和节点邻距var tree = d3.layout.tree()    .size([360,  360])// 角度360度,半径360px    .separation(function(a, b) {     return (a.parent == b.parent ? 1 : 2) / a.depth;// 父节点相同的节点邻距相等,不同的稍宽一点用来区分开    });var diagonal = d3.svg.diagonal.radial()//(2)指定为径向布局    .projection(function(d) {     return [d.y, d.x / 180 * Math.PI];// 半径d.y和角度d.x / 180 * Math.PI(转换成弧度制)     });var svg = d3.select("body").append("svg")    .attr("width", diameter)    .attr("height", diameter - 150)  .append("g")    .attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");//(3)加载jsond3.json("flare.json", function(error, root) {  var nodes = tree.nodes(root),//返回值是一个数组,每个节点上填充一些计算后的属性,例如深度,坐标等。      links = tree.links(nodes);//返回节点数组的连接数组  //(4)为链接添加路径  var link = svg.selectAll(".link")      .data(links)    .enter().append("path")      .attr("class", "link")      .attr("d", diagonal);  //(5)节点转换位置  var node = svg.selectAll(".node")      .data(nodes)     .enter().append("g")      .attr("class", "node")      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })  //(6)节点添加圆圈  node.append("circle")      .attr("r", 4.5);  //(7)节点添加文字  node.append("text")      .attr("dy", ".31em")      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })//小于180度的文字放在前面,否则放在后面      .attr("transform", function(d) { return d.x < 180 ? "translate(8)" : "rotate(180)translate(-8)"; })      .text(function(d) { return d.name; });});