【 D3.js 入门系列 --- 10.2 】 可拖动的地图

本人的个人博客为:www.ourd3js.com

csdn博客为:blog.csdn.net/lzhlzz

转载请注明出处,谢谢。



本节是结合9.2节
10节 的内容制作的一个可力学导向的中国地图,用户可以拖动中国的各个省份。

数据用的是 10.1节 中简化的中国地图文件: china_simplify.json

1. 定义各函数

	var projection = d3.geo.mercator()
						.center([107, 31])
						.scale(850)
    					.translate([width/2, height/2]);

	var path = d3.geo.path()
					.projection(projection);

	var force = d3.layout.force().size([width, height]);

	var color = d3.scale.category20();

projection 函数是用于将三维地图的坐标投影到二维所用的投影函数。具体可见: 10节

path 函数用于绘制地图路径,里面要传入投影函数 projection 。具体可见: 10节

force 是定义力学图的 layout 。具体可见: 9.2节

color 是颜色函数。

2. 读取数据

d3.json("china_simplify.json", function(error, root) {

		if (error)
			return console.error(error);
		console.log(root.features);
}

和前几节一样,用 d3.json() 读取文件,后面两句是用于检测错误,以及输出错误信息。

3. 转换数据

		var nodes = [];
		var links = [];

		root.features.forEach(function(d, i) {
			var centroid = path.centroid(d);
			centroid.x = centroid[0];
			centroid.y = centroid[1];
			centroid.feature = d;
			nodes.push(centroid);
		});

		var triangles = d3.geom.voronoi().triangles(nodes);

		triangles.forEach(function(d,i){
			links.push( edge( d[0] , d[1] ) );
			links.push( edge( d[1] , d[2] ) );
			links.push( edge( d[2] , d[0] ) );
		});

读取后的文件信息都存在变量 root 中,上面的代码是将 root 中的数据分别转换为力学图所需要的点和线,存在变量 nodes 和 links 中。

第1-2行: 定义变量 nodes 和 links

第4-10行: 对于 root.features 中存有每一个省的数据, root.features.forEach() 即对每一个省的数据,执行后面的无名函数,函数里面是计算出各省的中点,保存在 centroid.x 和 centroid.y 中,再把其他信息赋值给 centroid.feature,最后插入到 nodes 中。

第12行: 对 nodes 中的顶点进行三角剖分,即用三角形来连接各顶点,结果保存在 triangles 中。

第14-18行: 将三角形的各边存到 links 变量中。其中的 edge 函数的实现为:

	function edge(a, b) {
		var dx = a[0] - b[0], dy = a[1] - b[1];
		return {
			source: a,
			target: b,
			distance: Math.sqrt(dx * dx + dy * dy)
		};
	}

4. 绘制地图

		force.gravity(0)
			.charge(0)
			.nodes(nodes)
			.links(links)
			.linkDistance(function(d){ return d.distance; })
			.start();

		var node = svg.selectAll("g")
						.data(nodes)
						.enter().append("g")
						.attr("transform", function(d) { return "translate(" + -d.x + "," + -d.y + ")"; })
      					.call(force.drag)
				        .append("path")
				        .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
				        .attr("stroke","#000")
				        .attr("stroke-width",1)
				        .attr("fill", function(d,i){
				            return color(i);
				        })
				        .attr("d", function(d){
				        	return path(d.feature);
				        } );

		var link = svg.selectAll("line")
						.data(links)
						.enter()
						.append("line")
						.attr("class","link")
						.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; } );

第1-6行: 设定 force 的各参数进行设定。

第8-22行: 绘制各顶点,即中国各省。其中要注意,第11行和第14行,是完全相反的两个平移函数,不错,这么做就是为了移过去,再移回来,即初始时显示的是各省拼成的完整的地图且显示在最初设定的位置,因为拖拽的过程中变化的量是 d.x 和 d.y ,所以要这么做。这里有点难理解,请好好体会一下,如有疑问,请在下面留言。另外,第12行是调用 force.drag 函数。

第24-32行: 绘制连接各省的线条。

5. 力学图的结合

		 force.on("tick", function() {
			    link.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; });

			   node.attr("transform", function(d) {
			      return "translate(" + d.x + "," + d.y + ")";
			   });
		});

这里和 9.2节 一样,tick 指的是时间间隔,也就是每一个时间间隔之后就刷新一遍画面,刷新的内容写在后面的无名函数 function 中, function 函数中写上作图的内容。这里看到了吧,第7-9行里是用于平移的,平移的参数为 d.x 和 d.y 。

结果图:

拖动试试吧,哈哈:

自己用鼠标试试吧,点击下面的链接,完整代码请右键点击浏览器后选择查看:

http://www.ourd3js.com/demo/mapforce.html

谢谢阅读。

