环境
angular , d3
-
下载所绘地图的json文件
DATAV.GeoAtlas网站.png
一张地图中,省市的边界,城市的坐标位置,名称等信息,均以json文件格式保存。这样的GeoJson文件,可以在诸多网站中获得。一个比较推荐的,提供中国省市地图的网站是 DATAV.GeoAtlas。这里我们点击下载geojson文件,用于后面的绘制。
http://datav.aliyun.com/tools/atlas
-
将json数据读入程序
如何使用java或js读json文件,方法有很多,这里就不展开讨论了。需要注意的是,程序设计人员需要决策的一件事情是,应该在前端读文件还是在后端读文件。下面以我的例子展示,使用的是在后端读文件,传给前端的方式。
//后端读取json文件
@GetMapping("/map/province")
public ResponseEntity<JSONObject> getProvinceMap() throws IOException {
log.debug("load province map json");
//这里为了方便,直接指定文件名,工程中通常根据需要从别处获得文件名。
String mapFileName = "广东省.json"
String docPath = System.getProperty("user.dir") + "/src/main/resources/config/map/";
File file = new File(docPath, mapFileName);
String content = FileUtils.readFileToString(file, "UTF-8");
JSONObject jsonObject = JSONObject.parseObject(content);
return ResponseEntity.ok().body(jsonObject);
}
- 在前端网页上绘制地图
<!-- 在html中添加一个svg元素,此后的绘制操作均在这个svg里实现-->
<div>
<svg id="map" class="map-svg" #map></svg>
</div>
//ts里,引入d3
import * as d3 from 'd3';
import { ContainerElement } from 'd3';
//引入拓扑服务,调用其getProvinceMap的GET请求,从后端拿到数据
import { TopologyService } from 'app/cpe/service/topology.service';
export class CpeProvinceMapComponent implements OnInit {
//获DOM中svg元素
@ViewChild('map') mapSvg: ElementRef;
ngOnInit() {
this.topologyService.getProvinceMap().subscribe(mapJson => {
this.mapJson = mapJson;
this.generateProvinceMap();
});
}
generateProvinceMap() {
const svg = d3.select('#map');
// 1.定义投影和生成器
const projection = d3
.geoMercator()
.center([113, 23]) // 地图中心位置,113是经度,23是纬度
.scale(5000) // 设置缩放量
.translate([0, 0]); // 设置平移量
// 定义地理路径生成器,使每一个坐标都会先调用此投影,才产生路径值
const path = d3.geoPath().projection(projection); // 设定投影
const groups = svg.append('g'); //省市边界
const cityPoint = svg.append('g'); //城市圆点
const cityLabel = svg.append('g'); //城市名称标签
// 添加城市标签
cityLabel
.selectAll('label')
.data(this.mapJson.features) // 绑定数据
.enter()
.append('text')
.text(function(d, i) {
return d.properties.name;
})
.attr('x', function(d, i) {
return projection(d.properties.center)[0];
})
.attr('y', function(d, i) {
return projection(d.properties.center)[1] - 5;
})
.attr('font-size', 10);
// 添加城市圆点
cityPoint
.selectAll('circle')
.data(this.mapJson.features) // 绑定数据
.enter()
.append('circle')
.attr('class', 'point')
.attr('cx', function(d, i) {
return projection(d.properties.center)[0];
})
.attr('cy', function(d, i) {
return projection(d.properties.center)[1];
})
.attr('stroke', 'red')
.attr('stroke-width', 1)
.attr('fill', 'white')
.attr('r', 2);
const enableCities = this.enableCities;
// 添加城市边界
groups
.selectAll('path')
.data(this.mapJson.features) // 绑定数据
.enter()
.append('path')
.on('mouseover', function(d, i) { //鼠标移入移出的变色处理
d3.select(this).style('fill', '#2CD8FF');
}
})
.on('mouseout', function(d, i) {
d3.select(this).style('fill', '#1890ff');
})
.style('fill', '#1890ff' )
.style('stroke', 'black')
.attr('d', path);
}
}
总结,绘制地图还是比较容易的一件事,上述的代码仅为示意,不一定能正确运行,且由于展示了整个绘制过程,导致重点不是很清晰,这里指出,绘制地图的关键是下面这段代码,同时先学习svg的path,circle, text的绘制,会对读懂示意代码有很大的帮助。
// 1.定义投影和生成器
const projection = d3
.geoMercator()
.center([113, 23]) // 地图中心位置,113是经度,23是纬度
.scale(5000) // 设置缩放量
.translate([0, 0]); // 设置平移量
// 定义地理路径生成器,使每一个坐标都会先调用此投影,才产生路径值
const path = d3.geoPath().projection(projection); // 设定投影
const groups = svg.append('g'); //省市边界
// 添加城市边界
groups
.selectAll('path')
.data(this.mapJson.features) // 绑定数据
.enter()
.append('path')
.style('fill', '#1890ff' )
.attr('d', path);
-
效果展示
d3绘制广东省地图.png
结束!
网友评论