D3 4.0 Hierarchy 层布局浅析

来源:互联网 发布:tomcat连接数据库超时 编辑:程序博客网 时间:2024/06/05 06:02

D3 4.0 Hierarchy 层布局浅析

层布局中的基本数据结构基本就是树结构,所以其提供的一切属性和方法都是对树的操作,包括但不限于:

  • 树结点值获取—data

  • 树的高度—height

  • 节点的层次—depth

  • 父节点—parent

  • 节点的遍历—each()

  • 节点子孙—descendats()

  • 节点祖先—ancestors()

  • 树的叶子—leaves()

以上这些为层的基本方法,层扩展而来的布局也是根据这些基本属性、方法实现的;了解这些方法的原理及实现有助于了解层布局的扩展布局。本文就是对层布局内部进行分析。


Hierarchy 的数据结构

Node{    children:[n],    data:{},    depth:0,\\节点层次从0开始    height:2,\\树的高度    parent:Node}

Hierarchy数据结构的生成

Hierarchy有两种生成方式一个为普通数组使用stratify方式生成今后会介绍,还有一个为Hierarchy构造方法,传入参数为json的树形结构。先贴源码

export default function hierarchy(data,children){  var root = new Node(data),nodes=[root]  ...  while (node = nodes.pop()) {    if ((childs = children(node.data)) && (n = childs.length)) {      node.children = new Array(n);      for (i = n - 1; i >= 0; --i) {        nodes.push(child = node.children[i] = new Node(childs[i]));        child.parent = node;        child.depth = node.depth + 1;      }    }  }  ...}
  • 创建Node对象,初始化data

  • 根据children方法找到子节点数组,遍历数组创建Node放入父Node的children属性中,添加节点的层数、值等属性

function defaultChildren(d) {  return d.children;}

children 属性是一个回调函数默认指定children属性,可以自定义。


遍历

遍历是树的核心也是层布局的核心,层的所有方法都是通过遍历提供的。层次提供了3种遍历方式

  • 层次遍历

  • 前序遍历

  • 后序遍历

层次遍历—node.each()

先访问离根节点最近的节点,通过队列实现

export default function(callback) {  var node = this, current, next = [node], children, i, n;  do {    current = next.reverse(), next = [];    while (node = current.pop()) {      callback(node), children = node.children;      if (children) for (i = 0, n = children.length; i < n; ++i) {        next.push(children[i]);      }    }  } while (next.length);  return this;}

前序遍历—node.eachBefore()

先访问根,然后访问孩子的遍历方式

后续遍历—node.eachAfter()

先访问孩子,然后访问根的遍历方式

源码可以自己查看,了解其遍历方式对后续方法理解很有帮助。


其他方法

排序—sort(fn(a,b))

export default function(compare) {  return this.eachBefore(function(node) {    if (node.children) {      node.children.sort(compare);    }  });}

前序遍历每个节点,对每个节点的子节点数组进行排序。

求和—sum(fn(node.data))

export default function((value)) {  return this.eachAfter(function(node) {    var sum = +value(node.data) || 0,        children = node.children,        i = children && children.length;    while (--i >= 0) sum += children[i].value;    node.value = sum;  });}

后序遍历,对每个子节点进行自定义计算,赋值到value属性上。

求相邻的link 翻译将就吧。。。

export default function() {  var root = this, links = [];  root.each(function(node) {    if (node !== root) { // Don’t include the root’s parent, if any.      links.push({source: node.parent, target: node});    }  });  return links;}

层次遍历,将每个节点和其父节点构成一个对象,放到数组中。

求叶子—leaves()

不贴代码了,思路就是遍历节点判定没有子节点的放入数组中。

求俩节点路径—path()

判定其公共节点然后依次将起始节点到公共节点以及从公共节点到目的节点放入数组,注意数组的顺序。

节点的子孙—descendants()

export default function() {  var nodes = [];  this.each(function(node) {    nodes.push(node);  });  return nodes;}

注意最后返回的数组的顺序。

节点祖先

export default function() {  var node = this, nodes = [node];  while (node = node.parent) {    nodes.push(node);  }  return nodes;}

注意数组顺序。


结束

以上就是所有层布局涉及的方法。希望对君有所帮助。以后会尽量持续更新有关d3的内容。

1 0