vue+高德地图实现轨迹回放并实现播放进度条/倍数/时间

逻辑漫游
• 阅读 11902

需求:
1:轨迹回放:播放,暂停,继续播放
2:进度条,轨迹回放,进度条也要播放,轨迹停止播放,进度条也要暂停。
3:倍数:未播放选择倍数,正在播放选择倍数,暂停选择倍数。
4:播放时间

高德api示例里面只有需求一最简单的播放,暂停,继续播放。
所以要根据高德地图参考手册给出的现有的类与方法进行实现功能

废话不多说。

1:引入高德地图

<script
      type="text/javascript"
      src="https://webapi.amap.com/maps?v=1.4.0&key=你的key*&plugin=AMap.Autocomplete"
    >
</script>

模版

<template>
  <div>
   // map
    <div id="container"></div>
    // 倍数
    <div class="speed">
      <span
        :class="{multiple: true, milActive: muiltipleIndex == index}"
        v-for="(item,index)  in speedList"
        @click="selectMultiple(index, item)"
      >{{item}}X</span>
      <span class="bs_title">倍数播放</span>
    </div>
    
    <div class="input-card">
      <div class="plar-cnp">
      // 进度条
        <van-slider
          class="slider-i"
          v-model="value"
          @change="onChange"
          :button-size="15"
          :step="step"
        />
        // 时间
        <span class="progress_time">{{progressTime}}</span>
        // 播放,暂停,继续按钮
        <div class="p_icon">
          <van-icon v-if="palyStayus == 0" @click="startAnimation(0, [])" name="play-circle-o" />
          <van-icon v-if="palyStayus == 1" @click="pauseAnimation()" name="pause-circle-o" />
          <van-icon v-if="palyStayus == 2" @click="resumeAnimation()" name="play-circle-o" />
        </div>
      </div>
  </div>
</template>

变量

let TIME_VARIABLE;




data() {
    return {
      progressTime: 0,  // 时间
      palyStayus: 0, //0->未开始  1->行驶中  2->暂停
      value: 0,  // 进度条初始化
      speedList: [1, 2, 3, 4, 5], // 倍数数据
      markerSpeed: 100, // 初始化速度
      marker: null, // 标记点
      lineArr: [], // 轨迹点数组
      passedPolyline: null, 
      positionIndex: [], //轨迹起始点--车辆所在的位置
      speedCount: 1, // 目前选择的倍数
      passedPath: 0, // 存放(播放时点击倍数)抓取到的位置
      int: null, // 定时器--进度条
      timeInt: null // 定时器--时间
      curreGDPath: null,  //存放(播放时点击倍数)抓取到的经纬度
      polyline: null, // 轨迹线路
      map: null //map地图
    };
  },

2:获取数据(这一步就不写了,数据数量字段简化了一下)

