技术

d3、d3.pack、d3.hierarchy

展示

https://bl.ocks.org/xunhanliu/e0688dc2ae9167c4c7fc264c0aedcdd1

关于怎么使用,代码中有关键注释。

 

d3.pack

// https://d3js.org Version 4.8.0. Copyright 2017 Mike Bostock.

层级数据的结构

这是一种典型的树形结构,每个节点包含树的深度和高度,还有“父亲指针”,“儿子指针”。

部分源码

 var index$2 = function() {
var radius = null,
dx = 1,
dy = 1,
padding = constantZero; function pack(root) {
root.x = dx / 2, root.y = dy / 2;
if (radius) {
root.eachBefore(radiusLeaf(radius)) //前序遍历,对每个节点的半径进行设置。
.eachAfter(packChildren(padding, 0.5)) //后序遍历
.eachBefore(translateChild(1));
} else {
root.eachBefore(radiusLeaf(defaultRadius$1))
.eachAfter(packChildren(constantZero, 1))
.eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))//确定每个节点的半径
.eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));//处理每个节点的偏移
}
return root;
} pack.radius = function(x) {
return arguments.length ? (radius = optional(x), pack) : radius;
}; pack.size = function(x) {
return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
}; pack.padding = function(x) {
return arguments.length ? (padding = typeof x === "function" ? x : constant$8(+x), pack) : padding;
}; return pack;
}; function radiusLeaf(radius) {
return function(node) {
if (!node.children) {
node.r = Math.max(0, +radius(node) || 0);
}
};
} function packChildren(padding, k) {
return function(node) {
if (children = node.children) {
var children,
i,
n = children.length,
r = padding(node) * k || 0,
e; if (r) for (i = 0; i < n; ++i) children[i].r += r;
e = packEnclose(children);
if (r) for (i = 0; i < n; ++i) children[i].r -= r;
node.r = e + r;
}
};
} function translateChild(k) {
return function(node) {
var parent = node.parent;
node.r *= k;
if (parent) {
node.x = parent.x + k * node.x;
node.y = parent.y + k * node.y;
}
};
}

主要逻辑在L10-L12.

  1. root.eachBefore(radiusLeaf(radius))函数 比较简单,前序遍历,对每个节点的半径进行设置。其中radius是回调函数,参数是node.
  2. root.eachAfter(packChildren(padding, 0.5)) //后序遍历,在packEnclose函数中设置每个children相对于此节点的位置,并返回此节点的半径大小。这句话完成了半径的设置和节点相对于父节点的相对位置。
  3. root.eachBefore(translateChild(1)); //由于第二步的位置偏移只是相对于父节点的,这里,递归的把children的偏移加上其父亲节点的偏移。

注意L15行功能是否多余:

  本来packEnclose生成的布局是圆形相切布局(圆紧挨着圆,可能不太好看),如何在圆之间加一些空隙,这里作者用了一个小技巧:把计算之前的圆增大一点,经过packEnclose布局后,再把圆的半径给恢复。注:原数据中除叶子节点外都没有半径信息的,如果没有L15的代码的话,冒然增加一个padding,是无效果的,最后的结果是相切布局。L15的结果是把所有节点的半径都设置一下(相切布局)。

其中packChildren中的packEnclose函数是布局的核心代码。此部分代码未使用碰撞的思想(需要迭代,速度就更慢了),直接进行几何的相切布局。

使用方式:

返回结果: 外圆的半径。注意原数据a中每个元素多了一些坐标信息。意思就是,给一组点的大小,经过这个函数后,会得出一些布局信息。

d3 bubble源码分析的更多相关文章

  1. d3碰撞源码分析

    技术 d3. d3.force.d3.geom.quadtree. d3.geom.quadtree 四叉树的应用:图像处理.空间数据索引.2D中的快速碰撞检测.存储稀疏数据等,游戏编程. 上图中的数 ...

  2. jQuery源码分析系列(36) : Ajax - 类型转化器

    什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...

  3. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  4. 一个普通的 Zepto 源码分析(三) - event 模块

    一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...

  5. Zepto事件模块源码分析

    Zepto事件模块源码分析 一.保存事件数据的handlers 我们知道js原生api中要移除事件,需要传入绑定时的回调函数.而Zepto则可以不传入回调函数,直接移除对应类型的所有事件.原因就在于Z ...

  6. 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视GCC编译全过程 | 百篇博客分析OpenHarmony源码| v57.01

    百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...

  7. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  8. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  9. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

随机推荐

  1. shell编程笔记1

    参考文章:1 http://blog.csdn.net/wuwenxiang91322/article/details/9259877   通过chmod改变文件权限 补充知识: 1Linux文件的三 ...

  2. 服务器搭建域控与SQL Server的AlwaysOn环境过程(四)配置AlwaysOn

    0 引言 这一篇才真正开始搭建AlwaysOn,前三篇是为搭建AlwaysOn 做准备的. 步骤 1.3 配置AlwaysOn 请先使用本地用户Administrator登录这两个集群节点并执行下面的 ...

  3. 数组的常用方法 Array;

    数组: 1,arr.join();//返回默认由逗号隔开的一个字符串,传参则返回所传参数隔开的一个字符串; 2,arr.push();//往数组最后添加数据,返回新的数组的length,这个方法将改变 ...

  4. Spring boot配置404、500页面

    Spring boot 配置404页面很简单,如果你访问的url没有找到就会出现spring boot 提示的页面,很明显Spring boot不用配置就可以显示404页面了. 在template下创 ...

  5. CSS 清除浮动 伪类

    参考链接:https://www.cnblogs.com/yingsu/p/7261904.html 不清楚浮动的结果和影响不再描述,清除浮动的代码别处也有很多,每种方法都有十分简洁的代码,我今天学到 ...

  6. JAVA jsp page指令的属性 errorPage 和isErrorPage

    >errorPage指定当前页面出现错误的实际响应页面是什么, 其中“/” 表示的是当前WEB应用的根目录 <% page errorPage="/error.jsp" ...

  7. WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配

    原文:WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配 WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配 网上的 ...

  8. python 退出程序的执行

    使用sys.exit()退出当前程序的执行 import sys if x==0: sys.exit()

  9. yum下载的rpm包离线安装

    #修改yum设置,让rpm包缓存到本地 vi /etc/yum.conf #修改keepcache为1 keepcache=1 #清空yum缓存 yum clean all #安装你要离线安装的rpm ...

  10. 压缩和还原压缩的JS代码

    压缩JS代码:packer – 最好用的 javascript 压缩工具地址: http://dean.edwards.name/packer/ http://kan.willin.org/?page ...