一、饼状图

  在布局的应用中,最简单的就是饼状图。

1、数据

  有如下数据,需要可视化:

var dataset = [  ,  ,  ,  ,  ];

  这样的值是不能直接绘图的。例如绘制饼状图的一个部分,需要知道一段弧的起始角度和终止角度,这些值都不存在于数组 dataset 中。因此,需要用到布局,布局的作用就是:计算出适合于作图的数据。

2、布局(数据转换)

  定义一个布局:

var pie = d3.layout.pie();

  返回值赋给变量 pie,此时 pie 可以当做函数使用

var piedata = pie(dataset);

  将数组 dataset 作为 pie() 的参数,返回值给 piedata。如此一来:piedata 就是转换后的数据。简单吧,非常轻松就得到了。在控制台输出 piedata ,让我们来看看数据转换成什么了。

  如上图所示,5 个整数被转换成了 5 个对象(Object) ,每个对象都有变量起始角度(startAngle)和终止角度(endAngle),还有原数据(属性名称为 data)。这些都是绘图需要的数据。

  千万记住:布局不是要直接绘图,而是为了得到绘图所需的数据。

3、绘制图形

  为了根据转换后的数据 piedata 来作图,还需要一样工具:生成器

  SVG 有一个元素,叫做路径 <path>,是 SVG 中功能最强的元素,它可以表示其它任意的图形。顾名思义,路径元素就是通过定义一个段“路径”,来绘制出各种图形。但是,路径是很难计算的,通过布局转换后的数据 piedata 仍然很难手动计算得到路径值。为我们完成这项任务的,就是生成器。

  这里要用到的叫做弧生成器,能够生成弧的路径,因为饼图的每一部分都是一段弧。

var outerRadius = ; //外半径
var innerRadius = ; //内半径,为0则中间没有空白 var arc = d3.svg.arc() //弧生成器
.innerRadius(innerRadius) //设置内半径
.outerRadius(outerRadius); //设置外半径

  弧生成器返回的结果赋值给 arc。此时,arc 可以当做一个函数使用,把 piedata 作为参数传入,即可得到路径值。

  接下来,可以在 SVG 中添加图形元素了。先在 <svg> 里添加足够数量(5个)个分组元素(g),每一个分组用于存放一段弧的相关元素。

var arcs = svg.selectAll("g")
.data(piedata)
.enter()
.append("g")
.attr("transform","translate("+ (width/) +","+ (width/) +")");

  接下来对每个 <g> 元素,添加 <path>

arcs.append("path")
.attr("fill",function(d,i){
return color(i);
})
.attr("d",function(d){
return arc(d); //调用弧生成器,得到路径值
});

  因为 arcs 是同时选择了 5 个 <g> 元素的选择集,所以调用 append(“path”) 后,每个 <g> 中都有 <path> 。路径值的属性名称是 d,调用弧生成器后返回的值赋值给它。要注意,arc(d) 的参数 d 是被绑定的数据。

  另外,color 是一个颜色比例尺,它能根据传入的索引号获取相应的颜色值,定义如下。

var color = d3.scale.category10();   //有十种颜色的颜色比例尺

  然后在每一个弧线中心添加文本。

