uniapp 根据定位实现地图绘制轨迹

目录

一、实时定位并保存经纬度(推荐使用uni.getLocation )

二、根据已有的经纬度数组渲染线(polyline)以及标记点(markers)

三、前后台获取经纬度并展示到地图上(uni.startLocationUpdateBackground)

1、获取权限 

2、获取定位

 3、使用

4、结束定位


一、实时定位并保存经纬度(推荐使用uni.getLocation )

uniapp-getLocationicon-default.png?t=N7T8https://uniapp.dcloud.net.cn/api/location/location.html

方法示例 

			getLocation(id) {
				const _this = this;
				_this.coordinates.driverTaskId = id
				uni.getLocation({
					type: 'gcj02', // (!!!必需)默认为 wgs84 返回 gps 坐标,gcj02(更准确) 返回可用于 wx.openLocation 的坐标
					isHighAccuracy: true, //开启高精度定位(!!!必需)
					success: function(res) {
						_this.coordinates.latitude =  res.latitude // 当前位置纬度
						_this.coordinates.longitude = res.longitude // 当前位置经度
						console.log(_this.coordinates, 'coordinates')
					},
					fail: function(error) {
						uni.showToast({
							title: '无法获取位置信息!无法使用位置功能',
							icon: 'none',
						})
					}
				});
			},

注:高德(getRegeo)获取当前位置返回的坐标采用的是wgs84 ,如果需要经纬度来渲染到地图上,尽量不要用高德的。

二、根据已有的经纬度数组渲染线(polyline)以及标记点(markers)

使用uni-app的map组件 uniapp-mapicon-default.png?t=N7T8https://uniapp.dcloud.net.cn/component/map.html#map

 

地图组件封装

下面是我封装的一个map组件  回显轨迹(点击进入这个组件,前提是需要传轨迹点位) 

<button class="primary_button" @click="lookTrajectory(item)">查看轨迹</button>

// 查看轨迹方法
lookTrajectory(item) {
	getTrajectory(item.id).then(res => {
		if (res.data.code == 200) {
			const data = JSON.stringify(res.data.data)
			console.log(data)
			uni.navigateTo({
				url: `/pages/task/trajectory/trajectory?points=${data}&status=${item.taskStatus}&endLatitude=${item.endLatitude}&endLongitude=${item.endLongitude}&startLatitude=${item.startLatitude}&startLongitude=${item.startLongitude}&id=${item.id}`
			});
		}
	})
},
<template>
	<view>
		<map style="width: 100%; height: 100vh;" scale='13' :latitude="latitude" :longitude="longitude" :polyline="polyline" :markers="markers" :v-if="showmap">
		 </map>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				latitude:'',
				longitude:'',
				polyline: [], // 线
				points:[],
				showmap:false,
				markers:[], // 标记点
			};
		},
		onLoad(event) {
			uni.showLoading({
				title: '地图加载中',
				// mask: true
			})
			this.points = JSON.parse(event.points) // 通过navigateTo传过来的数据
			this.latitude=this.points[0].latitude
			this.longitude=this.points[0].longitude
			const length= this.points.length-1
			
			const taskline={
				points: this.points,
				color: "#5A97FF",
				width: 10, // width必须填 不然会报错
				arrowLine:true // 是否有箭头
			}
			const markers0={
				latitude:this.points[0].latitude,
				longitude:this.points[0].longitude,
				id:0,
				iconPath:'/static/images/task/startpoint.png',
				width:40,
				height:50
			}
			const markers1={
				latitude:this.points[length].latitude,
				longitude:this.points[length].longitude,
				id:1,
				iconPath:'/static/images/task/endpoint.png',
				width:40,
				height:50
			}
			this.markers.push(markers0)
			this.markers.push(markers1)
			console.log(this.markers)
			this.polyline[0]=taskline
			this.showmap=true;
			setTimeout(() => {
			    uni.hideLoading()
			}, 1000)
		}
	}
</script>

三、前后台获取经纬度并展示到地图上(uni.startLocationUpdateBackground)

uni.startLocationUpdateBackgroundicon-default.png?t=N7T8https://uniapp.dcloud.net.cn/api/location/location-change.html#startlocationupdatebackground

前提:由于项目需求,只有前台获取地址已经不满足了,因此找到了这个方法,前后台都可以获取地址

 manifest.json 文件中 "mp-weixin" 里添加:onLocationChange和startLocationUpdateBackground是搭配使用的

