使用百度地图 api 做的足迹页面一段时间了,经过一番改造,目前已基本能够满足自己需求。
一、添加百度地图
添加百度地图基本思路就是6点:
- 申请百度AK
- 适当位置添加百度地图容器
- 引入百度地图 api
- 创建地图实例
- 设置地图中心点
- 初始化地图
这里,也可参考官方的基础示例
1. 申请百度账号和AK
首先必须登陆百度账号,申请一个属于自己的AK,可以点击这个申请链接,并设置白名单,因为其AK是通过js文件引用的,会暴露在互联网,因此我申请了2个AK,一个白名单设置为 * ,给自己的测试环境用;一个白名单设置为博客域名,给博客用。
2.创建地图容器元素
地图需要一个HTML元素作为容器,这样才能展现到页面上。这里我们创建了一个div元素。
<div id="container"></div>
3.引入百度地图API文件
在html代码中添加加载百度 api 的 js 文件,需要填写AK
<script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=您的AK">
</script>
也可以通过异步加载js文件的方式来引用
var script = document.createElement("script");
script.type = "text/javascript";
script.src =
"//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的AK&callback=init";
document.body.appendChild(script);
4.创建地图实例
位于BMapGL命名空间下的Map类表示地图,通过new操作符可以创建一个地图实例。其参数可以是元素id也可以是元素对象。
var map = new BMapGL.Map("container");
注意:
- 在调用此构造函数时应确保容器元素已经添加到地图上;
- 命名空间 API GL版使用BMapGL作为命名空间,所有类均在该命名空间之下,比如:BMapGL.Map、BMapGL.Control、BMapGL.Overlay;
5.设置中心点坐标
这里我们使用BMapGL命名空间下的Point类来创建一个坐标点。Point类描述了一个地理坐标点,其中116.404表示经度,39.915表示纬度。(为天安门坐标)
var point = new BMapGL.Point(116.404, 39.915);
注意:在使用百度地图JavaScript API服务时,需使用百度BD09坐标,如使用其他坐标( WGS84、GCJ02)进行展示,需先将其他坐标转换为BD09,详细说明请参考坐标转换说明,请勿使用非官方的转换方法。
6.地图初始化,同时设置地图展示级别
在创建地图实例后,我们需要对其进行初始化,BMapGL.Map.centerAndZoom()方法要求设置中心点坐标和地图级别。 地图必须经过初始化才可以执行其他操作
map.centerAndZoom(point, 15);
7.其他配置
官方提供了详细的参考示例DEMO
map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
至此,我们就快速创建了一张以天安门为中心的地图。
上面的代码结合起来就是:
<!-- 指定地图容器 -->
<div id="container"></div>
<!-- 引用api -->
<script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=您的AK"></script>
<!-- 添加地图 -->
<script>
var map = new BMapGL.Map("container"); // 创建Map实例
var point = new BMapGL.Point(116.404, 39.915); //设置中心点坐标
map.centerAndZoom(point, 11); // 地图初始化,同时设置地图展示级别
map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
</script>
8. 异步加载地图
JavaScript API GL v1.0支持异步加载,我们可以在引用脚本的时候添加callback参数,当脚本加载完成后callback函数会被立刻调用,异步加载基础代码如下
//回调函数init
function init() {
var mp = new BMapGL.Map('map');
mp.centerAndZoom(new BMapGL.Point(121.491, 31.233), 11);
}
//异步加载,注意callback的值为函数名init
function loadScript() {
var script = document.createElement("script");
script.src = "https://api.map.baidu.com/api?v=1.0&type=webgl&ak=您的密钥&callback=init";
document.body.appendChild(script);
二、配置百度地图
1. 添加足迹
地图有了,我们缺少足迹。添加足迹也就是添加标记点。实现起来就2点,创建点位,添加点位,异步加载时,添加足迹的代码需放到回调函数 init 中。
//添加点坐标
var point1=new BMapGL.Point(112.001, 27.700);
// 创建点标记
var marker1 = new BMapGL.Marker(point1);
// 在地图上添加点标记
map.addOverlay(marker1);
2. 添加足迹信息
足迹有了,但我们希望点击足迹时会互动一下,如可以显示足迹点的一些详情,这里就需要用到信息窗口以及点击足迹点击事件了,以之前创建的marker1标记点为例。
// 创建信息窗口,opts为窗口基本信息
var opts = {
width: 200,
height: 100,
title: '娄底'
};
var infoWindow = new BMapGL.InfoWindow('我爱我的家乡娄底', opts);
// 给点标记添加点击事件
marker1.addEventListener('click', function () {
map.openInfoWindow(infoWindow, point1); // 开启信息窗口
});
3. 丰富足迹信息
按照上面已经的方法已经可以创建一个理想的足迹地图了,但我还想图文并茂一些,也就是希望添加图片等等,其实百度地图足迹信息是支持html代码的
将上方原来展示的'我爱我的家乡娄底'
,修改一下,改为'我爱我的家乡娄底<br><img src="/path/to/img.webp"/>'
看看,是否更加心动了?
4. 批量添加足迹点
上面的足迹信息是逐个添加事件的,且信息也没有规律性,直接使用之前 jvectmap 地图足迹点添加规则,进一步完善,就不提思路了,直接代码。将下面代码放到 init 函数中即可。
// 添加足迹点,每个足迹点为1个对象,包括足迹坐标LatLng,足迹名称name,足迹描述desc,足迹照片photo(可选),自定义足迹图标icon(可选)
var markers =[
{
latLng: [126.62357440234007, 45.720744140456844],
name: "哈尔滨",
desc: "在此度过了难忘的4年大学生活。",
photo: [
"tea1.webp",
"tea2.webp",
"tea3.webp",
],
},
{
latLng: [129.38819140037123, 45.18552720961948],
name: "威虎山",
desc: "和哈尔滨的大学老乡一起,平生第一次外出旅游",
icon: "foot.png",
},
{
latLng: [114.5215620483218, 38.04793789946941],
name: "石家庄",
desc: "",
},
];
//给每个足迹点添加足迹和事件
markers.forEach((element) => {
let point = new BMapGL.Point(element.latLng[0], element.latLng[1]); //创建坐标点
// 创建坐标点标记
if (element.icon) {
var myIcon = new BMapGL.Icon(element.icon, new BMapGL.Size(26, 26));
var marker = new BMapGL.Marker(point, { icon: myIcon });
} else {
var marker = new BMapGL.Marker(point);
}
map.addOverlay(marker); //添加到坐标点标记
let opts = {
width: 320, // 信息窗口宽度
height: 0, // 信息窗口高度
title: element.name, // 信息窗口标题
};
let info = "";
if (element.photo) {
let photos = element.photo;
photos.forEach((value) => {
info +=
"<a style='flex:1 1 50%;padding:1px;'><img style='width:100%;height:100%;object-fit: cover;' class='imgDemo' src='" +
value +
"'/></a>";
});
info =
"<div style='display: flex;flex-wrap: wrap;'>" +
info +
"</div><p style='line-height:1.5;font-size:12px;padding:8px 0;'>" +
element.desc +
"</p>";
} else {
info =
"<p style='line-height:1.5;font-size:12px;padding:8px 0;'>" +
element.desc +
"</p>";
}
let infoWindow = new BMapGL.InfoWindow(info, opts); // 创建信息窗口对象
marker.addEventListener("click", function () {
map.openInfoWindow(infoWindow, point); //开启信息窗口
// 图片加载完毕重绘infoWindow
element = document.getElementsByClassName("imgDemo");
for (i = 0; i <= element.length; i++) {
element[i].onload = function () {
infoWindow.redraw(); // 防止在网速较慢时生成的信息框高度比图片总高度小,导致图片部分被隐藏
};
}
});
});
至此,比较好维护的地图就创建好了。
5.将坐标点信息直接放到 json 文件
上面的代码还不太好维护,最后我将坐标信息以 json 的形式存放和读取来实现。
foods.json 的内容:
[
{
"latLng": [
126.62357440234007,
45.720744140456844
],
"name": "哈尔滨",
"desc": "在此度过了难忘的4年大学生活。",
"photo": [
"tea1.webp",
"tea2.webp",
"tea3.webp"
]
},
{
"latLng": [
129.38819140037123,
45.18552720961948
],
"name": "威虎山",
"desc": "和哈尔滨的大学老乡一起,平生第一次外出旅游",
"icon": "foot.png"
},
{
"latLng": [
114.5215620483218,
38.04793789946941
],
"name": "石家庄",
"desc": ""
}
]
并将 init 函数中的 var makers=[...]
这段代码删除,在主页面添加如下代码即可(搜索实现,折腾了好久,不知道这个是否有更优的办法)。
var markers = [];
async function fetchData() {
try {
const response = await fetch('foots.json');
if (!response.ok) {
throw new Error('Network response was not ok');
}
markers = await response.json(); // 解析JSON格式的响应体
} catch (error) {
console.error('There was a problem with your fetch operation:', error);
}
}
fetchData();