关于在H5中获取实时位置各种方案的对比

angrybird2332023-04-06FrontendH5开发GPS定位

前言

  • 最近在做一个H5的项目过程中,需要获取用户的当前位置,且对于定位的实时性和精度都有要求,所以需要调研一下各种方案,通过对各种方案的实地测试,总结出一些结论。

  • 准所周知,由于浏览器的安全策略,H5中获取实时位置的方案基本都是通过调用浏览器提供的API来实现的,包括GPS定位、IP定位、基站定位、Wi-Fi定位等,但是IP定位只在电脑端可行,Wi-Fi定位需要有WIFI才行,所以获取实时位置的方案基本都是通过调用浏览器提供的API来实现的。即: navigator.geolocation, 但是使用原生的api的话需要自己封装且需要考虑兼容性问题。

  • 所以我首先选择了目前现有的比较成熟的方案,腾讯地图、百度地图、高德地图、天地图、企业微信提供的定位API、微信小程序提供的定位api, 由于百度地图的坐标系统和经纬度是经过特殊算法加密的,无法对接现有的坐标,首先排除,所以下面就从这几个进行了测试。

腾讯地图

  • 腾讯地图提供了定位的插件,文档[https://lbs.qq.com/webApi/component/componentGuide/componentGeolocation]
  • 优点 腾讯地图前端定位组件是在原生H5定位的基础上做了一下优化,包括对获取的位置信息做了缓存,当原生H5定位失败的时候(用户未授权app权限或者拒绝了授权弹窗),会降级使用IP定位。 和原生相比,获取信息的成功率会有一定的提高。
  • 缺点 位置缓存比较严重,这对于实时定位来说位置不太准确。

高德地图

  • 高德地图提供了定位的插件,文档[https://lbs.amap.com/api/javascript-api-v2/guide/services/geolocation]
  • 优点 高德JS API提供的浏览器定位接口,融合了HTML5 Geolocation定位接口、精确IP定位服务,以及安卓定位sdk定位 使用
      AMap.plugin('AMap.Geolocation', function() {
      var geolocation = new AMap.Geolocation({
        enableHighAccuracy: true, // 是否使用高精度定位,默认:true
        timeout: 10000, // 设置定位超时时间,默认:无穷大
        offset: [10, 20],  // 定位按钮的停靠位置的偏移量
        zoomToAccuracy: true,  //  定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
        position: 'RB' //  定位按钮的排放位置,  RB表示右下
      })
    
      geolocation.getCurrentPosition(function(status,result){
        if(status=='complete'){
            onComplete(result)
        }else{
            onError(result)
        }
      });
    
      function onComplete (data) {
        // data是具体的定位信息
      }
    
      function onError (data) {
        // 定位出错
      }
    })
    
    • 缺点 高德地图定位点在城市街道与在乡村地区、农田地区的差异较大,定位点偏移很明显。

天地图

  • 天地图提供了定位的API,文档[http://lbs.tianditu.gov.cn/api/js4.0/examples.html] 示例demo
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <meta name="keywords" content="天地图"/>
    <title>天地图-地图API-范例-H5定位</title>
    <script type="text/javascript" src="http://api.tianditu.gov.cn/api?v=4.0&tk=您的密钥"></script>
    <style type="text/css">body,html{width:100%;height:100%;margin:0;font-family:"Microsoft YaHei"}#mapDiv{width:100%;height:400px}input,b,p{margin-left:5px;font-size:14px}</style>
    <script>
        var map;
        var zoom = 12;
        function onLoad() {
            //初始化地图对象
            map = new T.Map("mapDiv");
            //设置显示地图的中心点和级别
            map.centerAndZoom(new T.LngLat(116.40969, 38.89945), zoom);
            var lo = new T.Geolocation();
            fn = function (e) {
                if (this.getStatus() == 0){
                    map.centerAndZoom(e.lnglat, 15)
                    alert("获取定位坐标:"+e.lnglat.lat + "," + e.lnglat.lng)
                    var marker = new T.Marker(e.lnglat);
                    map.addOverLay(marker);

                }
                if(this.getStatus() == 1){
                    map.centerAndZoom(e.lnglat, e.level)
                    alert("获取定位坐标:"+e.lnglat.lat + "," + e.lnglat.lng)
                    var marker = new T.Marker(e.lnglat);
                    map.addOverLay(marker);
                }
            }
            lo.getCurrentPosition(fn);
        }
    </script>
</head>
<body onLoad="onLoad()">
<div id="mapDiv"></div>
<p>本示例演示如用H5定位所在城市</p>
</body>
</html>
  • 完全利用浏览器的geolocation接口获取用户当前位置,不支持的浏览器将无法获取
  • 缺点: 通过测试安卓系统与IOS系统的定位打点数据发现,定位点漂移点较多,偏移很大,特别是IOS打的定位点。

企业微信API

  • 微信小程序提供了定位的API,文档[https://developer.work.weixin.qq.com/document/path/90504]
  // 获取当前位置
  wx.getLocation({
      type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
      success: function (res) {
          var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
          var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
          var speed = res.speed; // 速度,以米/每秒计
          var accuracy = res.accuracy; // 位置精度
      }
  });
  // 打开持续定位
  wx.invoke('startAutoLBS',{
      type: 'gcj02', // wgs84是gps坐标,gcj02是火星坐标
    },
    function(res) {
      if(res.err_msg == "startAutoLBS:ok"){
        //调用成功
      }else {
        //错误处理
      }
  });
  // 停止持续定位接口
  wx.invoke('stopAutoLBS',{},
    function(res) {
        if(res.err_msg == "stopAutoLBS:ok"){
          //调用成功
        }else {
          //错误处理
      }
    });
  // 监听地理位置变化
  wx.onLocationChange( 
    function(res) {
      if(res.errMsg == "auto:location:report:ok"){
        var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90
        var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。
        var speed = res.speed; // 速度,以米/每秒计
        var accuracy = res.accuracy; // 位置精度
        var lbsIndex = 0;
      }else {
        //错误处理
      }
    }
  );
  • 缺点: 通过测试安卓系统与IOS系统的定位打点数据,定位点漂移点较多,偏移较大,尤其是农田区域。

微信小程序API

微信小程序提供了好几个获取位置以及持续获取位置的API,符合要求的是(wx.startLocationUpdateBackground)[https://developers.weixin.qq.com/miniprogram/dev/api/location/wx.startLocationUpdateBackground.html]

  • 开启小程序在前后台时均可接收位置消息,后台包括离开小程序后继续使用微信(微信仍在前台)、离开微信(微信在后台)两个场景,需引导用户开启授权。授权以后,小程序在运行中或进入后台均可接受位置消息变化。
  // 开启持续定位
  startLocation() {
    wx.startLocationUpdateBackground({
      type: 'wgs84',
      success: res => {
        if (res.errMsg === 'startLocationUpdateBackground:ok') {
          wx.onLocationChange(res => {
            console.log('onLocationChange', res)
          })
        }
      },
      fail: err => {
        console.log('err', err)
        promptUserTurnOnBackgroundLocation(this.startLocation)
      },
    })
  },
  • 优点: 获取的定位点是获取的位置APP获取的GPS数据,定位点比较准确,偏移较小,且IOS和安卓系统差异很小。
  • 缺点: 由于是H5开发,也就是说H5页面需要嵌入的小程序中,而且需要前后端配合才能记录定好点数据。

最终选择的是微信小程序API的方案,将H5嵌入到小程序的页面中,在进入小程序webview页面时实时获取定位数据并调用后端接口发送到后端,在H5页面中调用后端接口获取后端返回的实时位置数据,接口时间差很小,且不会丢失点位,最终实现实时经纬度位置记录。

最后更新时间 9/4/2024, 8:14:48 AM