近期肺炎疫情信息闹的火热,就该情况完成来沪人员分布热力图以及标注确诊患者足迹。就开发研究中遇到的问题以及解决方案做一下记录,如下所示:
一、效果示意图
简述完成效果:百度地图引入,增加热力图,添加比例尺,添加缩放平移控件,增加标注,窗口提示等,具体实现和关键代码描述如下。
二、引入百度地图,增加热力图显示
2.1官网申请账号,申请密钥
需要调用百度地图需要先登录官网百度平台官网注册,点击控制台
在点击->我的应用->创建应用
创建应用时如果只想在浏览器端和本地测试则选择应用类型为浏览器端,Referer白名单填*即可
提交完成即可在我的应用处看到你新增的应用,可复制密钥后续代码可使用,在下图您的密钥替换成相应密钥即可。
2.2增加热力图显示
可在百度地图提供的开发平台查看所需功能案例以及官方代码,便于查阅,方便好用百度地图API示例,示意图如下:
只需将所需功能对应的代码复制进自己项目中,并将密钥替换即可实现官网所示案例。
三、热力图改造所遇问题以及解决
3.1增加比例尺和缩放控件
关键代码如下所示,结合图一可看结果,皆有详细备注不再赘述:
//设置地图显示比例尺
var top_left_control = new BMap.ScaleControl({anchor: BMAP_ANCHOR_TOP_LEFT});// 左上角,添加比例尺
var top_left_navigation = new BMap.NavigationControl(); //左上角,添加默认缩放平移控件
var top_right_navigation = new BMap.NavigationControl({anchor: BMAP_ANCHOR_TOP_RIGHT, type: BMAP_NAVIGATION_CONTROL_SMALL}); //右上角,仅包含平移和缩放按钮
/*缩放控件type有四种类型:
BMAP_NAVIGATION_CONTROL_SMALL:仅包含平移和缩放按钮;BMAP_NAVIGATION_CONTROL_PAN:仅包含平移按钮;BMAP_NAVIGATION_CONTROL_ZOOM:仅包含缩放按钮*/
//添加控件和比例尺
function add_control(){
map.addControl(top_left_control);
map.addControl(top_left_navigation);
map.addControl(top_right_navigation);
}
add_control()
//移除控件和比例尺
function delete_control(){
map.removeControl(top_left_control);
map.removeControl(top_left_navigation);
map.removeControl(top_right_navigation);
}
3.2地图默认尺寸以及控制尺寸缩放范围
我默认地图显示五公里,即缩放尺寸12,百度地图可缩放范围为3-18,关键代码如下所示:
map.centerAndZoom(point, 12);
map.setMinZoom(10);
map.setMaxZoom(15);
3.3增加不同标注以及弹框
关键代码如下:
我使用引用图片的方式增加的标注,redPlace和grayPlace代表两种不同标注,简单放几条示例数据,主要包括经纬度,地点和时间,经纬度为确定位置,后两个信息为弹框显示可自行按需增减。实现效果如图一所示,
问题&解决
同一个地点出现不同时间的多条数据,标识出现覆盖,只显示一条数据的情况?更改前代码如下
for (var i = 0; i < redPlace.length; i ++) { var dandian = new BMap.Point(redPlace[i].lng,redPlace[i].lat); var outContent = redPlace[i].count +"" +"与"+redPlace[i].confirm_time+"确诊病例相关"; // var titleContent="最新确诊患者经过地点"; var photo ="../img/redplaceTwo.png" addMarker(dandian,outContent,photo); } for (var i = 0; i < grayPlace.length; i ++) { var dandian = new BMap.Point(grayPlace[i].lng,grayPlace[i].lat); var outContent = grayPlace[i].confirm_time + "在此位置" + grayPlace[i].count+ "发现确诊患者"; var photo ="../img/grayplaceTwo.png" addMarker(dandian,outContent,photo); }
解决:因需求14天前的数据显示为灰色,近期坐标数据为红色,所以首先需要判断redPlace中是否有重复的地址,有则提示增加相应时间,再判断灰色数据中是否有重复地点,有则增加相应时间且字体颜色变灰,代码中已经是更改好的版本,详情见如下代码所示。
var redPlace =[
{"lng":"121.417292","lat":"31.11383582","count":"春申景城","confirm_time":"2020.02.10"},
{"lng":"121.3791296","lat":"31.11698623","count":"莘沥路232号","confirm_time":"2020.02.10"},
{"lng":"121.326997","lat":"31.200547","count":"虹桥火车站","confirm_time":"2020.02.10"},
{"lng":"121.034558","lat":"30.90266994","count":"枫岸华庭","confirm_time":"2020.02.10"},
{"lng":"121.039004","lat":"30.90282982","count":"枫泾汽车站“枫梅线”站点","confirm_time":"2020.02.10"},
{"lng":"121.328657","lat":"31.276939","count":"龙湖天璞小区","confirm_time":"2020.02.22"}];
var grayPlace =[
{"lng":"121.467027","lat":"31.21994684","count":"陕西南路地铁站","confirm_time":"2020.02.06"},
{"lng":"121.4254809","lat":"31.20176557","count":"虹桥街道虹桥路1024弄","confirm_time":"2020.02.06"},
{"lng":"121.4610525","lat":"31.19391016","count":"枫林路街道东安二村","confirm_time":"2020.02.06"},
{"lng":"121.460441","lat":"31.19937","count":"安吉斯铭汽车销售服务有限公司","confirm_time":"2020.02.06"},
{"lng":"121.4838841","lat":"31.33612082","count":"四季绿城(北区)","confirm_time":"2020.02.09"}];
for (var i = 0; i < redPlace.length; i ++) {
var outContent = redPlace[i].count +"" +"与"+redPlace[i].confirm_time+"确诊病例相关"+"";
for(var j=0;j";
}
}
for(var k=0;k'+"与"+grayPlace[k].confirm_time+"确诊病例相关"+''+"";
}
}
var dandian = new BMap.Point(redPlace[i].lng,redPlace[i].lat);
// var titleContent="最新确诊患者经过地点";
var photo ="../img/redplaceTwo.png";
addMarker(dandian,outContent,photo);
}
for (var i = 0; i < grayPlace.length; i ++) {
var key = "1";
for(var j=0;j"+"与"+ grayPlace[i].confirm_time+ "确诊病例相关";
var dandian = new BMap.Point(grayPlace[i].lng,grayPlace[i].lat);
// var titleContent="曾经确诊患者经过地点";
var photo ="../img/grayplaceTwo.png"
addMarker(dandian,outContent,photo);
}
key = "1";
}
function addMarker(getPoint,outContent,photo){
var opts = {
position : getPoint, // 指定文本标注所在的地理位置
offset : new BMap.Size(5, 5), //设置文本偏移量
}
// var label = new BMap.Label(titleContent, opts); // 创建文本标注对象
// label.setStyle({
// color : "red",
// fontSize : "12px",
// height : "20px",
// lineHeight : "20px",
// fontFamily:"微软雅黑"
// });
// 设置图标
var myIcon = new BMap.Icon(photo, new BMap.Size(50, 50), {
imageSize: new BMap.Size(20, 20), // 设置图标大小
anchor: new BMap.Size(10, 20)
});
var marker = new BMap.Marker(getPoint,{icon:myIcon}); // 创建标注
//var marker = new BMap.Marker(getPoint);
var infoWindow = new BMap.InfoWindow(outContent,{width:200,}); // 创建信息窗口对象
// var titleWindow = new BMap.InfoWindow(titleContent, {width:50,height:5});
map.addOverlay(marker);
// marker.addEventListener("mouseover",function() {this.map.addOverlay(label);});
// marker.addEventListener("mouseout",function() {this.map.removeOverlay(label);});
marker.addEventListener("click", function(){
this.openInfoWindow(infoWindow);
// document.getElementById('smallpic').onload = function () {infoWindow.redraw();}
});
}
其中注释掉部分代码为鼠标移入或移出标识点的效果如下,即红色和灰色标注添加方法中加入
var titleContent="曾经确诊患者经过地点";
在调用方法addMarker中增加参数titleContent
addMarker(dandian,outContent,titleContent,photo);
addMarker方法中加入label的一些可自定义的属性等
var opts = { position : getPoint, // 指定文本标注所在的地理位置 offset : new BMap.Size(5, 5), //设置文本偏移量 } var label = new BMap.Label(titleContent, opts); // 创建文本标注对象 label.setStyle({ color : "red", fontSize : "12px", height : "20px", lineHeight : "20px", fontFamily:"微软雅黑" });
3.4加载海量点作标识
原本第一版本尝试使用百度地图API示例中的加载海量点更改一下图标样式,测试结果如下所示
核心代码如下:
if (document.createElement('canvas').getContext) { // 判断当前浏览器是否支持绘制海量点
var point = []; // 添加海量点数据
for (var i = 0; i < po.length; i++) {
point.push(new BMap.Point(po[i].lng,po[i].lat));
}
var options = {
size: BMAP_POINT_SIZE_SMALL,
shape: BMAP_POINT_SHAPE_CIRCLE,
color: 'red'
}
var pointCollection = new BMap.PointCollection(point, options); // 初始化PointCollection
map.addOverlay(pointCollection); // 添加Overlay
} else {
alert('请在chrome、safari、IE8+以上浏览器查看本示例');
}
但海量点形状有限,仅有圆形、星形、水滴形,但水滴型的颜色和大小不能更改,于是后期更换了一种解决方式,放上仅供参考
3.5热力图颜色更改与值域区间挂钩
本来颜色更改相对简单,更改效果如下所示。
问题,需求需要不同范围值显示不同的颜色,例如1-10为紫色,11-100为蓝色,101-1000为绿色,1001-10000为黄色,10000以上为红色,查阅了许多资料感觉从这个参数没办法做到(如有做的请留言相互学习一下)
查阅连接如下颜色修改参考--调色板、颜色修改参考、颜色修改参考
其中我觉得调色板的参考性最大,有一篇写可以更改颜色前的数值和max值设置相配合实现,我测试出来是不行,又有文章有说那个数值代表颜色透明度,总之颜色按不同阈值调整没有实现,遗憾。
四、便捷工具和官方API汇总
1.百度地图肯定离不开经纬度转换,一个好用的坐标拾取器,可输入地址名称查出该位置经纬度坐标坐标拾取器
2.百度地图JavaScript API2.0,许多参数可以参考查看百度地图JavaScriptAPI2.0
3.百度地图也是基于HeatMap.js做的,所以可能有的东西可以参考HeatMap.js参考