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

在找了许多参考资料后,我发现大部分关于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()过程——增加元素标签——执行后续操作。

效果图如下:


全部代码如下:

<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>


猜你喜欢

转载自blog.csdn.net/roll_jj/article/details/76019695