uniapp 根据定位实现地图绘制轨迹
uniapp 地图绘制线和标记点
·
目录
一、实时定位并保存经纬度(推荐使用uni.getLocation )
二、根据已有的经纬度数组渲染线(polyline)以及标记点(markers)
三、前后台获取经纬度并展示到地图上(uni.startLocationUpdateBackground)
一、实时定位并保存经纬度(推荐使用uni.getLocation )
uniapp-getLocationhttps://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-maphttps://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)
前提:由于项目需求,只有前台获取地址已经不满足了,因此找到了这个方法,前后台都可以获取地址
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>
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)