技术

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. eclipse启动错误:An internal error occurred during: "reload maven project".

    解决方案一: 简单粗暴!直接删除E:\eclipseWorkspace\.metadata目录!然后再单个导入eclipseWorkspace中的项目. 解决方案二: 打开这个配置文件:E:\ecli ...

  2. 【DNN 系列 创建WEB模块 项目】

    现在DNN已经更新到8.0.3 然而使用7.0 的项目模块 会报错, 就是填写网站的时候 会再网站的项目当中添加文件夹这样会破坏网站 所以来自己创建自己的模板项目 首选创建空的WEB 项目网站 创建完 ...

  3. Android PullToRefreshListView设置各个item之间的间距

    要设置第三方的上拉下载listView的item之间的间距,可以在xml布局文件中的listView节点中设置xml的属性即可: android:divider="#00000000&quo ...

  4. (转载)Android UI设计之AlertDialog弹窗控件

    Android UI设计之AlertDialog弹窗控件 作者:qq_27630169 字体:[增加 减小] 类型:转载 时间:2016-08-18我要评论 这篇文章主要为大家详细介绍了Android ...

  5. Devexpress控件使用二:barManager

    1.拖放控件 2.两种按钮显示形式 1)上面是大图标,下面是说明 a.Add → Largebutton 注:勾选 Show DesignTime enancements 才会出现Add b.添加图片 ...

  6. Avalon.js 实现列表

    <table border="0" cellpadding="0" cellspacing="0" class="tab1& ...

  7. 记我安装Caffe的血泪史(2)

    不知不觉居然花了一个星期来安装Caffe...真是醉了. 接上一篇blog,本以为编译完cuda,opencv之后问题就差不多了(其实本来是没有什么问题的,但硬是被我搞了一堆事情出来....) 出于对 ...

  8. Python读取Matlab的.mat文件

    参考网站: https://blog.csdn.net/rumswell/article/details/8545087 数据: R 22*22 double 部分截图如下: 使用sicpy.io即可 ...

  9. 路飞学城Python-Day15(模块二思维导图)

  10. (noip模拟二十一)【BZOJ2500】幸福的道路-树形DP+单调队列

    Description 小T与小L终于决定走在一起,他们不想浪费在一起的每一分每一秒,所以他们决定每天早上一同晨练来享受在一起的时光. 他们画出了晨练路线的草图,眼尖的小T发现可以用树来描绘这个草图. ...