轨迹记录-小程序地图移动

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

<!-- 轨迹记录 -->
<template>
	<view class="warp" :class="{'active_warp': activeMap}">
		<view class="back_top" :class="{'activ_top': activeMap}" @click="showMap(false)"><view class=""> 返回计时页面 </view></view>
		<view>
			<view class="ybp_wrap" id="main">
				<view class="gl_num">{{distance || `0.00`}}</view>
				<view class="gl_title">公里</view>
			</view>
			<view class="center_wrap">
				<view class="center_item">
					<view class="item_top">{{currentObj.speed || '0'}}</view>
					<view class="item_bottom">速度m/s</view>
				</view>
				<view class="center_item">
					<view class="item_top">{{startJsObj.currentTime}}</view>
					<view class="item_bottom">用时</view>
				</view>
				<view class="center_item">
					<view class="item_top">{{currentObj.accuracy || 0}}</view>
					<view class="item_bottom">精确度</view>
				</view>
			</view>
			<view class="footer">
				<view class="btn_wrap up" :animation="animationData1">
					<view class="btn stop_btn" @click="stopClick" >
						<u-icon size="40" name="pause" style="font-weight: 700;"></u-icon>
						<view class="">暂停</view>
					</view>
				</view>
				<view class="btn_wrap down" :animation="animationData2">
					<view class="btn start_btn"  @click="startLocation('qian','start')"><u-icon size="40" name="play-right-fill" style="color: #fff;"></u-icon></view>
					<view class="btn end_btn" @click="endClick"><view style="width: 40rpx;height: 40rpx;border-radius: 4rpx; background:#fff"></view></view>
				</view>
				<view class="map"><u-icon name="map" size="60" @click="showMap(true)" color="white"></u-icon></view>
			</view>
		</view>
		<!-- //倒计时遮罩 -->
		<view class="before_start_mask" v-if="DJSShow">
			<view class="djs_content" v-if="DJSMsg == 3" :class="{actived: true}" :animation="animationData">3</view>
			<view class="djs_content" v-if="DJSMsg == 2" :class="{actived: true}" :animation="animationData">2</view>
			<view class="djs_content" v-if="DJSMsg == 1" :class="{actived: true}" :animation="animationData">1</view>
			<view class="djs_content" style="opacity: 1;" v-if="DJSMsg == 'GO'">GO</view>
			<!-- <view class="djs_content" :class="{actived: true}"  :animation="animationData">
				{{DJSMsg}}
			</view> -->
		</view>
	</view>
</template>

