Html5中如何解决定位问题
这篇文章给大家分享的是有关Html5中如何解决定位问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
目标与分析
我们的目标是经过封装之后,只需要调用一个方法就可以拿到返回的位置信息。
我们需要做的事情是,针对不同的端(微信H5和其他浏览器环境)封装不同的类,再通过一个方法通过 UA 区分,调用不同环境对应的类获取位置。
在微信内部,经过反复的实践之后,不论是通过原生的 HTML5 定位,还是通过第三方(如百度或腾讯地图) jsapi 获取位置,不仅定位时间长,甚至经常出现定位失败的情况,严重影响用户体验,尤其对于大部分信息流都依赖于用于位置的商城首页来说,是完全无法接受的。所以在微信内我们只有微信 sdk 这一种选择;
而对于浏览器端,通过第三方的地图 jsapi 或定位组件,可以稳定且较快速地获取位置信息,为了与微信内尽量保持一致,我们选择的是腾讯地图 jsapi。
解决方案
Talk is cheap, show me the code. 废话不多说,直接上代码:
1. 在浏览器中,通过腾讯地图jsapi获取位置
1.1 在项目的 html 模版文件中引入腾讯地图 jsapi:
<!--index.html--><scriptcharset="utf-8"src="https://map.qq.com/api/js?v=2.exp&key=腾讯地图key&referer=应用名称"></script>
说明:
使用腾讯地图 jsapi, 需要先去腾讯地图开放平台申请自己的账号,然后创建自己的应用,将腾讯地图key 和创建的应用名称替换上面的值。
1.2 调用获取位置接口,获取位置信息
为了方便复用,我们单独封装一个腾讯地图 jsapi 的类,命名为 tMap.js
//tMap.jsconstqq=window.qqvargeolocation=nullif(qq&&qq.maps){//初始化定位组件geolocation=newqq.maps.Geolocation('QVLBZ-YUULR-OUMW7-WKXFD-4SUWS-UDBIA','mymap')}classTMap{//获取定位计数器用于定位失败时累计次数超过3次后不再继续,抛出定位失败错误getPositionCount=0//对外暴露的获取位置接口getLocation(){returnnewPromise((resolve,reject)=>{//定位成功回调this.getTMapLocation(resolve,reject)})}//调用腾讯地图获取位置getTMapLocation(success,fail){const_self=this//定位成功回调constshowPosition=position=>{uni.setStorage({key:'positionData',data:position})success(position)}//定位失败回调constshowErr=(err)=>//如果获取定位失败超过3次抛出错误否则继续获取定位信息if(this.getPositionCount>3){fail('超过3次获取定位失败')}else{//定位失败递归_self.getPositionCount=_self.getPositionCount+1_self.getTMapLocation(success,fail)}}//调用腾讯web定位组件获取位置信息if(geolocation){geolocation.getIpLocation(showPosition,showErr,{timeout:6000,//定位超时时长单位msfailTipFlag:true})}}}exportdefaultnewTMap()
2. 在微信 webview 中, 通过微信sdk获取位置信息
2.1 微信 js-sdk 相关的准备工作
2.1.1 引入js文件
/***微信sdk异步加载*@param{*}src*@param{*}callbackapi接口*/exportconsthandlerLoadScript=callback=>{constsrc=`https://res.wx.qq.com/open/js/jweixin-1.4.0.js`if(!(typeofcallback==='function')){callback=function(){}}varcheck=document.querySelectorAll(`script[src="${src}"]`)if(check.length>0){check[0].addEventListener('load',function(){callback()})callback()return}varscript=document.createElement('script')varhead=document.getElementsByTagName('head')[0]script.type='text/javascript'script.charset='UTF-8'script.src=srcif(script.addEventListener){script.addEventListener('load',function(){callback()},false)}elseif(script.attachEvent){script.attachEvent('onreadystatechange',function(){vartarget=window.event.srcElementif(target.readyState==='loaded'){callback()}})}head.appendChild(script)}
2.1.2 注入权限验证配置
所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用。通常是通过后台接口获取配置信息。
/***注入权限验证配置*@param{object}微信js-sdk权限验证配置*/exportconstwxconfigInfo=config=>{wx.config({debug:false,//开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId:config.appId,timestamp:parseInt(config.timestamp),nonceStr:config.nonceStr,signature:config.signature,jsApiList:[//需要使用的jsapi列表...,'getLocation'//获取地理位置]})}
2.2 调用 api 获取位置信息
/***微信获取位置*/exportconsthandleGetLocation=(config)=>{returnnewPromise((resolve,reject)=>{wxconfigInfo(config)wx.ready(function(){wx.getLocation({type:'wgs84',//默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'success:function(res){console.warn('微信sdk定位成功',res)resolve({lat:res.latitude,//纬度lng:res.longitude,//经度speed:res.speed,//速度,以米/每秒计accuracy:res.accuracy//位置精度})},fail:function(err){console.error('微信sdk定位失败',err)reject(err)}})})wx.error(function(err){//config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。console.log('wxjsapi-error=',err)reject(`wxjsapi-error:${err}`)})})
2.3 根据不同运行环境调用不同的定位方法
//public.js/***UA枚举*/constUA={/***微信h6*/WECHAT:'WECHAT',/***支付宝h6*/ALIPAY:'ALIPAY',/***其他*/OTHERS:'OTHERS'}/***判断客户端运行环境这里只判断微信和浏览器h6*/exportconstgetUserAgent=()=>{varuserAgent=navigator.userAgent.toLowerCase()if(userAgent.match(/Alipay/i)=='alipay'){returnUA.ALIPAY}elseif(userAgent.match(/MicroMessenger/i)=='micromessenger'){returnUA.WECHAT}else{returnUA.OTHERS}}
//js-sdk.js/***唤起微信api*@param{*}_href当前页面url*@param{*}options分享信息*@param{*}apiType调用api类型*/exportconsthandleWXSDKCall=(_href,apiType,options)=>{returnnewPromise((resolve,reject)=>{//通过后台接口获取配置信息WeChatServivce.sign(_href).then(res=>{if(res){if(apiType==='location'){handleGetLocation(res).then((res)=>{resolve(res)}).catch(err=>{reject(err)})}}}).catch(err=>{reject(`err-sign:${err}`)uni.showToast({title:err.data.code+err.data.msg,mask:true,icon:'none'})})})}//getLocation.jsimport{getUserAgent,handlerLoadScript}from'@/module/utils'import{handleWXSDKCall}from'@/module/utils/wechat/wxJsApiSdk'importUAfrom'@/module/enums/userAgent'importTMapfrom'@/module/utils/tMap'/***对外暴露的获取位置方法*@returnPromiseresolve一个positionData对象lat-纬度lng-经度*/constgetLocation=()=>{returnnewPromise((resolve,reject)=>{console.log('进入全局获取用户位置方法')conststorageData=uni.getStorageSync('positionData')constuserAgent=getUserAgent()if(storageData){resolve(storageData)}else{//根据环境判断如果在微信内使用微信sdk其他使用腾讯地图定位组件if(userAgent===UA.WECHAT){handlerLoadScript(()=>{handleWXSDKCall(window.location.href,'location').then((res)=>{uni.setStorageSync('positionData',res)resolve(res)}).catch(err=>{reject(err)})})}else{TMap.getLocation().then(res=>{uni.setStorageSync('positionData',res)resolve(res)}).catch((err)=>{reject(err)})}}})}exportdefaultgetLocation
3. 页面调用
3.1 绑定方法到 Vue 原型上:
importgetLocationfrom'@/module/utils/getLocation'Vue.prototype.$getLocation=getLocation
3.2 在页面组件中调用:
onShow(){//获取位置信息后请求后台接口this.$getLocation().then(res=>{console.warn('首页获取位置成功',res)this.latitude=res.latthis.longitude=res.lng//这里根据获取到的经纬度请求后台接口...}).catch(err=>{console.error('首页获取位置失败',err)//错误处理})}
总结
遇到的坑以及需要注意的点:
使用微信sdk获取位置信息需要按顺序完成以下步骤:
异步加载微信sdk
通过接口获取配置信息,配置微信sdk
在wx.ready回调中调用方法
必须严格按顺序完成以上的三个步骤,否则是无法调用微信sdk的功能的。
感谢各位的阅读!关于“Html5中如何解决定位问题”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。