D3 · 地图 · 可视化
最近都在学习D3和地图结合的东西,作为知识储备。于是自己就搞了一些小小栗子作为分享,很简单,所以高手可以略过啦哈哈。
需求: 通过一组json数据(比如是中国旅游业产值的数据(虚构)),我要把这些数据在地图上可视化显示,产值比较低的用浅颜色表示,产值高的则用深颜色表示。
实现的效果:
TopoJSON & GeoJSON 关系
TopoJSON是GeoJSON按拓扑学编码后的扩展形式,相比GeoJSON直接使用Polygon之类的几何体来表示图形的方法,TopoJSON中每个几何体都是将共享边(arcs)整合而成的。
对比一下
TopoJSON:
1 | { |
GeoJSON:
1 | { |
用TopoJSON最大优点:文件缩小了80%,消除了冗余,也就是说TopoJSON只相当于GeoJSON的20大小。
D3的应用中尽可能使用TopoJSON。
所以在我们项目里,中国边界使用了TopoJSON格式的数据。
产值数据
这一部分数据虽然是虚构,但是这一部分就是我们平时从接口调用得来的数据。
部分内容如下:
1 | { |
provinces就是每一个省份的值,name是省份名称,value是旅游业产值。
构建地图
重点来了。
d3.json请求数据
1 | d3.json("tourism.json", function(error, valuedata){ |
重组数据
将读取到的数据存到数组values,令其索引号为各省的名称。这里的作用就是:当我们为各省份填充色的时候可以循环读取。
1 | var values = {}; |
设定比例尺
1 | //求产值的最大值和最小值,并作为比例尺定义域的最大值&最小值 |
颜色
颜色插值函数以浅蓝色和深蓝色为边界,也就是说,省份的旅游产业值越大,蓝色越深。
1 | //定义最小值和最大值对应的颜色 |
设定省份颜色
1 | provinces.style("fill", function(d,i){ |
到了这里,我们得到这样的地图:
标识
虽然我们知道颜色越深产值越高,但是用户不知道。所以,我们缺少了一个什么颜色对应什么数值的一个标识。可以采用:左下角添加一个矩形,颜色渐变,然后再加对应的数值。
svg渐变中渐变是<defs>和<linearGradient>结合。这里不做详细介绍,举个例子:
1. 定义在
1 | <defs> |
- 使用
1 | <svg width="400" height="399"> |
那么用D3代码定义一个线性渐变如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25//定义一个线性渐变
var defs = svg.append("defs");
var linearGradient = defs.append("linearGradient")
.attr("id","linearColor")
.attr("x1","0%")
.attr("y1","0%")
.attr("x2","100%")
.attr("y2","0%");
var stop1 = linearGradient.append("stop")
.attr("offset","0%")
.style("stop-color",a.toString());
var stop2 = linearGradient.append("stop")
.attr("offset","100%")
.style("stop-color",b.toString());
//添加一个矩形,并应用线性渐变
var colorRect = svg.append("rect")
.attr("x", 20)
.attr("y", 490)
.attr("width", 140)
.attr("height", 30)
.style("fill","url(#" + linearGradient.attr("id") + ")");
最后,在举行在添加文字:1
2
3
4
5
6
7
8
9
10
11
12//添加文字
var minValueText = svg.append("text")
.attr("x", 20)
.attr("y", 490)
.attr("dy", "-0.3em")
.text(() => minvalue);
var maxValueText = svg.append("text")
.attr("x", 160)
.attr("y", 490)
.attr("dy", "-0.3em")
.text(()=> maxvalue);
最后把代码整理:
See the Pen d3-map by 何大小成 (@hopkinson) on CodePen.