d3 bubble源码分析
技术
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.
- root.eachBefore(radiusLeaf(radius))函数 比较简单,前序遍历,对每个节点的半径进行设置。其中radius是回调函数,参数是node.
- root.eachAfter(packChildren(padding, 0.5)) //后序遍历,在packEnclose函数中设置每个children相对于此节点的位置,并返回此节点的半径大小。这句话完成了半径的设置和节点相对于父节点的相对位置。
- root.eachBefore(translateChild(1)); //由于第二步的位置偏移只是相对于父节点的,这里,递归的把children的偏移加上其父亲节点的偏移。
注意L15行功能是否多余:
本来packEnclose生成的布局是圆形相切布局(圆紧挨着圆,可能不太好看),如何在圆之间加一些空隙,这里作者用了一个小技巧:把计算之前的圆增大一点,经过packEnclose布局后,再把圆的半径给恢复。注:原数据中除叶子节点外都没有半径信息的,如果没有L15的代码的话,冒然增加一个padding,是无效果的,最后的结果是相切布局。L15的结果是把所有节点的半径都设置一下(相切布局)。
其中packChildren中的packEnclose函数是布局的核心代码。此部分代码未使用碰撞的思想(需要迭代,速度就更慢了),直接进行几何的相切布局。
使用方式:

返回结果: 外圆的半径。注意原数据a中每个元素多了一些坐标信息。意思就是,给一组点的大小,经过这个函数后,会得出一些布局信息。
d3 bubble源码分析的更多相关文章
- d3碰撞源码分析
技术 d3. d3.force.d3.geom.quadtree. d3.geom.quadtree 四叉树的应用:图像处理.空间数据索引.2D中的快速碰撞检测.存储稀疏数据等,游戏编程. 上图中的数 ...
- jQuery源码分析系列(36) : Ajax - 类型转化器
什么是类型转化器? jQuery支持不同格式的数据返回形式,比如dataType为 xml, json,jsonp,script, or html 但是浏览器的XMLHttpRequest对象对数据的 ...
- OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波
http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...
- 一个普通的 Zepto 源码分析(三) - event 模块
一个普通的 Zepto 源码分析(三) - event 模块 普通的路人,普通地瞧.分析时使用的是目前最新 1.2.0 版本. Zepto 可以由许多模块组成,默认包含的模块有 zepto 核心模块, ...
- Zepto事件模块源码分析
Zepto事件模块源码分析 一.保存事件数据的handlers 我们知道js原生api中要移除事件,需要传入绑定时的回调函数.而Zepto则可以不传入回调函数,直接移除对应类型的所有事件.原因就在于Z ...
- 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视GCC编译全过程 | 百篇博客分析OpenHarmony源码| v57.01
百篇博客系列篇.本篇为: v57.xx 鸿蒙内核源码分析(编译过程篇) | 简单案例窥视编译全过程 | 51.c.h.o 编译构建相关篇为: v50.xx 鸿蒙内核源码分析(编译环境篇) | 编译鸿蒙 ...
- ABP源码分析一:整体项目结构及目录
ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...
- HashMap与TreeMap源码分析
1. 引言 在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...
- nginx源码分析之网络初始化
nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...
随机推荐
- BOOL的getter方法
在代码中经常会看到这样的属性声明 @property (nonatomic,assign,getter = isRead)BOOL read; 这行代码的意思就是,声明一个BOOL类型的read,但是 ...
- 洛谷P1339 [USACO09OCT]热浪Heat Wave(最短路)
题目描述 The good folks in Texas are having a heatwave this summer. Their Texas Longhorn cows make for g ...
- HTML&CSS——网站注册页面
1.表单标签 所有需要提交到服务器端的表单项必须使用<form></form>括起来! form 标签属性: action,整个表单提交的位置(可以是一个页面,也可以是一个后 ...
- STM8S汇编代码分析
转载:http://blog.csdn.net/u010093140/article/details/50021897使用STVD建立完汇编工程项目之后(具本建立方法可以看我的另一篇博文http:// ...
- RocketMQ学习笔记(6)----RocketMQ的Client的使用 Producer/Consumer
1. 添加依赖 pom.xml如下: <dependency> <groupId>org.apache.rocketmq</groupId> <artifa ...
- Maven缺少jar添加方式
Maven 中央仓库地址: 1. http://www.sonatype.org/nexus/ 2. http://mvnrepository.com/ (本人推荐仓库) 3. http://repo ...
- 快速沃尔什变换(FWT)笔记
开头Orz hy,Orz yrx 部分转载自hy的博客 快速沃尔什变换,可以快速计算两个多项式的位运算卷积(即and,or和xor) 问题模型如下: 给出两个多项式$A(x)$,$B(x)$,求$C( ...
- [原创]Linux 下 redis 链接一次
刚接触 Linux ,在 Linux 下安装 redis 链接redis 出现了以下问题 Could not connect to Redis at 127.0.0.1:6379: Connecti ...
- 学习《PythonWeb开发实战(董伟明)》中文PDF+源代码
python可以用了进行数据分析,也可以进行Web开发,一般会使用django或者flask等进行开发. 国内介绍python web的书有写的不错的,推荐看看<PythonWeb开发实战> ...
- Git日常操作指令
1. 将本地项目上传到码云: ①. 码云上创建一个项目 ②. 本地文件项目内右键git bash进入git控制台 ③. git init 命令 -- 会在本地创建一个.git文件夹 ④. git ...