arcs.append("text")
.attr("transform",function(d){
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor","middle")
.text(function(d){
return d.data;
});

  arc.centroid(d) 能算出弧线的中心

  要注意,text() 里返回的是 d.data ,而不是 d 。因为被绑定的数据是对象,里面有 d.startAngle、d.endAngle、d.data 等,其中 d.data 才是转换前的整数的值

二、力导向图

  力导向图中每一个节点都受到力的作用而运动,这种是一种非常绚丽的图表。

  力导向图(Force-Directed Graph),是绘图的一种算法。在二维或三维空间里配置节点,节点之间用线连接,称为连线。各连线的长度几乎相等,且尽可能不相交。节点和连线都被施加了力的作用,力是根据节点和连线的相对位置计算的。根据力的作用,来计算节点和连线的运动轨迹,并不断降低它们的能量,最终达到一种能量很低的安定状态。

  力导向图能表示节点之间的多对多的关系。

1、数据

  初始数据如下:

var nodes = [ { name: "桂林" }, { name: "广州" },
{ name: "厦门" }, { name: "杭州" },
{ name: "上海" }, { name: "青岛" },
{ name: "天津" } ]; var edges = [ { source : , target: } , { source : , target: } ,
{ source : , target: } , { source : , target: } ,
{ source : , target: } , { source : , target: } ];

  节点(nodes)和连线(edges)的数组,节点是一些城市名,连线的两端是节点的序号(序号从 0 开始)。

  这些数据是不能作图的,因为不知道节点和连线的坐标。这句话一说出来,就请想到布局。力导向图用到的布局是:d3.layout.force()

2、布局(数据转换)

  定义一个力导向图的布局如下

var force = d3.layout.force()
.nodes(nodes) //指定节点数组
.links(edges) //指定连线数组
.size([width,height]) //指定作用域范围
.linkDistance() //指定连线长度
.charge([-]); //相互之间的作用力

  然后,使力学作用生效:

force.start();    //开始作用

  如此,数组 nodes 和 edges 的数据都发生了变化。在控制台输出一下,看看发生了什么变化。

  节点转换前后如下图

  转换后,节点对象里多了一些变量。其意义如下:

  • index:节点的索引号
  • px, py:节点上一个时刻的坐标
  • x, y:节点的当前坐标
  • weight:节点的权重

  再来看看连线的变化:

  可以看到,连线的两个节点序号,分别变成了对应的节点对象。(一个代表源,一个代表目标

3、绘制

  有了转换后的数据,就可以作图了。分别绘制三种图形元素:

  • line,线段,表示连线。
  • circle,圆,表示节点。
  • text,文字,描述节点。

  代码如下:

//添加连线
var svg_edges = svg.selectAll("line")
.data(edges)
.enter()
.append("line")
.style("stroke","#ccc")
.style("stroke-width",); var color = d3.scale.category20();//颜色比例尺 //添加节点
var svg_nodes = svg.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr(
"r",20)
.style("fill",function(d,i){
return color(i);
})
.call(force.drag); //使得节点能够拖动 //添加描述节点的文字
var svg_texts = svg.selectAll("text")
.data(nodes)
.enter()
.append("text")
.style("fill", "black")
.attr("dx", )
.attr("dy", )
.text(function(d){
return d.name;
});

  调用 call( force.drag ) 后节点可被拖动。force.drag() 是一个函数,将其作为 call() 的参数,相当于将当前选择的元素传到 force.drag() 函数中

  最后,还有一段最重要的代码。由于力导向图是不断运动的,每一时刻都在发生更新,因此,必须不断更新节点和连线的位置

  力导向图布局 force 有一个事件 tick,每进行到一个时刻,都要调用它,更新的内容就写在它的监听器里就好

force.on("tick", function(){ //对于每一个时间间隔
//更新连线坐标
svg_edges.attr("x1",function(d){ return d.source.x; })
.attr("y1",function(d){ return d.source.y; })
.attr("x2",function(d){ return d.target.x; })
.attr("y2",function(d){ return d.target.y; }); //更新节点坐标
svg_nodes.attr("cx",function(d){ return d.x; })
.attr("cy",function(d){ return d.y; }); //更新文字坐标
svg_texts.attr("x", function(d){ return d.x; })
.attr("y", function(d){ return d.y; });
});

  tick 的英文意思是钟表发出的嘀嗒嘀嗒声,每次触发时,都会调用后面的无名函数 function。

D3.js系列——布局:饼状图和力导向图的更多相关文章

  1. D3.js系列——布局:弦图和集群图/树状图

    一.弦图 1.弦图是什么 弦图(Chord),主要用于表示两个节点之间的联系的图表.两点之间的连线,表示谁和谁具有联系. 2.数据 初始数据为: var city_name = [ "北京& ...

  2. D3.js系列——布局:打包图和地图

    一.打包图 打包图( Pack ),用于表示包含与被包含的关系,也可表示各对象的权重,通常用一圆套一圆来表示前者,用圆的大小来表示后者. 1.布局(数据转换) var pack = d3.layout ...

  3. D3.js系列——交互式操作和布局

    一.图表交互操作 与图表的交互,指在图形元素上设置一个或多个监听器,当事件发生时,做出相应的反应. 交互,指的是用户输入了某种指令,程序接受到指令之后必须做出某种响应.对可视化图表来说,交互能使图表更 ...

  4. D3.js力导向图中新增节点及新增关系连线示例

    大家在使用D3.js中的力导向图时,基本都会遇到动态增加节点及连线的需求,这里记录一下我的实现方式. 话不多说,先放代码: <!DOCTYPE html> <html lang=&q ...

  5. D3.js力导向图(适用于其他类型图)中后添加元素遮盖已有元素的问题解决

    上一篇说了在D3.js中动态增加节点及连线的一种实现方式,但是有后添加元素遮盖原节点的现象,这一篇说一下出现这个现象的解决办法. 在D3.js中后添加的元素是会遮盖先添加的元素的,同时还有一个设定:后 ...

  6. D3.js 力导向图的制作

    力导向图中每一个节点都受到力的作用而运动,这种是一种非常绚丽的图表. 力导向图(Force-Directed Graph),是绘图的一种算法.在二维或三维空间里配置节点,节点之间用线连接,称为连线. ...

  7. D3.js 力导向图的显示优化

    D3.js 作为一个前端,说到可视化除了听过 D3.js 的大名,常见的可视化库还有 ECharts.Chart.js,这两个库功能也很强大,但是有一个共同特点是封装层次高,留给开发者可设计和控制的部 ...

  8. Vue和d3.js(v4)力导向图force结合使用,v3版本升级v4【一】

    前段时间因为参与项目涉密,所以一直没有更新博客,有些博友给我私信或者留言要部分博文的源码,因为我的电脑更换,demo的源码没有备份 所以无法提供.大家可针对具体问题问我,有空我定会回复的.另外转发文章 ...

  9. D3.js 力导向图

    花了大半天看了一个八十几行的代码..心累 力导向图是之前就有画过很多次的东西,但是这次的代码看上去很陌生,然后发现是D3更新了4.0.... 先贴代码 var svg = d3.select(&quo ...

随机推荐

  1. [Leetcode Week4]Course Schedule II

    Course Schedule II题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/course-schedule-ii/description/ De ...

  2. 最近研究xcodebuild批量打包的一些心得

    http://blog.csdn.net/tlb203/article/details/8131707 转自Rainbird的个人博客 以前的时候只知道做安卓开发的兄弟挺辛苦的,不但开发的时候要适配一 ...

  3. git web 服务器的搭建【转】

    转自:http://blog.csdn.net/transformer_han/article/details/6450200 目录(?)[-] git服务器搭建过程 需求 硬件需求一台Ubuntu或 ...

  4. bp神经网络模型推导与c语言实现(转载)

    转载出处:http://www.cnblogs.com/jzhlin/archive/2012/07/28/bp.html BP 神经网络中的 BP 为 Back  Propagation 的简写,最 ...

  5. mvvm command的使用案例

    主界面如下: 前台代码: <Window x:Class="WpfApp1.MainWindow"        xmlns="http://schemas.mic ...

  6. Jxl、JxCell图表导出功能的实现

    最近接触过许多报表导出功能,也用过多种工具进行导出功能的实现,但对于图表的导出一直没有仔细的去展开研究和探讨,直到最近略微整理了下这方面的需求和技术攻克. 首先导出excel功能的实现主要有JXL.J ...

  7. 【SQL】事务

    1.事务的开始结束: START TRANSACTION :标记事务开始 COMMIT :标记事务成功结束 ROLLBACK :标记事务夭折 2.设定事务只读.读写性质: SET TRANSACTIO ...

  8. 《Java编程思想》笔记 第二章 一切都是对象

    1.对象存储位置 对象的引用存在栈中,对象存在堆中.new 出来的对象都在堆中存储.栈的存取速度较快. 所有局部变量都放在栈内存里,不管是基本类型变量还是引用类型变量,都存储在各自的方法栈中: 但是引 ...

  9. Python 进阶 之 @property

    @property是一个装饰器,由Python原生库所支持,无需import @property 的作用是将函数变成属性,一般作用于类内的成员函数. 先贴个代码来描述一下@poperty存在的意义: ...

  10. codeforces 671C

    题意定义f(l,r)为去掉[l,r]部分后剩下的数任意两个数的最大公约数的最大值 现在求f(l,r)的和 由于每个数ai最大只有200000,因此我们穷举因子x,记录以其为因子的a[i]的i值并按i升 ...