D3.js中的Cluster Dendrogram详解

Posted wan353694124

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D3.js中的Cluster Dendrogram详解相关的知识,希望对你有一定的参考价值。

Cluster Dendrogram

今天聊一个简单点的,叫做Cluster Dendrogram。Dendrogram的意思是“树状图”,咦?为什么不叫tree呢?仔细看官网作者对Dendrogram的解释,恍然大悟。官网解释如下:

A dendrogram is a node-link diagram that places leaf nodes of the tree at the same depth.

秒懂,有木有!意思是说,Dendrogram其实是一种树形结构图的特殊情况,特殊之处在于,Dendrogram将树叶都放置在了同一个深度上,而树形结构没有这个要求。话不多说,来张Dendrogram的图片,如下:

从图中可以清楚地看到,dendrogram的特点,那就是,树的叶子节点全部在同一个深度上。

接下来,详细解释一下,D3.js是怎么实现这颗特别的树的。

index.html详解——源码

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.node circle 
  fill: #999;


.node text 
  font: 10px sans-serif;


.node--internal circle 
  fill: #555;


.node--internal text 
  text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;


.link 
  fill: none;
  stroke: #555;
  stroke-opacity: 0.4;
  stroke-width: 1.5px;


</style>
<svg width="960" height="2000"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>

// 获取svg元素
var svg = d3.select("svg"),
    // 获取svg画布的宽度,此处+svg.attr("width")前面的“+”为了确保获取到的宽度是数字
    width = +svg.attr("width"),
    // 获取svg画布的高度
    height = +svg.attr("height"),
    // 为svg画布添加一个g元素,并将其向右移动40
    g = svg.append("g").attr("transform", "translate(40,0)");

// 定义cluster布局函数tree(),并且设置布局的宽、高
var tree = d3.cluster()
    .size([height, width - 160]);

// d3.stratify()函数用来将数据转换为tree布局所需要的格式,例如为数据计算并添加parent,depth,children等信息
var stratify = d3.stratify()
    //此处定义节点的parentId的计算方式为:从节点id字段中截取最后一个“.”之前的字符串
    .parentId(function(d)  return d.id.substring(0, d.id.lastIndexOf(".")); );

//读取数据文件
d3.csv("flare.csv", function(error, data) 
  if (error) throw error;

  // 转换csv文件读取的数据,使数据用于可以进行tree()布局
  // 返回的root是一个树结构的数据格式,其中的节点具有:children、data、height、id、depth、parent字段,
  // 这些字段都是stratify()函数自动计算并且添加的。非常强大的工具函数啊
  var root = stratify(data)
      .sort(function(a, b)  return (a.height - b.height) || a.id.localeCompare(b.id); );

  // 进行tree()布局,此处会自动布局,为数据添加可视化所需要的位置信息
  // 所以,调用tree(root)之后,root数据中的节点除了children、data、height、id、depth、
  // parent之外,又添加了x,y两个字段信息,表示节点的位置信息
  tree(root);

  // 绘制节点之间的连接线
  var link = g.selectAll(".link")
       // d3中descentdants函数用来返回某个结构中所有的节点数组,例如此处root是树形结构的数据,
       // 那么调用root.descentdants()之后返回的是root结构中所有节点的一个数组;
       // js中的slice()函数从已有的数组中返回指定的元素;
       // 因此 root.descendants().slice(1)函数返回root中除了depth 为0的节点之外的所有节点
       // 组成的数组,这里要去掉depth为0的节点,是因为,根节点只有和其子节点之间的连线,没有哪个
       // 节点指向根节点并和其之间有连线了
      .data(root.descendants().slice(1))
    .enter().append("path") // 添加path元素用来绘制节点连线
      .attr("class", "link")
      // 此处通过连线的子节点和父节点的坐标来计算path元素的属性“d”的值,以此来绘制节点之间的连线
      // 例如对于第一个节点的第一个子元素来说,返回的d属性为:
      // M600,20C100,20 100,492.88969812200304 0,492.88969812200304
      .attr("d", function(d) 
        return "M" + d.y + "," + d.x
            + "C" + (d.parent.y + 100) + "," + d.x
            + " " + (d.parent.y + 100) + "," + d.parent.x
            + " " + d.parent.y + "," + d.parent.x;
      );

  // 绘制节点
  var node = g.selectAll(".node")
      // 绑定节点数据
      .data(root.descendants())
    .enter().append("g")
      .attr("class", function(d)  return "node" + (d.children ? " node--internal" : " node--leaf"); )
      // 根据布局算出的每个节点的坐标位置 来摆放节点
      .attr("transform", function(d)  return "translate(" + d.y + "," + d.x + ")"; )

  // 每个节点用圆来绘制
  node.append("circle")
      .attr("r", 2.5);

  // 为节点绑定文字描述
  node.append("text")
      .attr("dy", 3)
      // 若节点有子节点,那么文字在节点的左边,否则在右边
      .attr("x", function(d)  return d.children ? -8 : 8; )
      // 若节点有子节点,那么文字在基点的左上方;否则,在右上方
      .style("text-anchor", function(d)  return d.children ? "end" : "start"; )
      // 节点文字内容的截取方法
      .text(function(d)  return d.id.substring(d.id.lastIndexOf(".") + 1); );
);

</script>

至此,Cluster Dendrogram图形实现过程解析完毕。下一篇将和Cluster dendrogram非常相似的图,叫Radial Cluster Dendrogram,可以看到,其实就是 Cluster Dendrogram图形的一种变形。

今天是星期六,眼睛酸涩,昨晚没有休息好,希望以后不要再出现这样的情况。

以上是关于D3.js中的Cluster Dendrogram详解的主要内容,如果未能解决你的问题,请参考以下文章

层次聚类python,scipy(dendrogram, linkage,fcluster函数)总算有博文说清楚层次聚类Z矩阵的意义了

d3js树状图tree

D3.js 入门系列 --- 9.4 集群图的制作

R语言ggplot2可视化:为层次聚类树状图dendrogram中的簇进行着色在树状图dendrogram中为不同的层次聚类簇配置不同的色彩

Javascript / D3.js - 绘制大型数据集 - 提高 d3.js 绘制的 svg 图表中的缩放和平移速度

如何暂时禁用 d3.js 中的缩放