uniapp实现动态轨迹回放

实现效果如下
在这里插入图片描述
代码如下

<!-- 轨迹回放 -->
<template>
	<view class="wrap" @tap="handleWrapTap">
		<map style="width: 100%; height: 100vh" id="myMap" :latitude="latitude" :longitude="longitude"
			:include-points="points" :polyline="polyline" :markers="markers"></map>
		<view class="tips">
			<view class="item tips_time">
				<!-- 月日 -->
				<text class="mr10">{{ tipsDate }}</text>
				<!-- 时分秒 -->
			</view>
			<!-- <view class="item tips_speed">{{`当前时速${spd}km/h`}}</view> -->
			<!-- <view class="item tips_mile">{{
        `已行驶${mlg > 0 ? mlg / 10 : 0}km`
      }}</view> -->
		</view>
		 <view class="bottom_wrap">
			<!-- <view class="header">
				<view class="license">{{ carInfo.license }}</view>
				<view @tap="handleChange" class="change">查看历史车辆</view>
			</view>
			<view class="flex">
				<view class="label">托运货物:</view>
				<view v-if="carInfo.goods.length" class="value">
					<text v-for="(item, index) in carInfo.goods" :key="index">{{ item.goods_name }}{{ item.goods_count
            }}{{ item.goods_unit }}</text>
				</view>
				<view class="value" v-else>暂无数据</view>
			</view> -->
			<view class="progress_wrap">
				<view class="flex">
					<view class="start">{{ carInfo.start_time }}</view>
					<view class="end">{{ carInfo.arrive_time }}</view>
				</view>

				<view class="progress">
					<view id="group" class="btn_group" v-if="showGroup">
						<image id="group1" @tap="speedMove" class="img speed mb20" mode="aspectFit"
							src="../../static/images/add-speed.png" />
						<image id="group2" @tap="reduceMove" class="img speed mb20" mode="aspectFit"
							src="../../static/images/reduce-speed.png" />
						<image id="group3" @tap="!startMove ? startMoveCar() : stopMove()" class="img" mode="aspectFit"
							:src="
                !startMove
                  ? '../../static/images/start-icon.png'
                  : '../../static/images/stop-icon.png'
              " />
					</view>
					<image id="image" @tap="handleStartMove" v-else class="img_start" mode="aspectFit" :src="
              !startMove
                ? '../../static/images/start-icon.png'
                : '../../static/images/stop-icon.png'
            " />
					<progress class="item" id="progress" @tap="handleTapProgress" @activeend="handleActiveEnd"
						@touchmove="handletouchmove" @touchstart="handletouchstart" @touchend="handletouchend"
						:active="false" active-mode="forwards" :percent="percent" stroke-width="16" duration="10" border-radius="10" activeColor="#5a7bee"/>
				</view>
			</view>
		</view>
		<tab-bar current="1" class="tabbar"></tab-bar>
	</view>
