高德JS API2.0实现轨迹回放,支持进度条拖动播放

1,994 阅读3分钟

最近在做项目,有一个轨迹回放的需求,还得支持进度条拖动播放。轨迹播放的功能高德的文档示例都很完整清楚,但是进度条播放的功能,我网上找了很久,一直没找到适合我需求的实现。于是结合着网上搜索的资料和高德文档,基本实现了我的需求。正好做个记录,也可以让有相关需求的朋友作个参考。

20231031_174212.gif

    //初始化地图
    initMap() {
      this.map = new AMap.Map("container", {
        resizeEnable: true,
        center: this.lineArr[0],
        zoom: 18,
      });
      // 移动点
      this.marker = new AMap.Marker({
        map: this.map,
        position: this.lineArr[0],
        icon: this.locationIcon,
        offset: new AMap.Pixel(-20, -20),
      });
      // 起始点
      this.startMarker = new AMap.Marker({
        map: this.map,
        position: this.lineArr[0],
        icon: startIcon,
        offset: new AMap.Pixel(-20, -20),
      });
    },
    // 绘制轨迹
    initPloyLine() {
      this.polyline = new AMap.Polyline({
        map: this.map,
        path: this.lineArr,
        showDir: true,
        strokeColor: "#28F", //线颜色
        strokeWeight: 6, //线宽
      });
      const _this = this;
      // 监听轨迹移动
      this.marker.on("moving", function (e) {
          // 获取移动的点位索引 同步进度条
        const index = _this.lineArr.findIndex(
          (item) => item[2] === e.passedPos[2]
        );
        _this.sliderVal = Math.round(
          ((index + 1) / _this.lineArr.length) * 100
        );
        _this.passedPolyline.setPath([..._this.passedPath, ...e.passedPath]);// 把当前运动的轨迹和进度条拖动的轨迹拼接
        _this.map.setCenter(e.target.getPosition(), true);
      });
       // 监听轨迹移动结束,这个方法找了好久
      this.marker.on("movealong", function (e) {
        _this.stop();
      });
      this.map.setFitView();
    },
    getLine() {
      const _this = this;
      // JSAPI2.0 使用覆盖物动画必须先加载动画插件
      AMap.plugin("AMap.MoveAnimation", function () {
        _this.initMap();
        _this.initPloyLine();
      });
    },

以上轨迹基础部分也可直接参考高德 lbs.amap.com/demo/javasc…

开始播放

    start() {
      // 调用this.passedPolyline.destroy()后,已运行轨迹就被销毁了,所以每次开始都必须重新定义,否者再次运行就没这些配置的颜色了
      this.passedPolyline = new AMap.Polyline({
        map: this.map,
        strokeColor: "#AF5", //线颜色
        strokeWeight: 6, //线宽
      });
      this.marker.moveAlong(this.linePath, {
        // 每一段的时长
        duration: 500, //可根据实际采集时间间隔设置
        // JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
        autoRotation: true,
      });
      this.playStatus = 1;
    },

接下来是进度条拖动播放,也是我搞了最久的部分

    // 手动拖动滑块
    onUpdate(value) {
      if (this.playStatus === 1) { 
        this.pause(); // 如果是播放状态就先暂停,不是播放状态 暂停会导致后续无法播放
      }
      const index = Math.round((value / 100) * this.lineArr.length);
      this.marker.setPosition(this.lineArr[index]); // 进度条停止移动后,重新设置marker点位置
      this.linePath = this.lineArr.slice(index); // 拖动进度条后,接下来点位要运动的轨迹就不是整条了,要截取剩余的轨迹
      this.passedPath = this.lineArr.filter((item, ind) => index > ind);//已经拖动的部分也要保存,不然已经运动的轨迹无法改变颜色
      this.passedPolyline.setPath(this.passedPath); // 设置已经拖动的路线
      //this.start();
    },

最后轨迹运动结束调用stop(),把进度条、播放状态还原至初始状态。

    stop() {
      if (this.lineArr.length) {
        this.marker.stopMove();
        this.passedPolyline.destroy()
      }
      this.playStatus = 0;
      this.sliderVal = 0;
      this.passedPath = [];
      this.linePath = this.lineArr;
    },

以上就是我本次完成的轨迹回放功能,不过还是有不完善,比如:

  • 结束后我想清除轨迹回放,但是调用this.passedPolyline.setPath([]),并没起作用。 调用 this.passedPolyline.destroy()就可以清除已播放轨迹
  • 还有我在拖动滑块后就调用了start()方法,因为之后手动无法触发。 不要在非播放状态下使用暂停方法就可以解决

详细的方法基本都可以在文档找到高德文档找到

如果朋友们有更好的方法,欢迎讨论和指正。

第一次写文章记录,希望表达清楚了。感谢