百度地图 API 制作足迹地图教程升级版
一、使用百度地图 API 的原因
之前一直在用 Robert Harm 开发我翻译的 Maps Marker Pro 插件,优点是极其强大,想要的各种功能都有了,但缺点也很明显,由于众所周知的原因,国内谷歌地图处于残废状态,OpenStreetMap 卡得要命,必应地图简陋又龟速,导致加载了 Mapsmarker 的页面响应极其缓慢,整合多个地图的页面尤其糟糕,严重影响使用体验。
感谢 @随望淡思 ,他的博文《用百度地图 API 做个人足迹地图教程》给了我不少启发,进而使用百度地图 API 重做了 “足迹” 页面,达到了自己想要的效果。
二、代码及修订
原始代码及安装过程见 @随望淡思 文,不再赘述。使用过程中发现一些问题和不足,综合查阅百度地图 API 后逐个解决。特分享如下:
1、在网速较慢,图片未加载时,生成的信息框高度比图片的总高度小,导致图片部分被隐藏。
此问题百度地图官方文档有写。代码如下:
marker.addEventListener("click", function() { infoWindow.setContent(content); this.openInfoWindow(infoWindow); document.getElementById('imgDemo').onload = function (){ infoWindow.redraw(); //即 onload 时重绘弹出窗口 } });
2、如何在同一个页面加载双地图?
解决方法百度地图官方也有说明,但比较简略。我自己整理的代码如下:
(1)<body></body> 中插入两个层:
<div id="map1_container" > <h2 class="post-title" style="text-align:center">World</h2> <div id="allmap1"></div> </div> <hr> <div id="map2_container"> <h2 class="post-title" style="text-align:center">China</h2> <div id="allmap2"></div> </div>
(2)</html> 下方插入 js:
<script type = "text/javascript" > /* 创建 Map1 */ var map1 = new BMap.Map("allmap1"); //创建 Map 实例 1 var point1 = new BMap.Point(8.858654,20.426204); //创建点坐标 var mapType1 = new BMap.MapTypeControl({mapTypes: [BMAP_NORMAL_MAP,BMAP_HYBRID_MAP],anchor: BMAP_ANCHOR_TOP_RIGHT}); //创建普通 2D 地图和卫星地图,放置在右上角 var overView1 = new BMap.OverviewMapControl(); //增加放大缩小及平移控件 var overViewOpen1 = new BMap.OverviewMapControl({isOpen:true, anchor: BMAP_ANCHOR_BOTTOM_RIGHT}); map1.centerAndZoom(point1, 1); //初始化地图, 设置中心点坐标和地图级别 /* 创建 Map2 */ var map2 = new BMap.Map("allmap2"); //创建 Map 实例 2 var point2 = new BMap.Point(106.744719,34.308185); //创建点坐标 var mapType2 = new BMap.MapTypeControl({mapTypes: [BMAP_NORMAL_MAP,BMAP_HYBRID_MAP],anchor: BMAP_ANCHOR_TOP_RIGHT}); //创建普通 2D 地图和卫星地图,放置在右上角 var overView2 = new BMap.OverviewMapControl(); //增加放大缩小及平移控件 var overViewOpen2 = new BMap.OverviewMapControl({isOpen:true, anchor: BMAP_ANCHOR_BOTTOM_RIGHT}); map2.centerAndZoom(point2, 5); //初始化地图, 设置中心点坐标和地图级别 </script>
3、如何一键回到最初的位置?
读者在点了几个地标后容易迷失方向,想要回到最初的位置,只能鼠标滚半天……解决方法是在图上增加一个自定义控件 “⊕” 并加入如下代码。
/* 定义一个控件实现点击后回到原位置 Map1 */ function ZoomControl1(){ //设置默认停靠位置和偏移量 this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT; this.defaultOffset = new BMap.Size(23, 210); } //通过 JavaScript 的 prototype 属性继承于 BMap.Control ZoomControl1.prototype = new BMap.Control(); //自定义控件必须实现 initialize 方法,并且将控件的 DOM 元素返回 //在本方法中创建个 div 元素作为控件的容器,并将其添加到地图容器中 ZoomControl1.prototype.initialize = function(map1){ //创建一个 DOM 元素 var div = document.createElement("div"); //添加文字说明 div.appendChild(document.createTextNode("⊕")); //设置样式 div.style.color = "#4369d0"; div.style.cursor = "pointer"; div.style.border = "1px solid gray"; div.style.backgroundColor = "whitesmoke"; //绑定事件 div.onclick = function(e){ map1.reset(); //reset 图层为原始位置 } //添加 DOM 元素到地图中 map1.getContainer().appendChild(div); //将 DOM 元素返回 return div; } //创建控件实例 var myZoomCtrl1 = new ZoomControl1();
然后在创建 Map 的时候加上:
map1.addControl(myZoomCtrl1); //自定义控件添加到地图当中
4、怎样使用自定义图标?
百度地图官方文档如下:
function addMarker(point, index){ //创建图标对象 var myIcon = new BMap.Icon("markers.png", new BMap.Size(23, 25), { //指定定位位置。 //当标注显示在地图上时,其所指向的地理位置距离图标左上 //角各偏移 10 像素和 25 像素。您可以看到在本例中该位置即是 //图标中央下端的尖角位置。 anchor: new BMap.Size(10, 25), //设置图片偏移。 //当您需要从一幅较大的图片中截取某部分作为标注图标时,您 //需要指定大图的偏移位置,此做法与 css sprites 技术类似。 imageOffset: new BMap.Size(0, 0 - index * 25) // 设置图片偏移 }); //创建标注对象并添加到地图 var marker = new BMap.Marker(point, {icon: myIcon}); map.addOverlay(marker); }
如果想要稍复杂一点,比如 “我去过的地方用默认图标,我想去的地方用自定义图标”,我的代码如下:
var pt = new BMap.Point(lng, lat); var myIcon = new BMap.Icon("icon/baiduOrangeIcon.png", new BMap.Size(20,28), {anchor: new BMap.Size(10, 28), infoWindowAnchor: new BMap.Size(10, 0)}); //自定义标注图标,注意添加 anchor、infoWindowAnchor 消除偏移 if(name.indexOf("想去") == -1) { //此处是在地标名字中加了 “(想去)” 二字,凡是有此二字的,判定为想去的地方并加载自定义图标 var marker = new BMap.Marker(pt); //创建标注 map1.addOverlay(marker); //将标注添加到地图中 } else { var marker = new BMap.Marker(pt,{icon:myIcon}); //自定义创建标注 map1.addOverlay(marker); //将标注添加到地图中 }
5、原代码里,文章超链接、图片都为空时出现错误图标。
解决方法:添加两段 if-else 函数。
if (web != 0) var webtxt = "<a style='color:#888' href="+web+">"+name+"</a>"; //如果地名有超链接到文章,显示之 else var webtxt = name; //否则只显示地名 if (pic1 != 0) var content = "<div style='font-size:14px;max-width:220px;word-wrap:break-word;overflow:visible'><img src="+pic1+" style='width:220px;' id='imgDemo'><p/>"+webtxt+"<p/>"+year+"</div>"; //如果有图片,显示之 else var content = "<div style='min-height:100%;max-width:220px;font-size:14px'>"+webtxt+"<p/>"+year+"</div>"; //否则不显示,解决<img src="空"> 时显示错误的问题
6、设置地标阴影及动画
阴影:
var pt = new BMap.Point(lng, lat); var myIcon = new BMap.Icon("/icon/baiduBlueIcon.png", new BMap.Size(20,28), {anchor: new BMap.Size(10, 28), infoWindowAnchor: new BMap.Size(10, 0)}); var shadow1 = new BMap.Icon("/icon/shadow.png", new BMap.Size(20,28), {anchor: new BMap.Size(8, 26)}); var marker = new BMap.Marker(pt,{icon:myIcon, shadow:shadow1});
动画:
marker.addEventListener("click", function() { marker.setAnimation(BMAP_ANIMATION_DROP); }
7、设置省份高亮 [2019/4/30 更新]
有简单办法也有复杂办法。这里只举最简单的例子。
/* 创建高亮省份 */ madeBoundary(); //区域图 function madeBoundary() { var datas = new Array("北京","上海","广东","江苏"); var bdary = new BMap.Boundary(); for(var i=0;i<datas.length;i++){ getBoundary1(datas[i],bdary); } } //设置省份区域图 function getBoundary1(data,bdary){ data = data.split("-"); bdary.get(data[0], function(rs){ //获取行政区域 var count = rs.boundaries.length; //行政区域的点有多少个 var pointArray = []; for (var i = 0; i < count; i++) { var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight: 2, strokeColor: "#ff0000",fillOpacity:0.5,fillColor:"#fbd8d8"}); //建立多边形覆盖物 map2.addOverlay(ply); //添加覆盖物 } }); }
三、百度足迹地图优缺点
优点:
- 加载速度飞快。
- 可使用百度地图坐标拾取系统搜索中文地名获取经纬度,偏僻的地儿也能秒找,非常方便。
- 配色清新,与 “不存在” 的谷歌地图有 “异曲同工” 之妙。
缺点:
- 手工修改页面新增地名的方法非常原始。像我一样有上百个地标的,简直做到要怀疑人生。
- 国外地名全部抓瞎,地标严重不全。
四、两种足迹地图的对比
目前最好用也是最全面的足迹地图插件仍然非 Mapsmarker 莫属,建议有需要的博主至此处下载。
对速度有需求、主要行踪集中在国内且有一定 JS 代码基础的博主,可选用百度地图的代码并自己制作。
Mapsmarker 截屏:

百度地图截屏:

[2019/6/23] 昨晚开始百度地图开始限制最大视图:

真的好恶心啊!换回 Mapsmarker!
厉害
@fooleap 呃,承蒙大神老弟夸赞,实在受之有愧……
加加油,争取把世界地图染红。
@从良未遂 那我可能会累死……
钻研精神可嘉 😅
@bigfa 过奖了,瞎折腾
红满全球指日可待
@maie “指日” 还是很困难的,人生还有四十年……