"permission" : {
            "scope.userLocation" : {
                "desc" : "获取当前位置信息"
            },
			"scope.userLocationBackground":{
			    "desc" : "获取您的后台位置"
			}
        },
		"requiredPrivateInfos":["getLocation","onLocationChange","startLocationUpdateBackground" ],
		"requiredBackgroundModes":["location"]

1、获取权限 

//   初次位置授权
			getAuthorize() {
				return new Promise((resolve, reject) => {
					uni.authorize({
						scope: 'scope.userLocationBackground',
						success: () => {
							resolve() // 允许授权
						},
						fail: () => {
							reject() // 拒绝授权
						},
					})
				})
			},
			// 用户首次拒绝授权后(考虑是误点击),弹框提示是否手动打开位置授权
			openConfirm() {
				return new Promise((resolve, reject) => {
					uni.showModal({
						title: '请求授权当前位置',
						content: '我们需要获取地理位置信息',
						success: res => {
							if (res.confirm) {
								uni.openSetting().then(res => {
									console.log('想看看:', res)
									if (res[1].authSetting['scope.userLocationBackground'] ===
										true) {
										resolve() // 打开地图权限设置
									} else {
										reject()
									}
								})
							} else if (res.cancel) {
								reject()
							}
						},
					})
				})
			},

 

2、获取定位

			// 获取当前位置
			getLocation(id) {
				const _this = this;
				uni.startLocationUpdateBackground({
					type: 'gcj02',
					success: (res) => {
						uni.onLocationChange((data) => {
							//获取当前时间
							var currentTime = new Date().getTime();
							//获取上次执行的时间
							var oldTime = uni.getStorageSync('oldTime');
							//判断当前间隔时间超过5s
							if (currentTime - oldTime > 5000) {
								console.log(data, '123456')
								//缓存当前执行的时间
								uni.setStorageSync('oldTime', currentTime);
								_this.coordinates.latitude = data.latitude // 当前位置纬度
								_this.coordinates.longitude = data.longitude // 当前位置经度
								// addTrajectory(_this.coordinates) // 把经纬度传给后端
							}
						});
					},
					fail: error => {
						console.log(error)
						uni.showToast({
							title: '无法获取位置信息!无法使用位置功能',
							icon: 'none',
						})
					}
				});
			},

 3、使用

this.getAuthorize()
	.then(() => {
        //   同意后获取
		this.getLocation(id)
	})
	.catch(() => {
	    //   不同意给出弹框,再次确认
		this.openConfirm()
			.then(() => {
				this.getLocation(id)
			})
	})

4、结束定位

uni.stopLocationUpdate()

四、需求更新:地图上根据实时获取经纬度去更新地图 

在mounted中设置自动刷新的定时器 

		mounted() {
			if(this.timer){
				clearInterval(this.timer)
			}else{
				console.log(this.taskstatus)
				if(this.taskstatus==3){
					this.timer = setInterval(() => {
						console.log('正在运输。。。。。')
					      this.lookTrajectory(); // 获取传到后端经纬度
					}, 5000);
				}
			}
		},
		beforeDestroy() {
			clearInterval(this.timer)
		},
			// 查看司机轨迹
			lookTrajectory() {
				getTrajectory(this.taskid).then(res => {
                    // 后端接口 获取经纬度
					if (res.data.code == 200) {
						const data =JSON.parse(JSON.stringify(res.data.data)) 
						this.points=data
						console.log(this.points,'获取轨迹经纬度了哦points~')
						this.setPolyline()
					}
				})
			},
			setPolyline(){
				this.latitude=this.points[0].latitude
				this.longitude=this.points[0].longitude
				const length= this.points.length-1
				
				const taskline={
					points: this.points,
					color: "#5A97FF",
					width: 10,
					arrowLine:true
				}
				const markers0={
					latitude:this.points[0].latitude,
					longitude:this.points[0].longitude,
					id:0,
					iconPath:'/static/images/task/startpoint.png',
					width:40,
					height:50
				}
				const markers1={
					latitude:this.points[length].latitude,
					longitude:this.points[length].longitude,
					id:1,
					iconPath:'/static/images/task/endpoint.png',
					width:40,
					height:50
				}
				this.markers[0]=markers0
				this.markers[1]=markers1
				this.polyline[0]= taskline;
				console.log("改变地图轨迹啦!!!")
			},

 这样就可以啦,可以实时刷新了

over over  如有错误请大家指正!!!!

补充:完整代码如下:

调用组件页面:

这里面css样式没有放上去

