7-8月的时候,南京突如其来的陷入了一场没头没脑的疫情,一家人分隔在城市的各个角落,每天都会紧张的查看今日新增,小小的数字显得十分沉重。
试着用了支付宝,微信,卫健委官网的疫情地图,发现这些地图最多精确到市。而每天的通报则会精确到街道,于是我就想用做一张区划更细、数据可视化的地图。
先上基础效果图:
工具
- 原生 JS
- 百度地图 JavaScript API v2.0
做地图的时候我还不太会用react,干脆原生JS上阵。
百度地图 JavaScript API 现在已有 3.0,为了方便查找资料我用了2.0,3.0版本向下兼容,所以个人感觉使用3.0更好。
JavaScript API v3.0类参考
准备工作
使用百度地图 API 需先申请秘钥(ak)
输入应用名 -> 选择浏览器端 -> Refer临时可填 *
具体可参考开发指南
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=你的秘钥&s=1"></script>
添加参数 s=1 使地图支持 HTTPS。
开始
// 百度地图
const map = new BMap.Map("container", {drawMargin: 100, drawer: BMAP_SVG_DRAWER_FIRST });
// 控制按钮和滚轮
map.addControl(new BMap.NavigationControl({type: BMAP_NAVIGATION_CONTROL_SMALL}));
map.enableScrollWheelZoom();
自定义中心点
地图打开时会请求当前坐标,以当前市的中心点为默认中心,但南京地跨长江,南北距离长于东西,默认中心显示时会有点歪。
可以通过坐标拾取工具寻找任意点转化的坐标:坐标拾取工具
坐标拾取工具也可以用于确定缩放尺度。
百度地图API一共分为19级,比例尺分别为:
[1:20米(简称20米,后同),50米,100米,200米,500米,1公里,2公里,5公里,10公里,20公里,25公里,50公里,100公里,200公里,500公里,1000公里,2000公里,5000公里,10000公里]
分别对应:
[19级,18级,17级,16级,15级,14级,13级,12级,11级,10级,9级,8级,7级,6级,5级,4级,3级,2级,1级]
缩放尺度为整数
// 中心点坐标
let centre_point = new BMap.Point(118.779425,31.939229);
// 设置中心点和缩放尺度
map.centerAndZoom(centre_point, 10);
定位并显示坐标
百度地图提供三种定位方式:
| 接口 | 类名 | 简介 |
|---|---|---|
| 浏览器定位 | Geolocation | 优先调用浏览器H5定位接口,如果失败会调用IP定位 |
| IP定位 | LocalCity | 根据用户IP 返回城市级别的定位结果 |
| 定位SDK辅助定位 | Geolocation | 当您的APP中有内置的Web页面,同时在Web页面需要提供您的当前位置信息时,可调用集成在App中的百度地图定位SDK来获取更精准的位置信息 |
JavaScript API - 定位| 百度地图API SDK
如果只使用其中一种定位方式,有时候定位会出现偏差,精度也只到“市”,默认定位落在该市区划第一位的区里。
SDK 辅助定位的精度最高,province / city / district / street / streetNumber
// 定位所在地并显示坐标
const geolocation = new BMap.Geolocation();
// 自定义坐标 icon
const icon_marker = new BMap.Icon("img/marker.png", new BMap.Size(40, 42));
//创建地理编码器
const gc = new BMap.Geocoder();
// 开启SDK辅助定位
geolocation.enableSDKLocation();
geolocation.getCurrentPosition(function(r){
if(this.getStatus() === BMAP_STATUS_SUCCESS){
let mk = new BMap.Marker(r.point,{icon: icon_marker});
map.addOverlay(mk);
map.panTo(r.point);
// alert('您的位置:' + r.point.lng + ',' + r.point.lat);
let pt = r.point;
map.panTo(pt);//移动地图中心点
// console.log(map.pointToPixel(pt));
gc.getLocation(pt, function(rs){
let addComp = rs.addressComponents;
let curr_district = addComp.district;
let current_value = districts[curr_district] === undefined ? 0 : districts[curr_district];
let high_risk_num = high[current_value] === undefined ? 0 : Object.keys(high[current_value]).length;
let middle_risk_num = middle[current_value] === undefined ? 0 : Object.keys(middle[current_value]).length;
// alert(addComp.province + addComp.city + addComp.district + addComp.street + addComp.streetNumber);
});
}
else {
alert('failed'+this.getStatus());
}
});
添加多边形覆盖物实现数据可视化
BMap.Boundary(),完整的区划名(市+区)获取该区划的边界坐标点。
BMap.Polygon 接收一组坐标点,创建多边形
strokeWeight边框粗细strokeColor:边框颜色fillColor填充颜色fillOpacity填充透明度
let district_fullname = city_name + district_name;
let boundary = new BMap.Boundary();
boundary.get(district_fullname, function(result){
// 行政区域的点有多少个
let count = result.boundaries.length;
for(let i = 0; i < count; i++){
let ply = new BMap.Polygon(result.boundaries[i], {strokeWeight: 2, strokeColor: boundary_color, fillColor: district_color, fillOpacity: district_opacity});
map.addOverlay(ply);
}
}
最终成品
github: github.com/norayao/cov…
demo: covid19-map.emist.top/