this.lineArr = [
{"gpsTime":"2020-02-06 14:37:56","longitude":109.07048","latitude":34.405327},

{"gpsTime":"2020-02-06 14:37:58","longitude":109.07059,"latitude":34.4055,},

{"gpsTime":"2020-02-06 14:38:00","longitude":109.07078,"latitude":34.40565},

{"gpsTime":"2020-02-06 14:38:02","longitude":109.07087,"latitude":34.405704},

{"gpsTime":"2020-02-06 14:38:06","longitude":109.07122,"latitude":34.40582},

{"gpsTime":"2020-02-06 14:38:07","longitude":109.0714,"latitude":34.405876},]

// 备份一组原始数据,后面初始化要用
this.standLineArr = this.lineArr

显示地图(数据请求到之后就回调显示地图)

this.map = new AMap.Map("container", {
    center: [116.478935, 39.997761],
    zoom: 20
});
this.marker = new AMap.Marker({
    map: this.map,
    //轨迹点的第一个点
    //this.positionIndex = new AMap.LngLat(
        //this.lineArr[0].longitude,
        //this.lineArr[0].latitude
    //);
    position: this.positionIndex, 
    icon: new AMap.Icon({
      size: new AMap.Size(40, 40), // 图标尺寸
      image: huoche, //绝对路径
      imageSize: new AMap.Size(40, 40)
    }),
    offset: new AMap.Pixel(-26, -13),
    autoRotation: true,
    angle: 90
 });
 // 初始化回放路线
 this.initPolyline();
 
 // 关键---获取轨迹点播放完所需要的时间(单位:s)
 //this.polyline.getLength()/1000 ---是总路程(km)
 //this.markerSpeed * this.speedCount --- 速度
 TIME_VARIABLE =
        (this.polyline.getLength() /
          1000 /
          (this.markerSpeed * this.speedCount)) *
        60 *
        60; //行驶时间(s)
 
 this.marker.on("moving", e => {
    this.passedPolyline.setPath(e.passedPath);
 });
 
 this.map.setFitView();
 
 
// 这里面的都是高德解析出更细致的经纬度点
 AMap.event.addListener(this.marker, "moving", e => {
    // console.log("当前已回放: " + e.passedPath);
    //这里是关键,车辆播放的时候,走的每一个点进行抓取(高德解析的更细致的点)以便更新倍数时及时的更新未走完的数据,后面会用到
    this.curreGDPath = new AMap.LngLat(
      e.passedPath[e.passedPath.length - 1].lng,
      e.passedPath[e.passedPath.length - 1].lat
    );
    // 行走到具体的第几个点
    this.passedPath = e.passedPath.length;
 });
      
 
 

播放结束后回调---初始化变量

 // 播放结束后回调--初始化各类数据
 this.marker.on("movealong", e => {
    this.palyStayus = 0; //播放/暂停按钮显示状态的改变
    this.speedCount = 1; // 播放倍数初始化为1
    this.markerSpeed = 100; // 播放速度初始化为100
    // 取消定时器(时间,进度条)
    clearInterval(this.int); 
    clearInterval(this.timeInt);
    this.lineArr = this.standLineArr;  // 数据初始化
    this.initPolyline(); // 数据再次更新到线条上。
  });

初始化回放路线

    // 初始化回放路线
    initPolyline() {
      this.polyline = new AMap.Polyline({
        map: this.map,
        path: this.lineArr,
        showDir: true,
        strokeColor: "#28F", //线颜色
        strokeWeight: 6 //线宽
      });
      this.passedPolyline = new AMap.Polyline({
        map: this.map,
        strokeColor: "#AF5", //线颜色
        strokeWeight: 6 //线宽
      });
    },
    

点击开始播放按钮

    startAnimation(status, arr) {
      //速度 = 初始速度 * 倍数
      let markerSpeed = this.markerSpeed * this.speedCount;
      
      if (status == 0) {
        // 初始时间为00:00
        this.progressTime = formatSeconds(0); 
        this.value = 0; // 进度条归0
        this.palyStayus = 1; // icon状态为播放
        arr = this.lineArr; 
        //计时器--- 开始监听时间和进度条
        this.monitorInterval(); 
      }
      // 还是播放---请查看高德地图api
      this.marker.moveAlong(arr, markerSpeed);
    },
    
    formatSeconds(value) {
        var secondTime = parseInt(value);// 秒
        var minuteTime = 0;// 分
        var hourTime = 0;// 小时
        if(secondTime > 60) {
            minuteTime = parseInt(secondTime / 60);
            secondTime = parseInt(secondTime % 60);
            if(minuteTime > 60) {
                hourTime = parseInt(minuteTime / 60);
                minuteTime = parseInt(minuteTime % 60);
            }
        }
        var result = parseInt(secondTime)< 10?("0" + parseInt(secondTime)): ("" + parseInt(secondTime));
        result =parseInt(minuteTime)< 10?("0" + parseInt(minuteTime))+ ":" + result : ("" + parseInt(minuteTime)) + ":" + result;
        return result;
    }

    

监听进度条和时间

monitorInterval() {
  // 进度条
  当(TIME_VARIABLE / 100) * 1000时间 每循环一次 进度条走一个倍数,等播放完进度条也刚好走完
  this.int = setInterval(() => {
    this.value += 1 * this.speedCount;
  }, (TIME_VARIABLE / 100) * 1000);
  
  // 时间
  this.timeInt = setInterval(() => {
    this.ptm += 1;
    this.progressTime = formatSeconds(this.ptm);
  }, 1000);
},

点击倍数

selectMultiple(e, data) {
  this.muiltipleIndex = e;
  this.speedCount = data; //倍数
  // 如果正在行驶中点击倍数
  if (this.palyStayus == 1) { 
    this.marker.pauseMove(); // 先暂停车
    // 截取到车辆未走的经纬度数组
    this.lineArr = this.lineArr.slice(this.passedPath); 
    
    //并把暂停住车辆时,车辆正好所在的经纬度拼接到未走的经纬度数组里面-------当前未回放的经纬度
    //this.curreGDPath这个很关键--在前面的代码中有交代
    //this.lineArr现在这个数据截取到了点击倍数时未走的路程
    this.lineArr.unshift(this.curreGDPath);
    //并把this.lineArr更新到线条里面,,要不线条颜色不同步
    this.initPolyline();
    // 刚才暂停了一下,就要再次开启播放
    this.startAnimation(1, this.lineArr);
  }
},

暂停。继续。停止

 // 暂停
pauseAnimation() {
  this.palyStayus = 2; // icon状态为2
  // 停止计时器
  clearInterval(this.int); 
  clearInterval(this.timeInt);
  this.marker.pauseMove();
},
// 继续
resumeAnimation() {
  this.palyStayus = 1;  // icon状态为2
  this.monitorInterval();
  this.marker.resumeMove();
},
// 停止
stopAnimation() {
  this.marker.stopMove();
},
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Easter79 Easter79
3年前
vue video全屏播放
需求:1、视频为长方形,页面初始化打开为横屏全屏播放视频。2、微信不支持自动播放,故自动播放需求删除。方法:1、vuevideoplayer插件因需求较简单,仅要求播放本地一个视频,故未选择使用插件。2、video<divid"video_box"style"zindex:999;":cl
Stella981 Stella981
3年前
Javascript判断Video视频播放、暂停、结束完成及获取长度事件监听处理
在日常应用场景中,可能会遇到这么一个情况,需要判断用户是否完整的观看完了一部视频,在这个场景中,和视频相关的事件大体涉及到几个部分,获取视频长度,视频开始播放,暂停播放和播放结束,下面来看下如何通过JavaScript来监听获取视频的这几种状态。html页面视频标签大体如下:<video id\"video" controls\"controls
Stella981 Stella981
3年前
React Native (一) react
ReactNative(一)reactnativevideo实现音乐播放器和进度条的功能功能:1.卡片滑动切歌2.显示进度条效果图:!(https://oscimg.oschina.net/oscnet/3c
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Stella981 Stella981
3年前
Android上定义播放器控件UniversalVideoView
在Android上播放视频最简单的方法是使用SDK中内置的VideoView,然后加上MediaController来控制视频播放暂停等,但是这样有一个缺点是无法定制自己的控制UI,所以这里提供一个自定义播放控件,它可以设置多种自定义属性(如loading样式,错误视频等),并且很容易在全屏与非全屏之间切换,另外支持AndroidV2.3及以上系统.
Wesley13 Wesley13
3年前
videojs在实时流的情况下暂停和播放
1.问题是videojs在实时流(live)的情况下暂停然后不能再次播放2.单击播放区只能暂停不能再次播放vartechClickfalse;$("localVideo.vjsbutton").on("click",function(){/if($('div').is(