vue项目中 百度地图轨迹播放功能实践,点击车辆图标弹出窗体

1,324 阅读4分钟

地图的轨迹播放功能属于比较常见的。那么如何实现呢?

今天说几种轨迹播放的方法。

一、直接绘制

这是我们一开始的做法。我们之前的做法是这样的,从后端获取轨迹经纬度的一个数组,使用定时器setInterval,每隔1秒画一个覆盖物小车,并且同时将上一个小车销毁,轨迹线条的话使用Polyline绘制。但是这样的绘制被用户提了意见,用户觉得我们的轨迹播放不够丝滑,总有一种一顿一顿的感觉。这种绘制方法网上到处都有,自己写也很简单,这里就不多说了。如果客户的要求不太高的话可以用。

二、基于算法的平滑移动

这里只是提供一种思路

其实动画的原理不就是很多张图片迅速变化吗?比如一开始出现的走马灯、动画片、电影。

卡顿的原因还是帧数太低了,那我们不要一秒绘制一次,这肯定是一顿一顿的,我们将两个轨迹点之间的空隙补全,然后以更高的频率绘制应该就可以了。这里可以搜一下平滑移动算法。理论上来说是可以实现的。

后来我看到百度地图有自带的方法,那还是不要自己写了。

三、百度地图自己的方法

这也是我推荐的。

3.1移动端平滑移动 SDK

安卓/IOS平滑移动 看了一下感觉挺丝滑的,而且车辆转弯时候角度变化啥的也很流畅。

image.png

3.2 JavaScript API GL 场景插件 轨迹

感觉网上用这个实现轨迹播放的文章几乎找不到,我来写一篇也挺有意义的呢。 可以参考 文档

image.png 不过这个应该只适合GL版本,其他版本的百度地图应该用不了。感觉效果还是挺好的。现在来实践一下。

还有一种是只有轨迹动画没有小车图标的,可以参考这个 教程

image.png

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();
},

运行了一下,感觉效果还行,我的图标随便从网上找的,其实应该放个俯视图,应该会更好。 image.png

3.2.3点击弹出窗体

点击小车图标可以看到返回数据 image.png 我们把小车当前的经纬度数据放到窗体里。把之前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);
 });

功能实现没啥问题 image.png