时间: 2024-07-29 21:58:38

【 D3.js 入门系列 --- 10.2 】 可拖动的地图的相关文章

【 D3.js 入门系列 --- 10 】 地图的绘制

本人的个人博客为:www.ourd3js.com csdn博客为:blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 地图的制作在 D3 中可以说是最重要的一环.因为在进行数据可视化时,很多情况都会和地图联系在一起,如中国各省的人口多少,GDP多少等,都可以和地图联系在一起. D3 中制作地图所需要的文件问 JSON 文件.JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.关于 JSON 的语法格式,可以在: http://www.w3s

【 D3.js 入门系列 — 10.3 】 GeoJSON 文件和 TopoJSON 文件的区别和联系

本人的个人博客为:www.ourd3js.com csdn博客为:blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 前些天有朋友留言询问 GeoJSON 文件和 TopoJSON 文件的关系,正好我其实也不是十分明了,查询了一番后整理如下,还望大家指证. 这两种文件都是基于 JSON 语法的,首先来说一下 JSON 语法和文件是怎样的. 1. JSON 格式 JSON(JavaScript Object Notation) 是一种轻量级的数据交换语言,以文字为基础,且易于让人阅读

【 D3.js 入门系列 --- 10.1 】 简化 GeoJSON 文件

本人的个人博客为:www.ourd3js.com csdn博客为:blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 上一篇制作中国地图时用到了 GeoJSON 文件.后来我发现这个文件太大,有 2,364 KB,当然这能保证地图很精确,但我们通常不需要那么精确的边界,所以有必要将它缩小.所幸已经有前人做过这项工作,真是前人栽树,后人乘凉,在这里表示感谢. 转换方法: 1. 打开网站  http://mapshaper.org/ 2. 点击 select 选择要缩减的 GeoJSO

【 D3.js 入门系列 --- 7 】 理解 update, enter, exit 的使用

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 在前面几节中反复出现了如下代码: svg.selectAll("rect") .data(dataset) .enter() .append("rect") 当所选择的 rect 数量比绑定的数据 dataset 的数量少的时候,通常会用到以上代码,这一节就详细说说当被选择元素和数据数量不一致时该如何处理. 这一节将涉及到三个函数.

【 D3.js 入门系列 --- 9.3 】 弦图的制作

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 弦图( Chord ),主要用于表示两个节点之间的联系.如下图: 两点之间的连线表示,谁和谁具有联系: 线的粗细表示权重: 上面的介绍源于: http://circos.ca/guide/tables/  ,我就不详细介绍了,还是很好理解的. 那么在 D3 中怎么用 layout 转换出弦图所需要的数据,并作图呢?请耐心往下看. 1. 首先给出数据 var ci

【 D3.js 入门系列 --- 9 】 常见可视化图形

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. Layout ,直译为"布局,安排".但在 D3 中不是这个意思. D3 中有很多 Layout 函数,它们不是为了在画面中布局什么,在 D3 中是对输入的数据进行转换,转换成比较容易进行可视化的数据.实际进行可视化时,需要其他的代码.我们可以简单地把 Layout 理解为"制作常见图形的函数",比如饼状图等等. D3 中一共提供了

【 D3.js 入门系列 --- 9.6 】 打包图的制作

本人的个人博客为:www.ourd3js.com csdn博客为:blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 打包图( Pack ),用于包含与被包含的关系,也表示各个对象的权重,通常用一圆套一圆来表示前者,用圆的大小来表示后者. 先看本节所使用的数据:  city2.json 这是各城市所属关系的数据.我们现在要用 D3 的 layout 来转换数据,使其容易进行可视化处理. var pack = d3.layout.pack() .size([ width, heigh

【 D3.js 入门系列 — 0 】 简介和安装

[ D3.js 入门系列 — 0 ] 简介和安装 发表于2014/06/12 近年来,可视化越来越流行,许多报刊杂志.门户网站.新闻.媒体都大量使用可视化技术,使得复杂的数据和文字变得十分容易理解,有一句谚语“一张图片价值于一千个字”,的确是名副其实.各种数据可视化工具也如井喷式地发展,D3 正是其中的佼佼者. 1. D3 是什么 D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档.听名字有点抽象,说简单一点,其实就是一个 JavaScript

【 D3.js 入门系列 --- 9.5 】 树状图的制作

这一节学习树状图的制作.树状图的制作和集群图完全相同,经过这两种 layout 转换后的数据也很相似. 本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 树状图( Tree )通常用于表示层级.上下级.包含与被包含关系.树状图的制作和 9.4节集群图的制作 的代码几乎完全一样.不错,你没看错,几乎完全一样.那么为什么要把这两种图分开,它们有什么不同呢?先来看看对于同一组数据,它们的结果有什么不同.数据为: {