uniapp map地图实现轨迹回放功能(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>
本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高桥留

打赏更新更快!质量更好!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值