</template>
<script>
	/* import tabBar from "../components/tabBar";*/
	import common from "@/utils/common"; 
	export default {
		/* components: {
			tabBar,
		}, */
		data() {
			return {
				token:'',
				// 车辆所有数据
				carData: {
					//  路线点
					track: [],
				},
				carInfo: null,
				percent: 0,
				showGroup: false,
				// 搜索条件
				formData: {
					license: "",
					startTime: "",
					endTime: "",
				},
				// 中心经纬度
				latitude: "",
				longitude: "",
				//   标记点
				markers: [{}, {}, {}],
				posi: {
					latitude: 0,
					longitude: 0,
					iconPath: "../../static/images/car-icon.png",
					callout: {
						content: "", // 车牌信息
						display: "BYCLICK",
						fontWeight: "bold",
						color: "#5A7BEE", //文本颜色
						fontSize: "12px",
						bgColor: "#ffffff", //背景色
						padding: 5, //文本边缘留白
						textAlign: "center",
					},
					anchor: {
						x: 0.5,
						y: 0.6,
					},
					width: 40,
					height: 40,
					id: 9,
				},
				//   线数据
				polyline: [{
					points: [],
					color: "#3591fc",
					arrowLine: true, //带箭头的线
					width: 8,
				}, ],
				lineArr: [], // 所有轨迹点数组
				points: [],
				timer: null,
				width: "",
				startX: "",
				spd: 0,
				mlg: 0,
				gtm: "",
				tipsDate: null, // 日期提示
				wait: 50,
				wait2: 50,
				iNum: 0, // 当前运动点在所有轨迹点数组的下标
				startMove: false, // 开始移动
				mapContext: null,
				clientX_start: 0,
				clientX_end: 0,
				posi_x: 0,
			};
		},
		watch: {
			// 车辆当前时间点
			gtm: {
				handler() {
					if (this.gtm) {
						this.tipsDate = 
							this.carData.track.locationtime
					}
				},
				deep: true,
				immediate: true,
			},
		},
		methods: {
			handletouchmove(e) {
				this.startMove = false;
				let currentX = e.touches[0].pageX;
				let currentY = e.touches[0].pageY;
				let tx = currentX - this.lastX;
				let ty = currentY - this.lastY;
				let text = "";
				// this.mindex = -1;
				//左右方向滑动
				if (Math.abs(tx) > Math.abs(ty)) {
					if (tx < 0) {
						text = "向左滑动";
					} else if (tx > 0) {
						text = "向右滑动";
					}
				}
				//上下方向滑动
				else {
					if (ty < 0) {
						text = "向上滑动";
					} else if (ty > 0) {
						text = "向下滑动";
					}
				}

				//将当前坐标进行保存以进行下一次计算
				this.lastX = currentX;
				this.lastY = currentY;
				this.text = text;
				this.clientX_end = currentX;
			},
			handletouchstart(e) {
				this.clientX_start = e.touches[0].pageX;
			},
			handletouchend(e) {
				uni.showLoading({
					title: "加载中",
				});
				// 清楚定时器
				this.startMove = false;
				clearInterval(this.timer);
				this.timer = null;

				let endX = parseInt(e.detail.x);
				let x = parseInt(this.clientX_end - this.clientX_start);
				this.posi_x += parseInt(this.clientX_end - this.clientX_start);
				this.posi_x = this.posi_x > 0 ? this.posi_x : 0;
				// 点击进度条 设置进度
				this.percent =
					this.posi_x > 0 ? (this.posi_x / this.width).toFixed(2) * 100 : 0;
				// 获取当前进度节点对应的  经纬度数据
				let index =
					this.posi_x > 0 ?
					parseInt((this.posi_x / this.width) * this.lineArr.length) :
					0;
				index = index > this.lineArr.length ? this.lineArr.length - 1 : index;
				let posi = {
					...this.posi,
					latitude: this.lineArr[index].lat,
					longitude: this.lineArr[index].lon,
				};
				this.$set(this.markers, 1, posi);
				/* this.spd = this.lineArr[index].spd;
				this.mlg = this.lineArr[index].mlg;
				this.gtm = this.lineArr[index].gtm.split("/"); */
				this.iNum = parseInt(this.percent / (100 / this.lineArr.length));
				console.log(this.iNum, "num");
				setTimeout(function() {
					uni.hideLoading();
				}, 1000);
			},
			handleChange() {
				clearInterval(this.timer);
				uni.navigateTo({
					url: "/pages/car/carList",
				});
			},
			// 点击 控制标签(开始、加速、减速)以外的部分就隐藏控制标签
			handleWrapTap(e) {
				let arr = ["group", "group1", "group2", "group3", "image"];
				let isInclude = arr.includes(e.target.id);
				this.showGroup = isInclude;
			},
			// 点击进度条
			handleTapProgress(e) {
				console.log("进度条");
				// 清楚定时器
				this.startMove = false;
				clearInterval(this.timer);

				let endX = parseInt(e.detail.x);
				let x = endX - this.startX;
				// 点击进度条 设置进度
				this.percent = (x / this.width).toFixed(2) * 100;
				this.posi_x = this.percent * (this.width / 100);
				// 获取当前进度节点对应的  经纬度数据
				let index = parseInt((x / this.width) * this.lineArr.length);
				index = index > this.lineArr.length ? this.lineArr.length - 1 : index;
				let posi = {
					...this.posi,
					latitude: this.lineArr[index].lat,
					longitude: this.lineArr[index].lon,
				};
				this.$set(this.markers, 1, posi);
				/* this.spd = this.lineArr[index].spd;
				this.mlg = this.lineArr[index].mlg;
				this.gtm = this.lineArr[index].gtm.split("/"); */
				this.iNum = parseInt(this.percent / (100 / this.lineArr.length));
				// console.log(this.iNum, "num");
			},
			// 播放完毕
			handleActiveEnd(e) {
				console.log("播放完毕")
				this.stopMove();
			},
			// 点击开始图标
			handleStartMove() {
				this.showGroup = true;
				this.startMoveCar();
			},
			startMoveCar() {
				common.toast("开始播放");
				this.startMove = true;
				this.start();
			},
			// 暂停播放
			stopMove() {
				this.startMove = false;
				clearInterval(this.timer);
				common.toast("暂停播放");
			},
			// 加速播放
			speedMove() {
				if (this.wait2 / this.wait === 8) {
					common.toast(`当前播放速度为×8,以达到最大,无法再加速`);
				} else {
					clearInterval(this.timer);
					this.startMove = false;
					this.wait = this.wait / 2;
					common.toast(`当前播放速度为×${this.wait2 / this.wait}`);
					this.startMove = true;
					this.start();
				}
			},
			// 减速播放
			reduceMove() {
				if (this.wait2 / this.wait === 0.25) {
					common.toast(`当前播放速度为0.25,以达到最小,无法再减速`);
				} else {
					clearInterval(this.timer);
					this.startMove = false;

					this.wait = this.wait * 2;
					common.toast(`当前播放速度为×${this.wait2 / this.wait}`);
					this.startMove = true;
					this.start();
				}
			},
			// 开始播放
			start() {
				clearInterval(this.timer);
				this.timer = null;
				this.mapContext = uni.createMapContext("myMap", this);
				this.startMove ?
					(this.timer = setInterval(() => {
						this.startMove ?
							this.mapContext.translateMarker({
								markerId: 9,
								destination: {
									longitude: this.lineArr[this.iNum].lon,
									latitude: this.lineArr[this.iNum].lat,
								},
								//rotate: parseInt(this.lineArr[this.iNum].agl),
								autoRotate:true,
								duration: 200,
								animationEnd: function() {
									console.log("轨迹回放完成")
									this.tipsDate = this.lineArr[this.iNum].locationtime;
									this.percent = (100 / this.lineArr.length) * this.iNum;
									this.posi_x = this.percent * (this.width / 100);
									if (this.iNum === this.lineArr.length - 1) {
										this.percent = 100;
										clearInterval(this.timer);
									}
									this.iNum++;
									this.start();
								}.bind(this),
								fail(e) {
									console.log("轨迹回放失败")
								},
							}) :
							"";
						clearInterval(this.timer);
					}, this.wait)) :
					"";
			},
			// 设置 标记点
			setMarkers() {
				this.$set(this.posi, "latitude", this.lineArr[0].lat);
				this.$set(this.posi, "longitude", this.lineArr[0].lon);
				this.points = [];
				this.lineArr.forEach((v) => {
					this.points.push({
						latitude: v.lat,
						longitude: v.lon,
					});
				});
				this.markers = [{
						latitude: this.lineArr[0].lat,
						longitude: this.lineArr[0].lon,
						iconPath: "../../static/images/begin.png",
						width: 21,
						height: 21,
						id: 8,
					},
					{
						...this.posi,
					},
					{
						latitude: this.lineArr[this.lineArr.length - 1].lat,
						longitude: this.lineArr[this.lineArr.length - 1].lon,
						iconPath: "../../static/images/end.png",
						width: 21,
						height: 21,
						id: 10,
					},
				];
				console.log("setMarkers"+this.markers+JSON.stringify(this.markers))
			},
			// 设置  路线
			setPolyline() {
				let obj = {};
				this.lineArr.forEach((line) => {
					this.polyline[0].points.push({
						longitude: line.lon,
						latitude: line.lat,
					});
				});
				console.log("pppppppppp"+JSON.stringify(this.polyline))
			},
			getGuiji() {
				var imei = '86478404274139';
				var date = '2021-09-07';
				uni.request({
					url: this.apiServier + "/findSportLocusByDate?imei=" + imei + "&date=" +
						date,
					method: 'GET',
					header: {
						'token': this.token,
					},
					success: (res) => {
						console.log("rrrrrrrrr" + JSON.stringify(res));
						if (res.data.code === 20000) {
							uni.showToast({
								title: '查询成功'
							})
							var data2 = res.data.data;
							this.carData.track = data2;
							console.log("this.carData.track" + JSON.stringify(this.carData.track));
							this.latitude = data2[0].lat;
							this.longitude = data2[0].lon;
							this.tipsDate = data2[0].locationtime;
							this.getData();
						}
			
						if (res.data.code === 50000) {
							uni.showToast({
								title: '该日期暂无轨迹'
							})
						}
					},
					fail: (res) => {
						uni.showToast({
							title: '服务器错误'
						})
					}
				})
			},
			// 获取车辆轨迹数据
			getData(data) {
				// 获取后台数据
				this.lineArr = this.carData.track;
				console.log("aaaaaaaaaaaaa"+this.lineArr);
				// 设置车牌号
				// 设置初始标记点 起点 终点
				this.setMarkers();
				this.setPolyline();
			},
		},
		mounted() {
			// 获取progress进度条的长度
			const query = uni.createSelectorQuery().in(this);
			query
				.select("#progress")
				.boundingClientRect((data) => {
					this.width = data.width;
					this.startX = data.left;
				})
				.exec();
		},
		onLoad(query) {
			this.token = uni.getStorageSync("token");
			this.getGuiji();
		},
	};
