地图的轨迹播放功能属于比较常见的。那么如何实现呢?
今天说几种轨迹播放的方法。
一、直接绘制
这是我们一开始的做法。我们之前的做法是这样的,从后端获取轨迹经纬度的一个数组,使用定时器setInterval,每隔1秒画一个覆盖物小车,并且同时将上一个小车销毁,轨迹线条的话使用Polyline绘制。但是这样的绘制被用户提了意见,用户觉得我们的轨迹播放不够丝滑,总有一种一顿一顿的感觉。这种绘制方法网上到处都有,自己写也很简单,这里就不多说了。如果客户的要求不太高的话可以用。
二、基于算法的平滑移动
这里只是提供一种思路
其实动画的原理不就是很多张图片迅速变化吗?比如一开始出现的走马灯、动画片、电影。
卡顿的原因还是帧数太低了,那我们不要一秒绘制一次,这肯定是一顿一顿的,我们将两个轨迹点之间的空隙补全,然后以更高的频率绘制应该就可以了。这里可以搜一下平滑移动算法。理论上来说是可以实现的。
后来我看到百度地图有自带的方法,那还是不要自己写了。
三、百度地图自己的方法
这也是我推荐的。
3.1移动端平滑移动 SDK
安卓/IOS平滑移动 看了一下感觉挺丝滑的,而且车辆转弯时候角度变化啥的也很流畅。
3.2 JavaScript API GL 场景插件 轨迹
感觉网上用这个实现轨迹播放的文章几乎找不到,我来写一篇也挺有意义的呢。 可以参考 文档
不过这个应该只适合GL版本,其他版本的百度地图应该用不了。感觉效果还是挺好的。现在来实践一下。
还有一种是只有轨迹动画没有小车图标的,可以参考这个 教程
3.2.1 引入
创立一个vue项目,获得ak之类的省略了。 打开public的index.html文件,加入以下代码。并将ak替换为你自己申请的ak,如果没有的话就自己去申请一个。 参考教程
<script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&&type=webgl&ak=你的ak"></script>
<script src="https://unpkg.com/@bmapgl-plugin/track"></script>
3.2.2实现
创建一个vue文件。 参考这里的代码,然后进行一定的修改。 我目前来说只想实现播放和暂停,点击车辆图标可以实现弹出信息窗体,这个我们公司目前的需求。一开始我参考的示例代码中const movePoint = new Track.ModelPoint画车,结果控制台一直报错,不知道为啥,网上也没有什么资料。最后用new Track.GroundPoint画的。
在这个vue文件中,data中需要的有:
list:[],//轨迹经纬度
map:null,//地图
trackLine:null,//轨迹插件
carUrl:null // 车辆图标地址
在mounted中填入以下代码。创建地图map实例和trackLine实例。后续地图的操作可以用直接thi.map或this.trackLine实现了。
var map = new BMapGL.Map("container");
var point = new BMapGL.Point(116.404, 39.915);
map.centerAndZoom(point, 15);
this.map = map;
this.carUrl = require("@/assets/car.png");
const track = new Track.View(map);
// 设置轨迹点数据
const trackData = [];
console.log(this.list.length, "length");
this.list.forEach((e) => {
const point = new BMapGL.Point(e.lng, e.lat);
const trackDataPoint = new Track.TrackPoint(point, {
timeStamp: e.timeStamp,
rotation: 0,
});
trackData.push(trackDataPoint);
});
// 创建回放轨迹线对象
const trackLine = new Track.LocalTrack({
trackPath: trackData,
});
this.trackLine = trackLine;
// 添加轨迹线对象
track.addTrackLine(trackLine);
// [可选]设置地图追踪轨迹线对象
track.focusTrack(trackLine);
var movePoint = new Track.GroundPoint({
point: trackData[0].getPoint(),
style: {
url: this.carUrl,
level: 18,
scale: 1,
size: new BMapGL.Size(16, 32),
anchor: new BMapGL.Size(0.5, 0.5),
},
});
movePoint.addEventListener(Track.MapCodes.CLICK, (e) => {
console.log("Track.GroundPoint.click", e);
});
movePoint.addEventListener(Track.MapCodes.MOUSE_OVER, (e) => {
console.log("Track.GroundPoint.MOUSE_OVER", e);
});
movePoint.addEventListener(Track.MapCodes.MOUSE_OUT, (e) => {
console.log("Track.GroundPoint.MOUSE_OUT", e);
});
trackLine.setMovePoint(movePoint);
在页面中绘制两个按钮,播放按钮和暂停按钮,播放按钮绑定play事件,暂停按钮绑定pause事件,在methos中填入以下代码:
play() {
this.trackLine.startAnimation();
console.log(this.trackLine, 111);
},
pause() {
this.trackLine.pauseAnimation();
},
运行了一下,感觉效果还行,我的图标随便从网上找的,其实应该放个俯视图,应该会更好。
3.2.3点击弹出窗体
点击小车图标可以看到返回数据
我们把小车当前的经纬度数据放到窗体里。把之前movePoint.addEventListener,监听的click事件的回调函数进行修改。
movePoint.addEventListener(Track.MapCodes.CLICK, (e) => {
console.log("Track.GroundPoint.click", e);
let point = e.latLng
const content = `<div>经纬度:${point.lat}、${point.lng} </div>`;
var opts = {
width: 200, // 信息窗口宽度
height: 100, // 信息窗口高度
};
const infoWindow = new BMapGL.InfoWindow(content, opts);
this.infoWindow = infoWindow;
this.map.openInfoWindow(infoWindow, point);
});
功能实现没啥问题