大数据可视化第三天——D3.js初探:饼形图

时间:2022-06-29 03:48:14

在找了许多参考资料后,我发现大部分关于D3.js的讲解不满足我的需求,有些讲的太过冗长,举了很多不需要的点,比如用D3来做排序过滤这种分析阶段就应该做完的事;有些又太简单,很多省略的细节让人看的似是而非。这篇我在网上找了一个饼状图的小例子来帮助自己理解D3一般图形绘制过程,在代码中涉及到某个知识点时再有针对性的学习。

首先来定义四个类别,每个类别中有不同数目的样本。

var dataset = [{
label: "A",
count: 10
},
{
label: "B",
count: 20
},
{
label: "C",
count: 30
},
{
label: "D",
count: 40
}
];
然后定义几个常量,主要是绘制时使用。

var width = 360;
var height = 360;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory20);

其中宽、高是svg的属性,radiu是圆的半径。这里因为width和heigtht是一样的,所以不用Math.min也没关系。color这里构建了一个颜色的标度,d3.scaleOrdinal()函数对

d3.schemeCategory20中的20个颜色构建了一个有序的颜色列表。

var svg = d3.select("#chart")
.append('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');

这里首先用d3提供的select方式选中了以ID"chart"命名的标签(这是我们预先定义的一个<div>标签)。

d3提供了两种select方法,select()和selectAll(),前面一种方法返回匹配这个选择器的第一个元素,后面一种方法返回匹配这个选择器的所有元素,前面加#代表了选择ID,加.代表了选择类。

然后在被选中的<div>标签中,通过.append()方法增加了一个svg区域用来绘制图形,随后的两个.attr()给这个svg区域加入了宽高的属性。这里有一个连续调用函数的方法成为“连缀语法”。在设置完svg区域的属性后,又在svg区域中加入了一个<g>标签,用来划定一个区域,设置了这个区域的transform属性,属性的值为translate(180,180),作用是把<g>标签所划定的区域先向右,再向左分别移动180的位置。

var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) { return d.count; })
.sort(null);
上面这段是定义了d3中的两个图形,一个是圆形arc(),一个是饼图pie(),这两个函数后面所append()的是一些针对这个图形的特殊设置函数,现在不必太过深究,到使用的时候再查文档也可以。这里简单介绍一下,innerRadius()和outerRadius()设置了圆环的内径和外径,假如innerRadius()里面参数不为0,将画出一个圆环;d3.pie().value()则通过接受一组数据来返回饼状图几条线的角度,并且不进行排序

  var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d,i){
return color(d.data.label);
})

上面这段是D3的核心,主要做了下面几件事,按行来讲解:

  1. 选择了SVG中的所有<path>标签,但是我们之前并没有在<svg>区域中设置<path>标签,所以将返回一个空值,但是随后将通过enter()创建这些<path>
  2. 我们将数据通过data()函数绑定到<path>上,这里涉及到D3的数据绑定机制,有datum()和data()两种方法,前者将被选中的所有对象都绑定同一个值,后者则按照被选中对象与data()中参数数据的数量对比进行不同处理:如果两者相等,直接执行后面的语句,也称作update();如果元素不够,比如现在的情况,将一直增加元素到与数据匹配为止,也称作enter(),每次enter增加一个标签然后执行update()的操作,所以在我们的例子中,将执行四次enter(),如果元素多余,则删除元素,也叫exit().
  3. 每次enter()会执行append('path')也就是增加一个<path>标签
  4. 然后增加一个path的属性d,这是SVG作图中一个相当复杂的属性,包含了许多svg的移动划线等操作,其属性值为d3的arc()函数所返回的path data.
  5. 然后每次enter()的过程fill一个不同的颜色,这个function(d,i)可能有些费解,这是由d3.js提供的变量,分别代表了数值和数值的索引。
上面整个过程确实比较复杂,不过.selectAll(ele).data().enter().append(ele).update()是一个d3中操作图表的常见流程,选择元素标签——绑定数据——执行enter()过程——增加元素标签——执行后续操作。

效果图如下:

大数据可视化第三天——D3.js初探:饼形图
全部代码如下:

<div id="chart">
</div>

<script src="d3/d3.js"></script>
<script>
var dataset = [{
label: "A",
count: 10
},
{
label: "B",
count: 20
},
{
label: "C",
count: 30
},
{
label: "D",
count: 40
}
];

var width = 360;
var height = 360;
var radius = Math.min(width, height) / 2;
var color = d3.scaleOrdinal(d3.schemeCategory20);

var svg = d3.select("#chart")
.append('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');
var arc = d3.arc()
.innerRadius(0)
.outerRadius(radius);
var pie = d3.pie()
.value(function(d) { return d.count; })
.sort(null);
var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d',arc)
.attr('fill',function(d,i){
return color(d.data.label);
})

</script>