【 D3.js 进阶系列 — 3.1 】 圆形分区图

时间:2022-01-17 15:29:04

分区图布局的 size 函数很有意思,即可用于制作矩形分区图,也可用于制作圆形分区图。本文就来谈讨一下圆形分区图的制作。

【 D3.js 进阶系列 — 3.1 】 圆形分区图

本文与【进阶 - 第 3.0 章】基本相同,只有布局函数的 size 函数和绘制图形的部分稍有区别。


1. 数据

本文仍然使用【入门 - 第 9.4 章】的数据,内容为中国境内几个城市的所属关系。


2. 布局(数据转换)

var partition = d3.layout.partition()
				.sort(null)
				.size([2 * Math.PI, radius * radius])  
				.value(function(d) { return 1; });

第 3 行:size 函数,第一个值为 2 * PI ,第二个值为圆半径的平方。如果您只需要得到效果,可不比深究为什么这么做,只需记得这么用即可。

注意第3行与【进阶 - 第 3.0 章】的不同。


3. 绘制

先定义一个绘制弧形的函数,这个函数在【入门 - 第 9.1 章】中也用过。

var arc = d3.svg.arc()
			.startAngle(function(d) { return d.x; })
			.endAngle(function(d) { return d.x + d.dx; })
			.innerRadius(function(d) { return Math.sqrt(d.y); })
			.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });

请好好体会上面的代码是什么意思。如果以圆形的形式来转换数据,那么 d.x 和 d.y 分别代表圆弧的绕圆心方向的起始位置由圆心向外方向的其实位置。d.dx 和 d.dy 分别代表各自的宽度。

接下来分别绘制圆弧和文字。

	var arcs = svg.selectAll("g")
				  .data(nodes)
				  .enter().append("g");
	
	arcs.append("path")
		.attr("display", function(d) { return d.depth ? null : "none"; }) // hide inner ring
		.attr("d", arc)
		.style("stroke", "#fff")
		.style("fill", function(d) { return color((d.children ? d : d.parent).name); })
		.on("mouseover",function(d){
			d3.select(this)
				.style("fill","yellow");
		})
		.on("mouseout",function(d){
			d3.select(this)
				.transition()
				.duration(200)
				.style("fill", function(d) { 
					return color((d.children ? d : d.parent).name); 
				});
		});

				  
	arcs.append("text")  
		.style("font-size", "12px")
		.style("font-family", "simsun")
		.attr("text-anchor","middle")
		.attr("transform",function(d,i){
				//第一个元素(最中间的),只平移不旋转
				if( i == 0 )
					return "translate(" + arc.centroid(d) + ")";
				
				//其他的元素,既平移也旋转
				var r = 0;
				if( (d.x+d.dx/2)/Math.PI*180 < 180 )  // 0 - 180 度以内的
					r = 180 * ((d.x + d.dx / 2 - Math.PI / 2) / Math.PI);
				else  // 180 - 360 度以内的
					r = 180 * ((d.x + d.dx / 2 + Math.PI / 2) / Math.PI);
					
				//既平移也旋转
				return  "translate(" + arc.centroid(d) + ")" +
						"rotate(" + r + ")";
		}) 
		.text(function(d) { return d.name; });

绘制方法问题不大,唯一要注意的是文字的旋转角度问题,请好好看看上面的注释问题。


4. 结果


完整代码,请点击下面的链接,再右键点击查看源代码:

http://www.ourd3js.com/demo/J-3.1/circle_partition.html



文档信息