</script>
<style lang="scss" scoped>
	.tips {
		position: absolute;
		top: 20%;
		left: 30rpx;

		.mr10 {
			margin-right: 10rpx;
		}

		.item {
			//height: 50rpx;
			width: 255rpx;
			background: #ffffff;
			border-radius: 50rpx;
			margin-bottom: 20rpx;
			font-weight: bold;
			font-size: 26rpx;
			line-height: 50rpx;
			text-align: center;
			color: #5a7bee;
		}
	}

	.bottom_wrap {
		position: absolute;
		bottom: 168rpx;
		width: 100%;
		background: #fff;
		padding: 30rpx;
		box-sizing: border-box;

		.header {
			display: flex;
			justify-content: space-between;

			.license {
				font-weight: bold;
				font-size: 34rpx;
				line-height: 48rpx;
				color: #000000;
			}

			.change {
				font-size: 34rpx;
				line-height: 48rpx;
				color: #5a7bee;
			}
		}

		.flex {
			display: flex;
			font-size: 24rpx;
			line-height: 34rpx;
			color: #888888;
		}

		.progress_wrap {
			//margin: 30rpx 0 40rpx;
			position: relative;
			top:0;
			.flex {
				display: flex;
				justify-content: space-between;
				font-weight: bold;
				font-size: 24px;
				line-height: 34px;
				padding-left: 100rpx;
				color: #000000;
			}

			.progress {
				display: flex;
				position: relative;
				padding-left: 100rpx;

				.img_start {
					width: 56rpx;
					height: 56rpx;
					position: absolute;
					left: 0;
					bottom: -10rpx;
				}

				.btn_group {
					display: flex;
					flex-direction: column;
					align-items: center;
					position: absolute;
					left: 0;
					bottom: -20rpx;

					padding: 20rpx 10rpx;
					background: #ffffff;
					box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.25);
					border-radius: 50rpx;

					.img {
						width: 56rpx;
						height: 56rpx;
						// margin-bottom: 40rpx;
					}

					.mb20 {
						margin-bottom: 40rpx;
					}

					.speed {
						width: 43rpx;
						height: 36rpx;
					}
				}
			}
		}

		.bottom {
			display: flex;

			.average_speed {
				display: flex;
				flex-direction: column;
				justify-content: space-between;
				width: 33.3%;

				.value {
					width: 100%;
					text-align: center;
					font-weight: bold;
					font-size: 34rpx;
					line-height: 48rpx;
					color: #5a7bee;
				}

				.label {
					width: 100%;
					text-align: center;
					font-weight: normal;
					font-size: 26rpx;
					line-height: 36rpx;
					color: #000000;
				}
			}
		}
	}
