最近做了一个项目,在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>
以上代码实测有效,希望对你能有所启发。
微信扫码加好友
全部评论