<script>
	import { getShow, addShow, updateShow } from "@/common/api/table";
	import { getDictionary } from "@/common/api/system.js";
	import { mapGetters } from "vuex";
	import { authorizedPositioning } from '@/common/util/localtion.js';
	import { getLocationPermiss,getLocationBackgroundPermiss } from '@/common/util/verifyPermiss.js';
	export default {
		name: "lsd-gjjl",
		components: {},
		data() {
			return {
				activeMap: false,
				instanceAnimation:null,//动画实例
				animationData:{},
				animationData1:{},
				animationData2:{},
				DJSShow: true,
				DJSTimer: null, //倒计时遮罩
				DJSMsg: '',
				echarts: null,
				chartData: {},
				startJsObj: {
					timestamp: 0, //时间戳
					currentTime: '00:00:00',
					timer: null
				},
				stepList: [],
				currentObj: {
					latitude: '',
					longitude: '',
					speed: '',
					accuracy: '',
				},
				distance: 0.00,//运动距离
			};
		},
		watch: {
			'startJsObj.timestamp': {
				handler(newValue, oldValue) {
					this.startJsObj.currentTime = this.formateTime(newValue)
				}
			}
		},
		methods: {
			showMap(flag) {
				console.log(flag)
				this.$emit('uploadPosition', {stepList: this.stepList, flag: flag})
				this.activeMap = flag
			},
			//点击暂停
			stopClick() {
				console.log('点击暂停')
				wx.stopLocationUpdate({
					success: () => {
						//动画
						this.instanceAnimation.scale(1.5,1.5).scale(0,0).step()
						this.animationData1 = this.instanceAnimation.export()
						this.instanceAnimation.scale(0,0).scale(1.5,1.5).scale(1,1).step()
						this.animationData2 = this.instanceAnimation.export()
						//时间暂停
						clearInterval(this.startJsObj.timer)
						this.startJsObj.timer = null
					},
					fail: (err) => {console.log('暂停失败',err)}
				})
				
			},
			//结束点击
			endClick() {
				uni.showModal({
					title: `确定结束本次轨迹记录吗?`,
					content: '',
					confirmText: "结束",
					cancelText: "继续记录",
					success: async function(res) {
						if (res.confirm) {
							this.backPage()
						}
					},
					fail(err) { }
				})
			},
			//返回上一页
			backPage() {uni.navigateBack({ delta: 1 })},
			//初始化倒计时
			initDJS() {
				this.DJSMsg = 3
				this.DJSTimer = setInterval(() => {
					if (this.DJSMsg == 1) {
						this.DJSMsg = 'GO'
					} else if (this.DJSMsg == 'GO') {
						this.DJSShow = false
						clearInterval(this.DJSTimer)
						this.startLocation('qian')
						this.DJSTimer = null
					} else {
						this.DJSMsg = this.DJSMsg - 1
					}
				}, 1000)
			},
			//格式化时间戳为时间
			formateTime(time) {
				const h = parseInt(time / 3600)
				const minute = parseInt(time / 60 % 60)
				const second = Math.ceil(time % 60)

				const hours = h < 10 ? '0' + h : h
				const formatSecond = second > 59 ? 59 : second
				return `${hours > 0 ? `${hours}` : '00'}:${minute < 10 ? '0' + minute : minute}:${formatSecond < 10 ? '0' + formatSecond : formatSecond}`
			},
			//开始记时
			startJS() {
				this.startJsObj.timer = setInterval(() => {
					this.startJsObj.timestamp = this.startJsObj.timestamp + 1
				}, 1000)
			},
			//初始化动画
			initAnimation() {
				this.instanceAnimation = uni.createAnimation({
					duration: 500,
					timingFunction: 'ease',
				})
				// this.instanceAnimation.opacity(0).opacity(1).opacity(0).step()
				// this.animationData = this.instanceAnimation.export()
			},
			//校验获取定位前悬是否开启
			async verifyPermiss() {
				// console.log(await getLocationPermiss(),'await getLocationPermiss()')
				// let flag = false
				if(await getLocationBackgroundPermiss()) {//未授权--返回上一页,已授权,进入倒计时
					
					this.initDJS()
				}else{
					uni.navigateBack({ delta: 1 });
				}
			},
			
			
			//开始位置变化-前台
			startLocation(flag, type) {
				// if(flag == 'qian') {
				// 	wx.startLocationUpdate({
				// 		success: (res) => {
				// 			console.log('开启-前台-时接收位置消息:', res)
				// 			this.startDataCl(flag, type, res)
				// 		},
				// 		fail: (res) => {
				// 			console.log('开启前台时接收位置失败:', res)
				// 		}
				// 	})
				// } else if(flag == 'hou') {
					wx.startLocationUpdateBackground({
						success: (res) => {
							console.log('开启-后台-时接收位置消息:', res)
							this.startDataCl(flag, type, res)
						},
						fail: (res) => {
							console.log('开启-后台-时接收位置失败:', res)
						}
					})
				// }
				
			},
			//开始位置
			startDataCl(flag, type, res) {
				if(type == 'start') {
					this.instanceAnimation.scale(1.5,1.5).scale(0,0).step()
					this.animationData2 = this.instanceAnimation.export()
					this.instanceAnimation.scale(1.5,1.5).scale(1,1).step()
					this.animationData1 = this.instanceAnimation.export()
				}else {
					this.listenChange()
				}
				this.startJS()
			},
			//监听位置变化信息
			listenChange() {
				wx.onLocationChange(res => {
					let obj = {
						latitude: res.latitude, //纬度,范围为 -90~90,
						longitude: res.longitude, //经度,范围为 -180~180,
						speed: res.speed, //速度,单位 m/s
						accuracy: res.accuracy, //位置的精确度
					}
					this.stepList.push(obj)
					this.currentObj = obj
					this.calcDistance()
					this.$emit('uploadCurrentPoint',obj)
					console.log('监听位置变化', res, res.latitude, res.longitude);
				});
			},
			//计算运动距离
			calcDistance() {
				if(this.stepList.length >= 2) {
					let last = this.stepList[this.stepList.length -1 ]
					let next = this.stepList[this.stepList.length -2 ]
					let distance = this.GetDistance(last.latitude,last.longitude,next.latitude,next.longitude,)
					this.distance = parseFloat(this.distance) +  parseFloat(distance)
				}
			},
			Rad(d){
				return d * Math.PI / 180.0;//经纬度转换成三角函数中度分表形式。
			},
			GetDistance(lat1,lng1,lat2,lng2){
			  var radLat1 = this.Rad(lat1);
			  var radLat2 = this.Rad(lat2);
			  var a = radLat1 - radLat2;
			  var  b = this.Rad(lng1) - this.Rad(lng2);
			  var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
			  Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
			  s = s *6378.137 ;// EARTH_RADIUS;
			  s = Math.round(s * 10000) / 10000; //输出为公里
			  s=s.toFixed(2);
				console.log('两点之间的距离:',s)
			  return s;
			}
		},
		mounted() {
			console.log('112233')
			this.verifyPermiss()//校验权限
			this.initAnimation()//控制全局渐变
		},
	}