</style>

  • 4
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
实现车辆轨迹回放,可以使用uniapp的map组件。以下是步骤: 1.引入map组件: 在页面的vue文件里,先引入map组件。如下: ``` <template> <view> <map :show-location="true" :markers="markers"></map> </view> </template> <script> import {uniMap} from '@dcloudio/uni-ui'; export default { components: { uniMap }, data(){ return { markers: [] } } } </script> ``` 2.设置地图样式: 在页面的style里,设置map组件的高度和宽度 ``` <style> map { width: 100%; height: 100%; position: fixed; top: 0; left: 0; z-index: 999; } </style> ``` 3.加载地图: 在mounted钩子函数里调用uniMap的createMap方法,创建地图 ``` mounted(){ this.createMap(); }, methods: { createMap(){ let mapCtx = uniMap.createMapContext('myMap', { showLocation: true }) mapCtx.moveToLocation(); } } ``` 4.显示轨迹: 使用setMarkers方法,将要显示的轨迹点添加到地图上 ``` let markers = [ { id: 1, longitude: 113.324520, latitude: 23.10229, iconPath: '/static/img/car.png', width: 50, height: 50, callout: { content: '起点' } }, { id: 2, longitude: 113.35938, latitude: 23.09211, iconPath: '/static/img/car.png', width: 50, height: 50, callout: { content: '终点' } }, { id: 3, longitude: 113.331441, latitude: 23.117706, iconPath: '/static/img/car.png', width: 50, height: 50, callout: { content: '中间点' } } ] this.markers = markers; ``` 5.轨迹回放: 使用定时器和moveToLocation方法,按照轨迹点顺序将地图移动到对应的位置 ``` play(){ let mapCtx = uniMap.createMapContext('myMap', { showLocation: true }) let i = 0; let len = markers.length; let timer = setInterval(() => { if(i >= len - 1){ clearInterval(timer); return; } i++; mapCtx.moveToLocation({ longitude: markers[i].longitude, latitude: markers[i].latitude }) }, 1000) } ``` 以上就是实现车辆轨迹回放的步骤。需要注意的是,地图的显示需要设置高度和宽度,因为地图是一个fixed定位的元素。另外,回放轨迹时需要使用定时器来控制地图移动的速度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值