前端定位

146 阅读2分钟

前端定位

背景

有个活动页面需要用户现场扫码, 不在范围内的用户扫码会进入其他页面

方案一:原生 html api

mdn文档

用法

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); // 返回距离,保留小数点后两位
}