技术

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. 使用xshell连接本地虚拟机中的Linux问题

    xshell 连接虚拟机中Linux报错: Could not connect to '192.168.8.120' (port 22):Connection failed. 原因:虚拟机中Linux ...

  2. js判断数据类型方法

    //一般js中我们判断数据类型 都使用typeof 这里采用 Object.prototype.toString function type (val) { return Object.prototy ...

  3. pic中断特别说明

    在调试产品W660-MODBUS过程中发现,程序工作在偶然情况下会工作异常,经过将近一个礼拜的追踪,发现PIC中断有一下两个怪异特性: 在刚进入中断时就应该清除中断标志,如果在最后返回之前才清除标志, ...

  4. ASM磁盘组中的AU与条带

    一.AU与条带(AU和条带就是一个分配单位,数据会被以一定单位分割,存储在多个磁盘中.分割单位的大小由AU.条带来决定. ASM有两种条带: 1.不可调粗粒度: 相当于ASM没有条带,或者说AU就是条 ...

  5. 《Unix环境高级编程》读书笔记 第13章-守护进程

    1. 引言 守护进程是生存期长的一种进程.它们常常在系统引导装入时启动,仅在系统关闭时才终止.它们没有控制终端,在后台运行. 本章说明守护进程结构.如何编写守护进程程序.守护进程如何报告出错情况. 2 ...

  6. 洛谷P2766 最长不下降子序列问题 网络流_DP

    Code: #include<cstdio> #include<iostream> #include<vector> #include<algorithm&g ...

  7. Pytorch搭建简单神经网络 Task2

    1>建立数据集(并绘制图像) # -*- coding: utf-8 -*- #demo.py import torch import torch.nn.functional as F # 主要 ...

  8. Redis散杂记

    Redis是一款很火的KV模式的内存数据库,与众不同的特点: 1.数据存储在内存 内存的读取速度仅次于CPU的寄存器.各等级缓存,“英雄”自动敏捷属性,特点就是快.高效.因此不需要类似存储磁盘的数据库 ...

  9. mycat读写分离+垂直切分+水平切分+er分片+全局表 测试

    原文http://blog.163.com/bigoceanwu@126/blog/static/172718064201683031639683/ 读写分离:利用最基础的mysql主从复制,事务性的 ...

  10. vue-cli 打包 使用 history模式 的后端配置

    apache的配置 这是windows下的 在httpd-vhosts.conf文件中把目录指向项目index.html文件所在的位置 # Virtual Hosts # <VirtualHos ...