<template>
	<view style="padding-bottom: 40rpx;">
		<!-- 展示任务 -->
		<view class="task-area" v-for="(item,findex) in tasklistArr" :key="findex">
			<view>
				<view class="task_button" v-if="userRole=='driver'">
					<view>
						<button class="primary_button" @click="lookTrajectory(item)">查看轨迹</button>
					</view>
					<view>
						<button class="primary_button" v-if="item.taskStatus==3"
							@click="startTask(item.id)">开始配送</button>
					</view>
				</view>
			</view>
		</view>
		<view class="task-hint" v-if="tasklistArr.length==0">暂无任务~</view>
	</view>
</template>

<script>
	import {
		getTask,
		gettaskInfo,
		addTrajectory,
		getTrajectory,
		cancelTask,
		deleteTask,
	} from "@/api/cargo.js";
	import {
		driverCancel,
		startTransportation,
	} from "@/api/drivertask.js";
	import cache from "@/utils/cache.js"; // 获取token
	export default {
		name: "tabbar-task",
		props: {
			tasklist: Array,
			taskstatus: String,
			param: Object,
		},
		data() {
			return {
				taskform: {},
				tasklistArr: [],
				timer: null, // 定时器
				gaodekey: '', // 高德的key
				coordinates: {
					latitude: '', //纬度
					longitude: '', // 经度
					taskId: '', // 任务id
				}, //坐标系
				weChatUserId: '', // 微信用户id(司机)
				userRole: '', // 用户权限 货主还是司机
				sysUserId: '', //货主id
			};
		},
		beforeCreate() {
			uni.showLoading({
				mask: true,
				title: '正在加载中...',
			})
		},
		mounted() {
			this.weChatUserId = cache('user_token', null)
			this.sysUserId = cache('sys_user', null)
			this.userRole = cache('user_role', null)
			this.tasklistArr = JSON.parse(JSON.stringify(this.tasklist))
			setTimeout(() => {
				uni.hideLoading()
			}, 500)
			if (this.userRole == 'company') {
				this.refreshOwnerList()
			}
		},
		watch: {
			tasklist: {
				immediate: true, // 这句重要
				handler(val) {
					this.tasklistArr = val;
				},
			},
		},
		methods: {
			// 开始任务
			startTask(id) {
				// 开始配送  startTransportation是接口
				// export function startTransportation(id) {
				// 	return request({
				// 		url: `/driver/start_transportation/${id}`,
				// 		'method': 'POST'
				// 	})
				// }

				startTransportation(id).then(res => {
					if (res.data.code == 200) {
						this.refreshDriverList() // 更新列表
						// 先获取位置权限
						this.getAuthorize()
							.then(() => {
								console.log("同意获取位置权限")
								//   同意后获取
								this.getLocation(id)
							})
							.catch(() => {
								//   不同意给出弹框,再次确认
								this.openConfirm()
									.then(() => {
										console.log("同意获取位置权限")
										this.getLocation(id)
									})
							})
					}
				})
			},
			// 查看轨迹
			lookTrajectory(item) {
				getTrajectory(item.id).then(res => {
					if (res.data.code == 200) {
						const data = JSON.stringify(res.data.data)
						console.log(data)
						uni.navigateTo({
							url: `/pages/task/trajectory/trajectory?points=${data}&status=${item.taskStatus}&endLatitude=${item.endLatitude}&endLongitude=${item.endLongitude}&startLatitude=${item.startLatitude}&startLongitude=${item.startLongitude}&id=${item.id}`
						});
					}
				})
			},
			//   初次位置授权
			getAuthorize() {
				return new Promise((resolve, reject) => {
					uni.authorize({
						scope: 'scope.userLocationBackground',
						success: () => {
							resolve() // 允许授权
						},
						fail: () => {
							reject() // 拒绝授权
						},
					})
				})
			},
			// 用户首次拒绝授权后(考虑是误点击),弹框提示是否手动打开位置授权
			openConfirm() {
				return new Promise((resolve, reject) => {
					uni.showModal({
						title: '请求授权当前位置',
						content: '我们需要获取地理位置信息',
						showCancel: false,
						success: res => {
							if (res.confirm) {
								uni.openSetting({
									success(res) {
										resolve() // 打开地图权限设置
									}
								})
							} else if (res.cancel) {
								reject()
							}
						},
					})
				})
			},
			// 获取当前位置
			getLocation(id) {
				const _this = this;
				_this.coordinates.taskId = id
				uni.startLocationUpdateBackground({
					type: 'gcj02',
					success: (res) => {
						uni.onLocationChange((data) => {
							/* 							_this.coordinates.latitude = data.latitude // 当前位置纬度
														_this.coordinates.longitude = data.longitude // 当前位置经度
														addTrajectory(_this.coordinates) */
							//获取当前时间
							var currentTime = new Date().getTime();
							//获取上次执行的时间
							var oldTime = uni.getStorageSync('oldTime');
							console.log(currentTime, 'currentTime')
							console.log(oldTime, 'oldTime')
							//获取上次保存的位置信息
							// var oldLocation = wx.getStorageSync('oldLocation');
							//将经纬度拼接
							// var newLocation = data.latitude + "" + data.longitude;
							//判断当前间隔时间超过5s
							if (currentTime - oldTime > 5000) {
								console.log(data, '传递经纬度')
								//缓存当前最新位置
								// uni.setStorageSync('oldLocation', newLocation);
								//缓存当前执行的时间
								uni.setStorageSync('oldTime', currentTime);
								_this.coordinates.latitude = data.latitude // 当前位置纬度
								_this.coordinates.longitude = data.longitude // 当前位置经度
								addTrajectory(_this.coordinates)
							}
						});
					},
					fail: error => {
						console.log(error)
						uni.showToast({
							title: '无法获取位置信息!无法使用位置功能',
							icon: 'none',
						})
					}
				});
			},
		},
	}
