環(huán)境
angular , d3
-
下載所繪地圖的json文件
一張地圖中担孔,省市的邊界煎谍,城市的坐標(biāo)位置执泰,名稱等信息咙好,均以json文件格式保存。這樣的GeoJson文件碱璃,可以在諸多網(wǎng)站中獲得弄痹。一個(gè)比較推薦的,提供中國省市地圖的網(wǎng)站是 DATAV.GeoAtlas嵌器。這里我們點(diǎn)擊下載geojson文件肛真,用于后面的繪制。
http://datav.aliyun.com/tools/atlas
DATAV.GeoAtlas網(wǎng)站.png 將json數(shù)據(jù)讀入程序
如何使用java或js讀json文件爽航,方法有很多蚓让,這里就不展開討論了。需要注意的是讥珍,程序設(shè)計(jì)人員需要決策的一件事情是历极,應(yīng)該在前端讀文件還是在后端讀文件。下面以我的例子展示衷佃,使用的是在后端讀文件趟卸,傳給前端的方式。
//后端讀取json文件
@GetMapping("/map/province")
public ResponseEntity<JSONObject> getProvinceMap() throws IOException {
log.debug("load province map json");
//這里為了方便,直接指定文件名锄列,工程中通常根據(jù)需要從別處獲得文件名图云。
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);
}
- 在前端網(wǎng)頁上繪制地圖
<!-- 在html中添加一個(gè)svg元素,此后的繪制操作均在這個(gè)svg里實(shí)現(xiàn)-->
<div>
<svg id="map" class="map-svg" #map></svg>
</div>
//ts里邻邮,引入d3
import * as d3 from 'd3';
import { ContainerElement } from 'd3';
//引入拓?fù)浞?wù)竣况,調(diào)用其getProvinceMap的GET請求,從后端拿到數(shù)據(jù)
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是經(jīng)度饶囚,23是緯度
.scale(5000) // 設(shè)置縮放量
.translate([0, 0]); // 設(shè)置平移量
// 定義地理路徑生成器,使每一個(gè)坐標(biāo)都會(huì)先調(diào)用此投影,才產(chǎn)生路徑值
const path = d3.geoPath().projection(projection); // 設(shè)定投影
const groups = svg.append('g'); //省市邊界
const cityPoint = svg.append('g'); //城市圓點(diǎn)
const cityLabel = svg.append('g'); //城市名稱標(biāo)簽
// 添加城市標(biāo)簽
cityLabel
.selectAll('label')
.data(this.mapJson.features) // 綁定數(shù)據(jù)
.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);
// 添加城市圓點(diǎn)
cityPoint
.selectAll('circle')
.data(this.mapJson.features) // 綁定數(shù)據(jù)
.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) // 綁定數(shù)據(jù)
.enter()
.append('path')
.on('mouseover', function(d, i) { //鼠標(biāo)移入移出的變色處理
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);
}
}
總結(jié)帕翻,繪制地圖還是比較容易的一件事,上述的代碼僅為示意萝风,不一定能正確運(yùn)行,且由于展示了整個(gè)繪制過程紫岩,導(dǎo)致重點(diǎn)不是很清晰规惰,這里指出,繪制地圖的關(guān)鍵是下面這段代碼泉蝌,同時(shí)先學(xué)習(xí)svg的path歇万,circle, text的繪制,會(huì)對讀懂示意代碼有很大的幫助勋陪。
// 1.定義投影和生成器
const projection = d3
.geoMercator()
.center([113, 23]) // 地圖中心位置,113是經(jīng)度贪磺,23是緯度
.scale(5000) // 設(shè)置縮放量
.translate([0, 0]); // 設(shè)置平移量
// 定義地理路徑生成器,使每一個(gè)坐標(biāo)都會(huì)先調(diào)用此投影,才產(chǎn)生路徑值
const path = d3.geoPath().projection(projection); // 設(shè)定投影
const groups = svg.append('g'); //省市邊界
// 添加城市邊界
groups
.selectAll('path')
.data(this.mapJson.features) // 綁定數(shù)據(jù)
.enter()
.append('path')
.style('fill', '#1890ff' )
.attr('d', path);
-
效果展示
d3繪制廣東省地圖.png
結(jié)束!