</script>

<style lang="scss">
	.warp {
		width: 100%;
		height: 100vh;
		background-color: #584f60;
		transition: .5s;
		&.active_warp{
			height: 10vh;
			overflow: hidden;
		}
		.back_top{
			height: 0;
			display: flex;
			justify-content: center;
			align-items: center;
			color: white;
			overflow: hidden;
			// display: none;
			transition: .5s;
			color: white;
			&.activ_top{
				height: 10vh;
				// display: flex;
			}
		}
	}

	.before_start_mask {
		position: fixed;
		width: 100%;
		height: 100vh;
		left: 0%;
		top: 0;
		background-color: black;
		z-index: 10086;
		display: flex;
		justify-content: center;
		align-items: center;
		margin-bottom: 200rpx;
		.djs_content {
			transform: translateY(-180rpx);
			color: white;
			font-size: 180rpx;
			font-weight: 700;
			opacity: 0;
			font-family: 'Times New Roman', Times, serif;
			&.actived {
				animation: myfirst 1s infinite;
			}
		}

	}

	.ybp_wrap {
		width: 100%;
		height: 300px;
		color: rgba(255, 255, 255, 1);
		animation: colorchange 2s infinite;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;

		.gl_num {
			font-size: 130rpx;
			font-weight: 700;
		}

		.gl_title {}
	}

	.center_wrap {
		color: rgba(255, 255, 255, 1);
		animation: colorchange 2s infinite;
		display: flex;
		justify-content: space-around;

		.center_item {
			width: 33.33%;
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;

			.item_top {
				font-size: 60rpx;
				font-weight: 700;
			}

		}
	}
	.footer{
		position: relative;
		margin-top: 40rpx;
		.map{
			position: absolute;
			right: 60rpx;
			top: 78rpx;
			padding: 10rpx;
			border: 2rpx solid white;
			border-radius: 50%;
			color: white;
			z-index: 99;
		}
	}
	.btn_wrap {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		&.up{
			z-index: 99;
		}
		&.down{
			transform: scale(0,0);
		}
		display: flex;
		justify-content: center;
		
		.btn {
			width: 160rpx;
			height: 160rpx;
			border-radius: 50%;
			display: flex;
			margin: 40rpx;
			flex-direction: column;
			justify-content: center;
			align-items: center;
			
			&.stop_btn {
				
				background-color: #fff;
			}

			&.start_btn {
				// transform: scale(0,0);
				background-color: #0f0;
			}

			&.end_btn {
				// transform: scale(0,0);
				background-color: #f0f;
			}
		}
	}

	@keyframes myfirst {
		0% {
			opacity: 0;
		}

		50% {
			opacity: 1;
		}

		70% {
			opacity: 1;
		}

		100% {
			opacity: 0;
		}
	}

	@keyframes colorchange {
		0% {
			color: rgba(255, 255, 255, 1);
		}

		50% {
			color: rgba(255, 255, 255, .6);
		}

		100% {
			color: rgba(255, 255, 255, 1);
		}
	}
</style>

<!-- 地图 -->
<template>
	<view style="position: relative;">
		<map 
			v-if="polyline[0].points.length > 0"
			id="fs_map" 
			:markers="markers" 
			:polyline="polyline" 
			:show-location="true"
			:show-compass="true"
			:enable-traffic="true"
			:enable-building="true"
			:latitude="changeCenterPosition.latitude" 
			:longitude="changeCenterPosition.longitude" 
			style="width: 100%; height: 90vh;" 
		/>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				markers:[{
					id: 1,
					width: 40,
					height: 40,
					latitude: 0,
					longitude: 0,
					iconPath: '/static/img/fireFightingEngine.png',
					anchor: {
						x: 0.5,
						y: 1
					}
				}],//标记点
				polyline:[{ points: [], width: 6,  arrowLine: true, color: '#3591FC', }],//路线
			};
		},
		computed: {
			//中心点位置变化
			changeCenterPosition() {
				return {
					latitude: this.currentpoint.latitude || '',
					longitude: this.currentpoint.longitude || ''
				}
			}
		},
		props: {
			// currentpoint: {
			// 	type: Array,
			// 	default() {return []}
			// },
			currentpoint: {
				type: Object,
				default() {return {}}
			}
		},
		watch: {
			currentpoint: {
				handler(newValue, oldValue) {
					this.polyline[0].points.push({latitude: newValue.latitude, longitude: newValue.longitude})
				},
				deep: true
			}
		},
		methods: {
		},
		onLoad(options) {
			this.option = options
		},
		mounted() {
			
		}
	}
</script>

<style lang="scss">

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

RxnNing

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值