【前端探索】H5获取用户定位?看这一篇就够了

您所在的位置:网站首页 web地理定位 【前端探索】H5获取用户定位?看这一篇就够了

【前端探索】H5获取用户定位?看这一篇就够了

#【前端探索】H5获取用户定位?看这一篇就够了| 来源: 网络整理| 查看: 265

提出问题

由于现在做的是强依赖于LBS的业务,在业务迭代的两年间,我们遇到了无数关于Web页面上获取用户位置定位的问题:

为什么我开了app的定位授权,但是H5上却获取不到用户位置信息? 为什么我关了app的定位授权,但是H5上还是获取到了用户位置信息? 为什么我进页面的时候会弹H5的位置授权弹窗,这个弹窗上的文字可以改吗? 我拒绝了H5的位置授权弹窗,要怎么重新弹出来授权弹窗?

多年的踩坑经验,总结成了下面的文章,下面来好好回答这些问题。

web端的定位方式分类

web端定位的方式,大概可以分为下面三类:

H5原生:navigator.geolocation IP定位:用IP通过CGI接口获取定位 app定位:app获取定位再传给前端

基于这三类,我们可以采用下面方式这些来进行位置定位。

navigator.geolocation

H5的原生定位即navigator.geolocation。

腾讯地图前端定位组件

腾讯地图前端定位组件是基于navigator.geolocation做了一些封装,如果原生定位失败,会降级用ip获取定位,同时也对获取的位置信息做了一些缓存的优化。

腾讯地图IP定位API

通过CGI接口请求得到一个精确度比较低的位置信息。

微信的jssdk

微信提供了jssdk,H5可以直接调用获取到位置信息。本质上是通过jsbridge传递app获取到位置信息。同理,我们也可以通过url参数等其他方式,来传递app获取到的位置信息。

web端LBS定位.png

下面来详细讲一下各种定位方式的调用,为了方便使用,各种定位方法是对下面这个LocationInterface接口的实现:

// 经纬度,等位置信息 export interface LocationData { lat: number, lng: number, type?: string, } // 定位flag,标记定位返回结果的类型 export enum LocationFlag { LocationSuccss = 1, // gps定位,给精确定位 LocationIpSuccss = 2, // ip定位,给ip定位 LocationFailed = 3, // 定位失败,给默认定位 } // 返回的定位结果 export type LocationResult = { location: LocationData flag: LocationFlag }; // 不同定位场景需要实现的接口 export interface LocationInterface { getLocation(options?: LocationOptions): Promise; } 1. navigator.geolocation 文档

developer.mozilla.org/zh-CN/docs/…

使用方式 // H5原生的位置定位 export default class TencentMapApiLocation implements LocationInterface { getLocation(): Promise { return new Promise((resolve, reject) => { function geoShowPosition(position) { if (position) { const location = { lat: position.coords.latitude, lng: position.coords.longitude }; resolve({ location, flag: LocationFlag.LocationSuccss }); } else { reject(); } } function geoShowError(error) { console.log(`getPosError:${error.code},${navigator.geolocation},${error.message}`); reject(); } navigator.geolocation.getCurrentPosition(geoShowPosition, geoShowError); }); } } 优缺点 优点: 不依赖外部接口和组件,位置信息准确。 是否能获取到位置信息,与内嵌H5的app是否开启定位授权强相关,不会出现关闭定位授权,还能获取到定位的情况。 缺点: 用户拒绝H5的授权弹窗后,需要用户重置系统权限才能获取到定位授权(重新开启app的授权设置也是没用的)。 H5的定位授权弹窗的是浏览器弹出的,文案不能自定义,没办法在这个弹窗向用户说明获取位置信息是用在什么地方。 适用场景

navigator.geolocation适用于大多数的获取定位的场景,而且其能否获取到定位,完全和用户是否给app开启位置授权有关,不用担心app在合规检查中出现问题。

回答上面的问题

问题1.为什么我开了app的定位授权,但是H5上却获取不到用户位置定位信息?

这是因为H5调用navigator.geolocation获取定位,除了需要app开启授权,还需要“浏览器的授权”。

问题3.为什么我进页面的时候会弹H5的定位授权弹窗,这个弹窗上的文字可以改吗?

不能。

问题4.我拒绝了H5的定位授权弹窗,要怎么再弹出来授权弹窗?

移动端浏览器的授权弹窗被用户拒绝后,需要“重置系统的定位设置”,才能重新弹出这个弹窗。

在iOS,重置定位权限的操作路径是:系统-通用-还原-还原位置和隐私。

2. 腾讯地图前端定位组件 文档

lbs.qq.com/webApi/comp…

使用方式 // 用腾讯地图sdk获取位置 export default class TencentMapLocation implements LocationInterface { public getLocation(options: LocationOptions): Promise { return new Promise((resolve, reject) => { function geoShowPosition(location) { resolve({ location, flag: LocationFlag.LocationSuccss }); } function geoShowError() { reject(); } loader('https://3gimg.qq.com/lightmap/components/geolocation/geolocation.min.js', () => { // eslint-disable-next-line no-undef const geolocation = new (window as any).qq.maps.Geolocation( tencentMapConfig.GEO_KEY, tencentMapConfig.GEO_REFERER, ); const tencentMapOptions = { timeout: options.timeout, }; geolocation.getLocation(geoShowPosition, geoShowError, tencentMapOptions); }); }); } } 优缺点 优点 腾讯地图前端定位组件是在原生H5定位的基础上做了一下优化,包括对获取的位置信息做了缓存,当原生H5定位失败的时候(用户未授权app权限或者拒绝了授权弹窗),会降级使用IP定位。 和原生相比,获取信息的成功率会有一定的提高。 缺点 用户是否能获取到位置信息,与是否开启app的定位授权不是强相关的。用户关闭了app的定位授权,仍然可以通过缓存和ip定位获取到位置信息。 因为是优先使用H5原生定位,依然会弹出H5的定位授权弹窗。 适用场景

