使用百度地图 JS API 播放轨迹
发表于2019-09-09,长度4253,
505个单词,
12分钟读完
尽管百度在BAT巨头中的名声越来越差,但不可否认百度地图依然是国内使用最广泛、最方便的地图工具。相比高德、腾讯的地图,领先的不是一两点。 我之前吐槽过一次高德的周边,简直不敢回首:高德打车,这辈子不再用。
今天简单说一下百度地图API的使用。最近用它实现了一个播放轨迹的功能,就是有一系列轨迹点和对应的时间点组成的时序集合,可以根据不同时间间隔、不同距离间隔进行轨迹相邻点间的移动。
效果如图:

资源准备
百度地图上的标记都是图片,当然它自动了默认的标记图。如果想使用其他图片作为标记(比如图中的电动车),需要自己去下载,并且要指定图片的大小。
我推荐使用https://www.iconfont.cn这个网站,图标多,而且尺寸可以自己选。
实现代码
先引入依赖包和图片:
import moment from 'moment'
import bike from '/assets/bike.png'
我们需要地图对象、轨迹集合、电车标记:
var markerArr = data.list; // 轨迹集合
var map; // 地图对象
var bikeMarker; // 电车标记
然后初始化地图:
if (markerArr.length == 0) return;
map = new BMap.Map("map", { enableMapClick: true }); // 地图显示在ID为map的元素上
var point = new BMap.Point(markerArr[0]['longitude'], markerArr[0]['latitude']); // 中心点为第一个轨迹点
map.centerAndZoom(point, 15);
map.enableScrollWheelZoom(true);
map.addControl(new BMap.MapTypeControl()); // 地图类型
map.addControl(new BMap.NavigationControl()); // 导航控件
map.addControl(new BMap.OverviewMapControl()); // 小地图
map.addControl(new BMap.ScaleControl()); // 缩放控件
接下来是重点。先把轨迹点间的距离和速度算出来,放在一个新集合里:
var pairs = [];
for (var i = 0; ; i++) {
var cond = false;
var obj = markerArr[i];
var point = new BMap.Point(obj['longitude'], obj['latitude']);
var icon;
if (i == 0) {
icon = new BMap.Icon(`${sp}`, new BMap.Size(32, 32), {
anchor: new BMap.Size(16, 32),
});
} else if (i + 1 == markerArr.length) {
icon = new BMap.Icon(`${dp}`, new BMap.Size(48, 48), {
anchor: new BMap.Size(24, 48),
});
cond = true;
} else {
icon = new BMap.Icon(`${cp}`, new BMap.Size(16, 16), {
anchor: new BMap.Size(8, 8),
});
}
var marker = new BMap.Marker(point, { icon });
marker.setLabel(new BMap.Label(obj['time'].split('T')[1].split('.')[0], {
offset: new BMap.Size(25, 5)
}));
map.addOverlay(marker);
if (cond) {
// 标记完最后一个点就结束
break;
}
const nxtObj = markerArr[i + 1];
var ruler = this.zoom[map.getZoom() - 1];// 取出比例尺
const nxtP = new BMap.Point(nxtObj['longitude'], nxtObj['latitude']);
var timeDiff = moment(nxtObj['time']) - moment(obj['time']);
timeDiff = parseInt(timeDiff / base);
var dist = map.getDistance(point, nxtP);
if (dist * 5 > ruler) {
// 距离太短的不分段
const stp = parseInt(dist * 25 / ruler);
var st = 0;
var startP = point;
if (obj['longitude'] == nxtObj['longitude']) {
const latDiff = (nxtObj['latitude'] - obj['latitude']) / stp;
while (st < stp) {
var newLat = startP['lat'] + latDiff;
var endP = new BMap.Point(nxtObj['longitude'], newLat);
addLineFreg([startP, endP], timeDiff, stp);
startP = endP;
st++;
}
} else if (obj['latitude'] == nxtObj['latitude']) {
const lngDiff = (nxtObj['longitude'] - obj['longitude']) / stp;
while (st < stp) {
var newLng = startP['lng'] + lngDiff;
var endP = new BMap.Point(newLng, nxtObj['latitude']);
addLineFreg([startP, endP], timeDiff, stp);
startP = endP;
st++;
}
} else {
// 不可能出现经纬度都一样 不然距离为0
var lngDiff = (nxtObj['longitude'] - obj['longitude']) / stp;
var latDiff = (nxtObj['latitude'] - obj['latitude']) / stp;
while (st < stp) {
var newLng = startP['lng'] + lngDiff;
var newLat = startP['lat'] + latDiff;
var endP = new BMap.Point(newLng, newLat);
addLineFreg([startP, endP], timeDiff, stp);
startP = endP;
st++;
}
}
} else {
addLineFreg([point, nxtP], timeDiff, 5);
}
}
然后根据速度展示集合点:
showLineFreg();
const showLineFreg = async () => {
for (let i = 0; i < pairs.length; i++) {
var o = pairs[i]
await show(o);
}
}
const show = (pair) => new Promise((resolve, reject) => {
const to = pair.mock * diss;
setTimeout(() => {
if (bikeMarker) {
map.removeOverlay(bikeMarker);
}
bikeMarker = new BMap.Marker(pair.points[1], { icon: bicon });
map.addOverlay(bikeMarker);
map.addOverlay(new BMap.Polyline(pair.points, {
strokeColor: "black",
strokeWeight: 2,
strokeOpacity: 0.7
}));
map.panTo(pair.points[0]);
resolve();
}, to);
});
注意使用的异步标记,不然不能一点点移动。
这样就大功告成了!
Written on September 9, 2019
分类:
dev,
标签:
javascript
如果你喜欢,请赞赏!