</script>

trajectory文件就是封装的map组件

 

<template>
	<view>
		<map style="width: 100%; height: 100vh;" scale='13' :latitude="latitude" :longitude="longitude" :polyline="polyline" :markers="markers" :v-if="showmap">
		 </map>
	</view>
</template>

<script>
	import {
		getTrajectory
	} from "@/api/drivertask.js";
	export default {
		data() {
			return {
				latitude:'',
				longitude:'',
				polyline: [], // 线
				points:[],
				showmap:false,
				markers:[], // 标记点
				taskid:'', // 任务id
				taskstatus:'', // 任务状态
				timer:null, // 定时器
				endLatitude:'',
				endLongitude:'',
				startLatitude:'',
				startLongitude:'',
			};
		},
		onLoad(event) {
			uni.showLoading({
				title: '地图加载中',
				// mask: true
			})
			this.endLatitude=event.endLatitude
			this.endLongitude=event.endLongitude
			this.startLatitude=event.startLatitude
			this.startLongitude=event.startLongitude
			this.points = JSON.parse(event.points)
			this.taskid = event.id
			this.taskstatus = event.status
			this.setPolyline()
			this.showmap=true;
			setTimeout(() => {
			    uni.hideLoading()
			}, 1000)
		},
		mounted() {
			if(this.timer){
				clearInterval(this.timer)
			}else{
				console.log(this.taskstatus)
				if(this.taskstatus==5){
					this.timer = setInterval(() => {
						console.log('正在运输。。。。。')
					      this.lookTrajectory();
					}, 5000);
				}
			}
		},
		beforeDestroy() {
			clearInterval(this.timer)
		},
		methods:{
			// 查看司机轨迹
			lookTrajectory() {
				getTrajectory(this.taskid).then(res => {
					if (res.data.code == 200) {
						const data =JSON.parse(JSON.stringify(res.data.data)) 
						this.points=data
						console.log(this.points,'获取轨迹经纬度了哦points~')
						this.setPolyline()
					}
				}) // 获取地图轨迹数据点
			},
			setPolyline(){
				this.latitude=this.points[0].latitude
				this.longitude=this.points[0].longitude
				const length= this.points.length-1
				
				const taskline={
					points: this.points,
					color: "#5A97FF",
					width: 10,
					arrowLine:true
				}
				const markers0={
					latitude:this.points[0].latitude,
					longitude:this.points[0].longitude,
					id:0,
					iconPath:'/static/images/task/startpoint1.png',
					width:48,
					height:61
				}
				const markers1={
					latitude:this.points[length].latitude,
					longitude:this.points[length].longitude,
					id:1,
					iconPath:'/static/images/task/endpoint1.png',
					width:48,
					height:61
				}
				const markers2={
					latitude:this.startLatitude,
					longitude:this.startLongitude,
					id:2,
					iconPath:'/static/images/task/startpoint2.png',
					width:48,
					height:61
				}
				const markers3={
					latitude:this.endLatitude,
					longitude:this.endLongitude,
					id:3,
					iconPath:'/static/images/task/endpoint2.png',
					width:48,
					height:61
				}
				this.markers[0]=markers0
				this.markers[1]=markers1
				this.markers[2]=markers2
				this.markers[3]=markers3
				this.polyline[0]= taskline;
				console.log("改变地图轨迹啦!!!")
			},
		},
	}
</script>

<style lang="scss">

</style>

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值