适用于对LBS依赖比较高的业务,在几种定位方式中,是首选的定位方式。

由于位置信息的获取,与用户是否授权app不强相关,在合规检查中可能会有风险。

回答上面的问题

问题2. 为什么我关了app的定位授权,但是H5上还是获取到了用户位置信息?

由于腾讯地图前端定位组件的优化,在用户关闭app定位授权的时候,依旧可以通过ip定位和缓存获取到位置信息。

由于我们的业务是嵌入在多个app中,最近经常需要配合app修改页面以通过合规检查,常用的修改方案是改用navigator.geolocation获取位置信息,或者直接用app获取的位置信息。

3. 微信sdk定位 文档

developers.weixin.qq.com/doc/offiacc…

使用方式 // 用微信sdk获取用户位置信息 export default class WechatSdkLocation implements LocationInterface { public getLocation(): Promise { return new Promise((resolve, reject) => { configWx(['getLocation', 'openLocation'], []).then((wx) => { const tmp = { type: 'gcj02', success(res) { const location = { lat: parseFloat(res.latitude), lng: parseFloat(res.longitude), }; resolve({ location, flag: LocationFlag.LocationSuccss }); }, fail(error) { console.log('WechatSdkLocation', error); reject(); }, }; wx.getLocation(tmp); }) .catch((error) => { console.log('WechatSdkLocation', error); reject(); }); }); } } 优缺点 优点 速度快,精确度高,成功率高 不会有定位授权弹窗。 是否能获取到位置信息,完全和app是否授权相关。 缺点 没有,在微信webview直接用这个就好了。 适用场景

只有微信webview。

使用前需要注入微信js-sdk的配置信息。

在其他app中使用

这种定位方式的本质是直接使用app的定位能力,同理在其他的app中,我们也可以用类似的方式来获取位置信息。需要做的就是app和H5之间的消息传递,通过url参数、jsBridge等等,实现的方式很多。

4. 腾讯地图API的IP定位 文档

lbs.qq.com/service/web…

使用方式 // 用腾讯地图api通过IP获取用户位置信息 export default class TencentMapApiLocation implements LocationInterface { public getLocation(): Promise { return new Promise((resolve, reject) => { axios.get(`https://apis.map.qq.com/ws/location/v1/ip?key=${tencentMapConfig.GEO_KEY}`).then((res) => { const result = (res?.data?.result) || {}; const location = (result?.location) || {}; if (location) { resolve({ location, flag: LocationFlag.LocationIpSuccss }); } else { reject(); } }) .catch((error) => { console.log('TencentMapApiLocation', error); reject(); }); }); } } 优缺点 优点 成功率高 不需要H5授权弹窗,不需要app授权 缺点 精确度低,一般都只有市级的经纬度 API接口的请求次数有限额,企业用户可以申请到300w次/日的配额。 适用场景

适用于对精确度要求不高的业务,IP定位一般在服务端使用,可以作为其他定位方法的降级方案,如果前端获取不到用户位置信息,服务端再用ip定位去拉取LBS业务的数据。

由于有限额,服务端可以对单个ip的位置信息做一下缓存优化,减少配额的使用。

封装一下

业务开发的时候,我们当然不希望去考虑上面那么多。我需要位置信息,调用组件接口,拿到位置信息,就可以了。

我们再来把上面提到的这些方案,做一下封装,对外只需要暴露一个getLocation接口。

/** * @module Location 位置定位 * @description 定位工具,支持原生H5定位、腾讯地图定位、微信的sdk定位、ip定位 */ class Location { public static locationFlag = LocationFlag; private static instance: Location = new Location(); private static env; public static getInstance() { return this.instance; } /** * 获取定位信息 * @exports getLocation * @param {object} options 定位参数 * @param {number} options.timeout 定位超时时间 * @param {boolean} options.useWxSdk 在微信环境下,是否优先使用微信Sdk定位 * @param {boolean} options.useTencentMapApi 是否使用腾讯地图api进行IP定位 * @param {boolean} options.useH5Geolocation 是否使用原生IP定位 * @param {boolean} options.cache 是否缓存,推荐使用 */ public static getLocation(options: LocationOptions) { // 填充默认数据 // ... return new Promise((resolve, reject) => { // 使用sessionStorage存储的位置信息 // ...处理缓存的一些逻辑 // 示例化不同场景的定位组件 if (options.useWxSdk && Location.env.isWeixin) { this.getInstance().locationHandle = new WechatSdkLocation(); } else if (options.useTencentMapApi) { this.getInstance().locationHandle = new TencentMapApiLocation(); } else if (options.useH5Geolocation) { this.getInstance().locationHandle = new H5GeolocationLocation(); } this.getInstance().locationHandle.getLocation(options).then((res) => { resolve(res); // 缓存位置信息 // ...保存位置信息 }) .catch((error) => { reject(error); }); }); } private locationHandle: LocationInterface; constructor() { Location.env = initEnv(); this.locationHandle = new TencentMapLocation(); } } demo工程

本文源码:github.com/luciozhang/…

如果对您有帮助,劳烦点个小星星🌟。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3