🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 树图 ## 需求 主要是展示分层结构形数据,例如展示中国部分城市: 上海,西安,宝鸡,北京,杭州,温州 ## 分析 首先建议阅读[树图-中文](https://github.com/xswei/d3-hierarchy) 首先分析城市的层级,比如北京属于直辖,西安属于陕西。 ``` javascript var data = { "name": "中国", "children": [ {"name": "北京"}, {"name": "陕西", "children": [ {"name": "宝鸡"}, {"name": "西安"} ] }, {"name": "上海"}, {"name": "浙江", "children": [ {"name": "杭州"}, {"name": "温州"} ] }, ] } ``` 为此我们可以得到这样的数据结构。 我们简要回顾饼图制作,饼图绘制需要使用d3.pie将数据转化为利于绘制,之后使用d3.arc绘制。 层次类图的绘制思路是相似的: 1. 将数据进行层次化,简单来说就是为每个节点加入更多属性: * node .data - 为构造函数指定的关联数据。 * node .depth - 根节点为零,每个后代生成增加1。 * node .height - 叶节点为零,与内部节点的任何后代叶的最大距离。 * node .parent - 父节点,或根节点为null。 * node .children - 子节点数组(如果有); 未定义叶节点。 * node .value - 节点及其后代的总和值; 可选的,见节点的.sum和节点 .Count之间。 2. 将层次化好的数据,通过如d3.tree等进行布局。简单来说:就是通过设定当前绘制区域的大小,然后计算各节点的位置,大小等用于绘制的数据。 3. 通过绘制节点连线即可。 ## 绘制 ``` javascript //创建svg var svg = d3.select('#root') .append('svg') .attr('width', 600) .attr('height', 600) .style("background-color","rgb(142, 137, 137)"); var margin=[100,100,100,100] var color = d3.scaleOrdinal(d3.schemeCategory20) //模拟数据: var data = { "name": "中国", "children": [ {"name": "北京"}, {"name": "陕西", "children": [ {"name": "宝鸡"}, {"name": "西安"} ] }, {"name": "上海"}, {"name": "浙江", "children": [ {"name": "杭州"}, {"name": "温州"} ] }, ] } //将数据进行层次化 var dataSet = d3.hierarchy(data) console.log(dataSet) //创建树布局 var tree = d3.tree() .size([400,400]) //所有的节点 var node =tree(dataSet) console.log(node) //拿到所有节点 var nodes = node.descendants() //可以拿到所有的连线点 var links = node.links() //此处注意得到所有位置点是从上到下的 //而我们经常使用的是从左到右 //所以我们应该在绘制时颠倒x和y值 //分组 var nodeG = svg.append('g') .attr('transform','translate(100,100)') var linksG = svg.append('g') .attr('transform','translate(100,100)') // 绘制节点 nodeG.selectAll('circle').data(nodes) .enter() .append('circle') .attr('cx',function(d){return d.x}) .attr('cy',function(d){return d.y}) .attr('r',20) .attr('fill',function(d,i){color(i)}) //绘制连线 var line = d3.linkHorizontal() .x(function (d) {console.log(d); return d.x }) .y(function (d) { return d.y }) linksG.selectAll('path') .data(links) .enter() .append('path') .attr('d',line) .attr('fill','none') .attr('stroke','#eee') ``` 细节提示: 1. 在设置图表垂直向下,或者水平向右的控制上没有相关函数处理,但我们可以在绘制时调换xy,在调换xy处,需要同时调换d3.tree设置的宽高。 2. 绘制线条时应考虑: * d3.linkVertical - 创建一个新的垂直 link 生成器. * d3.linkHorizontal - 创建一个新的水平的 link 生成器. 3. 绘制连线是注意path应该将fill属性设置为none。并设置stroke值。 4. 如图实例tree0,注意层级关系,应该将link放置在node前绘制。 ## 实例 [tree0](https://doter1995.github.io/d3-start-course/tree/tree-0.html) ![](https://box.kancloud.cn/b6aea40c1ebbd998c6e2b598f6083448_449x532.png) [tree1](https://doter1995.github.io/d3-start-course/tree/tree-1.html) ![](https://box.kancloud.cn/3147351ee63c4de44ff6978f66b8bde9_518x409.png)