前端定位
背景
有个活动页面需要用户现场扫码, 不在范围内的用户扫码会进入其他页面
方案一:原生 html api
用法
const getCurrentPosition = () => {
return new Promise((resolve, reject) => {
const geolocation = navigator.geolocation;
geolocation.getCurrentPosition(({ coords }) => {
console.log('getCurrentPosition', coords);
resolve(coords);
}, (error) => {
reject(error)
})
})
}
问题
第一次进入页面时如果拒绝了给页面位置权限, 下次就不会再弹获取权限的弹窗了, 除非清理本地缓存
方案二: 使用第三方 sdk
这里使用了百度地图的 sdk
首先去百度地图开放平台申请一个ak, 然后再 index.html 中引入
注意:
1.由于Chrome、iOS10以上系统等已不再支持非安全域的浏览器定位请求,为保证定位成功率和精度,请尽快升级您的站点到HTTPS。
2.iOS15系统浏览器默认关闭位置请求,需要用户设置手机为允许/询问后方可获取精确的定位,定位权限的开启方式请参见iOS15定位问题。
3.由于浏览器原生定位成功率并不高,我们提供ip和安卓sdk定位进行辅助,如果定位精准在城市级别,可提供ak联系我们提高定位精准度。
<script src="https://api.map.baidu.com/api?v=2.0&ak=ni-zi-ji-de-ak"></script>
getLocation = () => {
return new Promise((resolve, reject) => {
const geolocation = new window.BMap.Geolocation();
geolocation.enableSDKLocation();
geolocation.getCurrentPosition((r) => {
const pt = r.point;
const gc = new window.BMap.Geocoder();
gc.getLocation(pt, (rs) => {
const { lat, lng } = pt;
const distance = getLatAndLonDistance(lat, lng, LAT, LON);
console.log('distance', distance, pt, rs)
resolve(true);
});
}, (err) => {
reject(err)
});
})
}
根据两个经纬度获取距离
// 根据两个地点的经纬度获取两个地点的距离
// lat: 纬度, lon: 经度
export function getLatAndLonDistance(lat1, lon1, lat2, lon2) {
const R = 6371; // 地球半径(千米)
const dLat = (lat2 - lat1) * Math.PI / 180; // 将纬度转换为弧度
const dLon = (lon2 - lon1) * Math.PI / 180; // 将经度转换为弧度
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c; // 计算距离(千米)
return distance.toFixed(2); // 返回距离,保留小数点后两位
}