关于在H5中获取实时位置各种方案的对比
前言
最近在做一个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页面中调用后端接口获取后端返回的实时位置数据,接口时间差很小,且不会丢失点位,最终实现实时经纬度位置记录。