如何在Uniapp map中实现地图轨迹回放功能

19人浏览 / 0人评论 / 添加收藏

最近做了一个项目,在Uniapp项目中需要实现地图的轨迹以及轨迹回放的功能,通过translateMarker和moveAlong两种实现方式。

话不多说,直接上代码:

<template>
<view>
 <map id="map" :style="{ width: screenWidth + 'px',height: mapHeight+ 'px' }" :latitude="center.latitude"
  :longitude="center.longitude" :polyline="polyline" :markers="markers" scale="16" :show-location="true">
 </map>
</view>
</template>
<script>
export default {
 data() {
  return {
   mapHeight: uni.getSystemInfoSync().windowHeight * 0.9,
   screenWidth:uni.getSystemInfoSync().windowWidth,
   center: {
    latitude: 39.90469, longitude: 116.40717,
   },
   //轨迹数据
   trackPoints: [
     {
      latitude: 39.90469,
      longitude: 116.40717
     },
     {
      latitude: 39.90569,
      longitude: 116.40817
     },
     {
      latitude: 39.90669,
      longitude: 116.40917
     },
     {
      latitude: 39.90769,
      longitude: 116.41017
     },
     {
      latitude: 39.90869,
      longitude: 116.41117
     }
   ],
   polyline: [],
   markers: [{
    id: 1,
    latitude: 39.90469,
    longitude: 116.40717,
    iconPath: '/static/startIcon.png',
    width: 30,
    height: 30,
    rotate: 0
   }],
   mapContext: null,
   isPlaying: false,
   currentIndex: 0,
   speed: 5,
   animationDuration: 2000,
   currentProgress: 0
  }
 },
 onLoad() {
  
 },
 onReady() {
  this.initMap();
 },
 methods: {
  // ****地图方法****
  initMap() {
   // #ifdef MP-WEIXIN
   this.mapContext = wx.createMapContext('map', this);
   // #endif
   // #ifdef APP-PLUS
   this.mapContext = uni.createMapContext('map', this);
   // #endif

   // 设置轨迹线
   this.polyline = [{
    points: this.trackPoints,
    color: '#0091FF',
    width: 6,
    arrowLine: true
   }];
   // 轨迹回放-translateMarker(带自动旋转等功能)
   this.togglePlay()
   // 轨迹回放-moveAlong
   // this.moveMaker()
  },
  
  moveMaker(){
   this.mapContext.moveAlong({
    markerId: 1,
    path: this.trackPoints,
    autoRotate: true, // 标记点是否自动旋转
    duration: 10000, // 动画持续时间,单位ms
    success: () => {
     console.log('轨迹回放完成');
    }
   });
   // 调整地图视野以包含整个轨迹
   this.mapContext.includePoints({
    points: this.trackPoints,
    padding: [50, 50, 50, 50]
   });
  },
  
  // 开始/暂停动画
  togglePlay() {
   if (this.isPlaying) {
    this.pauseAnimation();
   } else {
    this.startAnimation();
   }
  },

  // 开始动画
  startAnimation() {
   if (this.currentIndex >= this.trackPoints.length - 1) {
    this.currentIndex = 0;
   }

   this.isPlaying = true;
   this.moveToNextPoint();
  },

  // 暂停动画
  pauseAnimation() {
   this.isPlaying = false;
   // #ifdef MP-WEIXIN || APP-PLUS
   this.mapContext.stopTranslateMarker();
   // #endif
  },

  // 重置动画
  resetPlay() {
   this.pauseAnimation();
   this.currentIndex = 0;
   this.currentProgress = 0;

   const firstPoint = this.trackPoints[0];
   this.markers[0].latitude = firstPoint.latitude;
   this.markers[0].longitude = firstPoint.longitude;
   this.center = {
    ...firstPoint
   };
   this.markers = [...this.markers];
  },

  // 移动到下一个点
  moveToNextPoint() {
   if (!this.isPlaying || this.currentIndex >= this.trackPoints.length - 1) {
    this.isPlaying = false;
    return;
   }

   const fromPoint = this.trackPoints[this.currentIndex];
   const toPoint = this.trackPoints[this.currentIndex + 1];

   // 计算动画持续时间(基于距离和速度)
   const distance = this.calculateDistance(fromPoint, toPoint);
   const duration = Math.max(500, Math.min(3000, distance * 1000 / this.speed));

   // 计算方向角度
   const rotate = this.calculateRotate(fromPoint, toPoint);

   // #ifdef MP-WEIXIN || APP-PLUS
   this.mapContext.translateMarker({
    markerId: 1,
    destination: {
     latitude: toPoint.latitude,
     longitude: toPoint.longitude
    },
    autoRotate: true,
    rotate: rotate,
    duration: duration,
    animationEnd: () => {
     this.currentIndex++;
     this.currentProgress = Math.round(
      (this.currentIndex / (this.trackPoints.length - 1)) * 100
     );
     this.moveToNextPoint();
    }
   });
   // #endif

   // 更新中心点
   this.center = {
    latitude: (fromPoint.latitude + toPoint.latitude) / 2,
    longitude: (fromPoint.longitude + toPoint.longitude) / 2
   };
  },

  // 计算两点间距离
  calculateDistance(point1, point2) {
   const R = 6371000; // 地球半径(米)
   const dLat = (point2.latitude - point1.latitude) * Math.PI / 180;
   const dLng = (point2.longitude - point1.longitude) * Math.PI / 180;
   const a =
    Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(point1.latitude * Math.PI / 180) *
    Math.cos(point2.latitude * Math.PI / 180) *
    Math.sin(dLng / 2) * Math.sin(dLng / 2);
   const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
   return R * c;
  },

  // 计算方向角度
  calculateRotate(fromPoint, toPoint) {
   const dx = toPoint.longitude - fromPoint.longitude;
   const dy = toPoint.latitude - fromPoint.latitude;
   return Math.atan2(dy, dx) * 180 / Math.PI;
  },
  // ****地图方法end****
 }
}
</script>
以上代码实测有效,希望对你能有所启发。

全部评论