在数据可视化中,地图是很重要的一部分。很多情况会与地图有关联,如中国各省的人口多少,GDP多少等,都可以和地图联系在一起。
制作地图需要 JSON 文件,将 JSON 的格式应用于地理上的文件,叫做 GeoJSON 文件。本文就是用这种文件绘制地图。 那么如何获取中国地图的 GeoJSON 文件呢? 如下链接,打开并下载至本地,并命名为ChinaGeoFull.json,后面实现会用到。 geo.datav.aliyun.com/areas_v2/bo…
html
<script src="./d3.v7.min.js"></script>
<body>
<svg width="900" height="700"></svg>
</body>
获取svg
//获取svg
var svg = d3.select('svg');
var width = svg.attr('width');
var height = svg.attr('height');
//创建区域分组
var g = svg.append('g').attr('transform', 'translate(0,0)');
投影函数
由于 GeoJSON 文件中的地图数据,都是经度和纬度的信息。它们都是三维的,而要在网页上显示的是二维的,所以要设定一个投影函数来转换经度纬度。
//创建一个地图投影
var mercator = d3.geoMercator()
.center([107, 31])//设置投影的中心点 经纬度
.scale(550)//设置缩放因子
.translate([width / 2, height / 2]);//设置平移偏移量
地理路径生成器
为了根据地图的地理数据生成 SVG 中 path 元素的路径值,需要用到d3.geoPath([projection[, context]),称它为地理路径生成器。
//创建一个地理路径生成器
var geoPath = d3.geoPath(mercator);
获取中国地图的GeoJson
./mapfull.json是100000_full.json去了湖北省的第四组数据,不去除地图溢出,不正常。
d3.json('./mapfull.json').then(function (data) {//D3 v5版本d3.json()现在将返回一个你可以在.then()方法中处理的Promise
console.log(data);//features
});
新建一个颜色比例尺
//新建一个颜色比例尺
var scaleColor = d3.scaleOrdinal()
.domain(d3.range(data.features.length))
.range(d3.schemeCategory10);
绘制区域
//绘制区域
g.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('stroke', 'gray')
.attr('strok-widht', 1)
.attr('d', geoPath)
.attr('fill', function (d, i) {
return scaleColor(i);
})
.on('mouseover', function (d, i) {
d3.select(this).attr('fill', 'yellow');
})
.on('mouseout', function (d, i) {
d3.select(this).attr('fill', scaleColor(i));
});
绘制文字
//绘制文字
g.append('g')
.selectAll('text')
.data(data.features)
.enter()
.append('text')
.attr('font-size', 12)
.attr('text-anchor', 'middle')
.attr('x', function (d, i) {
var position = mercator(d.properties.centroid || [0, 0]);
return position[0];
})
.attr('y', function (d, i) {
var position = mercator(d.properties.centroid || [0, 0]);
return position[1];
})
.attr('dy', function (d, i) {
//这里为什么这么写呢,因为澳门和香港重合了,挤到一起了。
if (d.properties.name === '澳门特别行政区') {
return 10;
}
})
.text(function (d, i) {
return d.properties.name;
});
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>中国地图</title>
<script src="./d3.v7.min.js"></script>
</head>
<body>
<svg width="900" height="700"></svg>
</body>
<script>
//获取svg
var svg = d3.select('svg');
var width = svg.attr('width');
var height = svg.attr('height');
//创建区域分组
var g = svg.append('g').attr('transform', 'translate(0,0)');
//创建一个地图投影
var mercator = d3.geoMercator()
.center([107, 31])//设置投影的中心点 经纬度
.scale(550)//设置缩放因子
.translate([width / 2, height / 2]);//设置平移偏移量
//创建一个地理路径生成器
var geoPath = d3.geoPath(mercator);
//获取中国地图的json文件
//利用node.js 在本地起一个http-server (./mapfull.json是100000_full.json去了湖北省的第四组数据,不去除地图溢出,不正常。)
d3.json('./mapfull.json').then(function (data) {//D3 v5版本d3.json()现在将返回一个你可以在.then()方法中处理的Promise
console.log(data);//features
//新建一个颜色比例尺
var scaleColor = d3.scaleOrdinal()
.domain(d3.range(data.features.length))
.range(d3.schemeCategory10);
//绘制区域
g.append('g')
.selectAll('path')
.data(data.features)
.enter()
.append('path')
.attr('stroke', 'gray')
.attr('strok-widht', 1)
.attr('d', geoPath)
.attr('fill', function (d, i) {
return scaleColor(i);
})
.on('mouseover', function (d, i) {
d3.select(this).attr('fill', 'yellow');
})
.on('mouseout', function (d, i) {
d3.select(this).attr('fill', scaleColor(i));
});
//绘制文字
g.append('g')
.selectAll('text')
.data(data.features)
.enter()
.append('text')
.attr('font-size', 12)
.attr('text-anchor', 'middle')
.attr('x', function (d, i) {
var position = mercator(d.properties.centroid || [0, 0]);
return position[0];
})
.attr('y', function (d, i) {
var position = mercator(d.properties.centroid || [0, 0]);
return position[1];
})
.attr('dy', function (d, i) {
//这里为什么这么写呢,因为澳门和香港重合了,挤到一起了。
if (d.properties.name === '澳门特别行政区') {
return 10;
}
})
.text(function (d, i) {
return d.properties.name;
});
});
</script>
</html>