利用uniap中的地图组件默认给一个经纬度,绘制对应经纬度的点和圆,即
markers和circles;
首先在data 中定义
radius: 500, storeLocation: { lon: '116.40400', lat: '39.92800' }, carLocation: { lon: '', lat: '' }, newCarLocation: {}, distanceLen: [], circles: [{ latitude: '', longitude: '', color: '#ffffffff', fillColor: '#7cb5ec29', radius: 100, strokeWidth: 1 }], markers: [], newLocationList: [],
在页面初始化加载的时候,调用this.getLegDetail方法,此时假如后后台拿到的数据是
this.dbForm.lonLat是多个经纬度,经纬度之间使用逗号分割,多个经纬度之间使用封号相隔,然后调用getLegDetail方法来获取多个点坐标和标记点,下面是代码
getLegDetail(info) {
Object.assign(this.dbForm, JSON.parse(info));
const lonLatArray = this.dbForm.lonLat.split(';');
if (lonLatArray.length > 0) {
const locationList = []; // 多个仓库
for (let i = 0; i < lonLatArray.length; i++) {
const lonLat = lonLatArray[i];
const [lon, lat] = lonLat.split(',');
// 添加对经纬度是否合法的验证
const isValidLon = !isNaN(parseFloat(lon));
const isValidLat = !isNaN(parseFloat(lat));
if (isValidLon && isValidLat) {
locationList.push({ longitude: parseFloat(lon), latitude: parseFloat(lat) });
}
}
if (locationList.length > 0) {
const list = [];
locationList.forEach(item => {
list.push({
lon: item.longitude,
lat: item.latitude
})
this.newLocationList = list;
})
this.drawCircles(locationList);
this.drawMarkers(this.newLocationList);
} else {
uni.showModal({
title: '提示',
content: '请联系管理员正确维护仓库地址经纬度',
showCancel: false
});
}
}
},
drawCircles(arr = []) {
const list = [];
arr.forEach(i => {
list.push({
latitude: i.latitude,
longitude: i.longitude,
color: '#01478bff',
fillColor: '#7cb5ec70',
radius: this.radius,
strokeWidth: 1
})
})
this.circles = list;
},
drawMarkers(locationList) {
const markers = [];
locationList.forEach((item, index) => {
const iconPath = (item === this.newCarLocation)
? '/pages/driver/static/point.png'
: '/static/logo.png';
markers.push({
id: index,
latitude: item.lat,
longitude: item.lon,
iconPath: iconPath,
width: 60,
height: 32
});
});
this.markers = markers;
},
然后每隔30秒来获取自己的坐标位置
onShow() {
this.timer = setInterval(() => {
this.getLocation()
}, 30000)
},
onHide() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
},
通过获取自己的经纬度位置, 其中commonUtils是公告方法,需要自己定义,或者重新定义为一个函数,此时代码中的commonUtils,是我前端封号的公共方法,
getLocationFirst111() {
return new Promise((resolve, reject) => {
uni.getLocation({
type: 'gcj02',
success: res => {
resolve(res)
},
fail: err => {
reject(err)
}
})
})
}
getLocation() {
return commonUtils.getLocationFirst111().then(res => {
this.carLocation.lat = res.latitude;
this.carLocation.lon = res.longitude;
this.newCarLocation = {
lat: this.carLocation.lat,
lon: this.carLocation.lon
};
let locationList = [];
const list = this.newLocationList.map(item => item)
locationList = [this.newCarLocation, ...list];
this.drawMarkers(locationList);
}).catch(() => {
this.openAuthSetting();
});
},
此时在drawMarkers方法中便有自己和后端返回的多个经纬度,根据list 和自己的经纬度作比较,当其中有一个在后端返回的多个经纬度范围之内,就可打卡,否则无法打卡
async handleConfirm() {
await this.getLocation();
// 存储距离的数组
const distances = [];
// 计算自己与每个仓库的距离并存储到数组中
this.newLocationList.forEach(item => {
const distance = this.distance(
this.newCarLocation.lat,
this.newCarLocation.lon,
item.lat,
item.lon
);
distances.push(distance);
});
console.log(distances)
const validityDistance = distances.some(item => item * 1000 < this.radius);
if (validityDistance) {
this.confirmVisible = true;
} else {
uni.showModal({
title: '提示',
content: '您还未进入仓库范围,请到达仓库范围之后进行确认操作!',
showCancel: false
});
}
},
计算两点之间的距离;即两个点各自的经纬度计算出两点之间的距离;
distance(lat1, lng1, lat2, lng2) {
const EARTH_RADIUS = 6378.137; // 地球半径
const rad = (d) => { return d * Math.PI / 180.0; }; // 计算弧度
const radLat1 = rad(lat1), radLat2 = rad(lat2), a = radLat1 - radLat2, b = rad(lng1) - rad(lng2);
let 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 * EARTH_RADIUS;
s = Math.round(s * 10000) / 10000;
s = s.toFixed(3);
return s;
},
其中在手机上获取自己的地理位置的api是
openAuthSetting() {
/* #ifndef H5 */
uni.getSetting({
success: (res) => {
const authLocation = res.authSetting['scope.userLocation'];
if (authLocation !== undefined && authLocation !== true) {
uni.showModal({
title: '请授权位置权限',
content: '需要获取您的地理位置,请确认授权!',
showCancel: false,
success: () => {
uni.openSetting({
success: result => {
const auLocation = result.authSetting['scope.userLocation'];
if (auLocation) {
uni.showToast({ title: '授权成功', icon: 'success', duration: 3000 })
this.getLocation();
} else {
uni.showToast({ title: '授权失败', icon: 'error', duration: 3000 })
}
}
})
}
})
} else {
this.getLocation();
}
},
fail: err => {
uni.showModal({
title: '提示',
content: JSON.stringify(err),
showCancel: false
})
}
})
/* #endif */
},