前端定位组件更新公告: 为了提升前端定位组件定位能力,同时提升前端定位组件的体验、规范定位组件服务的使用,防止公用额度占满造成调用失效影响业务,请各位开发者尽快升级到新版本,旧版本将逐步关停;
前端定位组件,旨在优化纯HTML5 Geolocation定位能力弱,定位成功率不高的问题,提供简单、易用的接口帮助业务层获取用户当前的位置信息(需用户授权),以降低开发成本,提升定位精准度。 说明:由于微信7.0版本升级了对https的安全限制,在微信7.0版本及以上版本使用http协议访问定位组件会导致定位失败。开发者如遇到上述问题,请切换至https协议访问。
前端定位组件依赖WebService API服务,在调用前请确保传入的key已分配以下WebService API服务额度;
| 服务名 | 相关功能点 | 官方文档 |
|---|---|---|
| 逆地址解析 | 由经纬度到文字地址及相关位置信息能力 | https://lbs.qq.com/service/webService/webServiceGuide/address/Gcoder |
| IP定位 | 在其他定位方式失效时IP定位获取位置 | https://lbs.qq.com/service/webService/webServiceGuide/position/webServiceIp |
| 坐标转换 | 标准GPS坐标系转换到腾讯地图坐标系 | https://lbs.qq.com/service/webService/webServiceGuide/webServiceTranslate |
引入封装好的静态JS文件,通过多种经纬度获取方法,并配合调用WebserviceAPI服务获取,让定位效率和准确性更出色。本方式JS文件资源形式改为了CDN维护,能够支撑更大量级的访问量;另外,本方式的调用日志更加健全,在排查问题的时候能够更加高效且精准的定位并解决问题。
js引入地址:https://mapapi.qq.com/web/lbs/h5-components/geolocation/geolocation.min.js
| 构造函数 | 说明 |
|---|---|
window.LBS.WebComponent.Geolocation({key, referer, domain}) |
参数说明: - key:选填(与domain二选一必填),开发密钥(key),可在腾讯位置服务官网申请注册- referer:必填,调用来源(应用名称),示例:referer=mapqq- domain:选填(与key二选一必填),开发者代理服务的域名 |
| 方法 | 返回值 | 说明 |
|---|---|---|
| getLocation(sucCallback, errCallback, [options: {timeout?: number, highAccuracy?: boolean, maximumAge?: number}]) | 获取当前所在地理位置,调用一次即重新定位一次,定位数据比较精确。 sucCallback为定位成功回调函数,必填; errCallback为定位失败回调函数,选填,如果不填,请设为null; options为定位选项,选填,具体可配置项如下: ● timeout:定位的超时时间(单位为毫秒),默认值为5000(即5秒); ● highAccuracy: 是否进行严格的高精度定位,若为true则在高精度获取失败时不会进行IP兜底; ● maximumAge: 浏览器原生API navigator.geolocation.getCurrentPosition配置项,用于控制获取经纬度的缓存时间,默认为0。 |
|
| getIpLocation(sucCallback, [errCallback]) | 立即获取当前所在地理位置,适用于非精确定位场景,是IP定位,城市级别。 sucCallback为定位成功回调函数,必填; errCallback为定位失败回调函数,选填。 |
|
| watchPosition(sucCallback, [options: {timeout: number, highAccuracy: boolean}]) | 监听位置信息的改变,类似HTML5 Geolocation的watchPosition。 sucCallback为定位成功回调函数,必填; options为定位选项,选填,具体可配置项如下: ● timeout:定位的超时时间(单位为毫秒),默认值为5000(即5秒); ● highAccuracy: 是否进行严格的高精度定位,若为true则在高精度获取失败时不会进行IP兜底。 ● maximumAge: 浏览器原生API navigator.geolocation.getCurrentPosition配置项,用于控制获取经纬度的缓存时间,默认为0。 |
|
| clearWatch() | 清除监听,类似HTML5 Geolocation的clearWatch。 |
| 属性 | 类型 | 说明 |
|---|---|---|
| nation | string | 国家 |
| province | string | 省份 |
| city | string | 城市 |
| district | string | 区县 |
| adcode | string | 行政区划代码,规则详见:腾讯位置服务行政区划文档 |
| addr | string | 详细地址 |
| lat | number | 纬度 |
| lng | number | 经度 |
| accuracy | number | 定位精确度 |
| gcoder_request_id | string | 逆地址解析的请求id(非必有) |
| ip_request_id | string | IP定位的请求id(非必有) |
| module | ‘geolocation’ | 固定字符串,表示数据为前端定位组件返回值 |
| type | CoreType | 获取经纬度的具体定位方式,详见CoreType |
| logs | { status: PositionStatus, type: CoreType }[] | 不同定位类型的定位情况 |
| 属性 | 类型 | 说明 |
|---|---|---|
| status | PositionStatus | 定位状态码,用于排查定位失败的原因 |
| message | string | 错误信息,为空字符串时请根据status查看失败原因 |
| logs | { status: PositionStatus; message: string; type?: CoreType }[] | 完整定位日志,会返回定位过程中各个节点的定位情况 |
| 枚举值 | 说明 |
|---|---|
| h5 | 基于浏览器原生API navigator.geolocation.getCurrentPosition获取的经纬度,详见:MDN文档 |
| wx | 基于微信JSSDK获取的经纬度,详见:微信文档 |
| 基于QQ能力获取的经纬度 | |
| x5 | 基于QQ浏览器提供的API获取的经纬度 |
| ip | 基于IP定位获取的经纬度,详见:腾讯位置服务IP定位 |
| 枚举值 | 说明 |
|---|---|
| 10000 | 定位成功 |
| 10001 | 所有获取经纬度的方式均失败 |
| 10002 | 所有定位途径均超时 |
| 10101 | 浏览器原生API - 地理位置信息的获取失败,因为该页面没有获取地理位置信息的权限 |
| 10102 | 浏览器原生API - 地理位置获取失败,因为至少有一个内部位置源返回一个内部错误 |
| 10103 | 浏览器原生API - 获取地理位置超时 |
| 10104 | 浏览器原生API - 所用浏览器不支持该API |
| 10201 | 微信JSSDK - 定位失败 |
| 10202 | 微信JSSDK - 页面未加载SDK |
| 10203 | 微信JSSDK - 页面已加载SDK但不支持wx.getLocation方法 |
| 10301 | QQ定位 - SDK未加载成功 |
| 10302 | QQ定位 - 未获取经纬度授权 |
| 10303 | QQ定位 - 未开启传感器 |
| 10304 | QQ定位 - 未知错误 |
| 10305 | QQ定位 - 用户拒绝授权 |
| 10306 | QQ定位 - SDK不支持getLocation |
| 10307 | QQ定位 - iframe加载失败 |
| 10401 | QQ浏览器API - 定位失败 |
| 10402 | QQ浏览器API - 定位超时 |
| 10501 | IP定位 - 定位失败 |
| 10502 | IP定位 - 定位超时 |
| 10601 | 逆地址解析服务报错 |
| 10602 | 坐标转换服务报错 |
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>H5定位组件Demo - 调用方式一</title>
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
/>
<style>
* {
margin: 0;
padding: 0;
border: none;
}
body {
width: 100%;
height: 100%;
font-size: 16px;
}
#map-el {
width: 100vw;
height: 100vh;
}
.buttons {
position: absolute;
left: 10px;
top: 10px;
z-index: 99999;
display: flex;
flex-direction: column;
align-items: stretch;
gap: 10px;
padding: 10px;
}
button {
padding: 8px 6px;
border-radius: 8px;
background-color: rgba(255, 132, 132, 0.9);
color: white;
cursor: pointer;
}
#watch-status {
padding: 8px 6px;
border-radius: 8px;
background-color: rgba(255, 132, 132, 0.9);
color: white;
}
</style>
<script src="https://mapapi.qq.com/web/lbs/h5-components/geolocation/geolocation.min.js"></script>
<script src="https://map.qq.com/api/gljs?v=1.exp&key=[your key]"></script>
</head>
<body>
<div id="map-el"></div>
<div class="buttons">
<button onClick="getLocation()">getLocation</button>
<button onClick="getIpLocation()">getIpLocation</button>
<button onClick="watchPosition()">watchPosition</button>
<button onClick="clearWatch()">clearWatch</button>
<span id="watch-status">位置监听状态:关</span>
</div>
<script>
/** LBS申请的key */
const key = '[your key]';
/** 项目标识 */
const referer = 'h5-geolocation-demo-4';
/** 定位组件实例 */
const geoInstance = new window.LBS.WebComponent.Geolocation({ key, referer });
/** 精确定位配置项 */
const options = { timeout: 6000, highAccuracy: true };
/** 地图实例 */
const map = new window.TMap.Map(document.querySelector('#map-el'));
/** 地图marker图层 */
const markerLayer = new window.TMap.MultiMarker({ id: 'markers', map });
/** 展示定位结果 */
const onSuccess = (result) => {
console.log('>>> 定位成功回调数据', result);
const { lat, lng } = result;
const origin = new window.TMap.LatLng(lat, lng);
markerLayer.setGeometries([{ id: 1, position: origin }]);
map.easeTo({ center: origin, zoom: 17 });
};
/** 失败回调 */
const onError = (error) => console.log('>>> 定位失败回调数据', error);
/** 高精定位 */
const getLocation = () => geoInstance.getLocation(onSuccess, onError, options);
/** IP定位 */
const getIpLocation = () => geoInstance.getIpLocation(onSuccess, onError);
const watchStatusDOM = document.querySelector('#watch-status');
/** 开启定位监听 */
const watchPosition = () => {
geoInstance.watchPosition(onSuccess, onError, options);
watchStatusDOM.innerHTML = '位置监听状态:开';
};
/** 结束定位监听 */
const clearWatch = () => {
geoInstance.clearWatch();
watchStatusDOM.innerHTML = '位置监听状态:关';
};
</script>
</body>
</html>
将方式一的JS资源封装成html文件形式,方便需要在iframe中使用的场景。
<iframe src="https://mapapi.qq.com/web/lbs/h5-components/geolocation/geolocation.html?key=[your key]
&referer=[your referer]&immediate=[0 | 1]" width="0" height="0" frameborder="none" scrolling="no"
style="display: none" allow="geolocation *" />
</iframe>
| 参数名 | 必填 | 参数说明 |
|---|---|---|
| key | 否(domain或key必填其一) | 开发密钥(key),可在腾讯位置服务官网申请注册 |
| domain | 否(domain或key必填其一) | 开发者代理服务的域名 |
| referer | 是 | 调用来源,一般为您的应用名称,为了保障对您的服务,请务必填写! |
| immediate | 否 | 传入为1时会在iframe加载完成后立刻触发一次getLocation,默认为1 |
父页面通过调用iframe页面的contentWindow.postMessage方法来告知iframe进行定位,本调用方式支持两种调用传值方式,具体如下: 传值方式一:入参为方法名字字符串,该方式适合在不用传入其他配置项时使用
const iframeDOM = document.querySelector('iframe');
iframeDOM.contentWindow.postMessage('getIpLocation', '*');
传值方式二:入参为Object对象,对象传递两个属性,分别是“func”用于告知iframe调用的函数名、“options”告知iframe调用的函数具体的配置项,该方式适合在需要传入函数配置项时使用
const iframeDOM = document.querySelector('iframe')
iframeDOM.contentWindow.postMessage({ func: 'getLocation', options: {timeout: 8000, highAccuracy: true} }, '*')
在完成上述“调用iframe函数”后,iframe会调用被告知的函数,并将函数执行结果通过message事件传递给父页面,因此需要在父页面对message事件进行监听处理,iframe具体会在事件的data中传递三个属性:"source"用于标识本次message事件是由定位组件触发(具体传值为’lbs-geolocation’)、"func"用于标识本次定位结果是执行哪个函数的结果、"result"用于传递本次执行的具体结果,示例代码如下:
window.addEventListener('message', ({ data }) => {
if(data?.source !== 'lbs-geolocation' && !data?.func) {
return;
}
switch(data.func) {
// 返回的是getLocation方法的执行结果
case 'getLocation':
// 返回的是getIpLocation方法的执行结果
case 'getIpLocation':
// 返回的是getIpLocation方法的执行结果
case 'watchPosition': {
const { result } = data
result?.module ? onSuccess(result) : onError(result)
break;
}
// 未知类型可以打印查看
default: {
console.log('Unknown Function: ', data.func, data);
break;
}
}
})
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>H5定位组件Demo - 调用方式二</title>
<meta
name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"
/>
<style>
* {
margin: 0;
padding: 0;
border: none;
}
body {
width: 100%;
height: 100%;
font-size: 16px;
}
#map-el {
width: 100vw;
height: 100vh;
}
.buttons {
position: absolute;
left: 10px;
top: 10px;
z-index: 99999;
display: flex;
flex-direction: column;
align-items: stretch;
gap: 10px;
padding: 10px;
}
button {
padding: 8px 6px;
border-radius: 8px;
background-color: rgba(255, 132, 132, 0.9);
color: white;
cursor: pointer;
}
#watch-status {
padding: 8px 6px;
border-radius: 8px;
background-color: rgba(255, 132, 132, 0.9);
color: white;
}
</style>
<script src="https://map.qq.com/api/gljs?v=1.exp&key=[your key]"></script>
</head>
<body>
<div id="map-el"></div>
<div class="buttons">
<button onClick="getLocation()">getLocation</button>
<button onClick="getIpLocation()">getIpLocation</button>
<button onClick="watchPosition()">watchPosition</button>
<button onClick="clearWatch()">clearWatch</button>
<span id="watch-status">位置监听状态:关</span>
</div>
<script>
/** 地图实例 */
const map = new window.TMap.Map(document.querySelector('#map-el'));
/** 地图marker图层 */
const markerLayer = new window.TMap.MultiMarker({ id: 'markers', map });
/** LBS申请的key */
const key = '[your key]';
/** 项目标识 */
const referer = 'h5-geolocation-demo-4';
/** 立即触发标识 */
const immediate = 1;
/** iframeDOM */
const iframeDOM = document.createElement('iframe');
iframeDOM.width = 0;
iframeDOM.height = 0;
iframeDOM.src = `https://mapapi.qq.com/web/lbs/h5-components/geolocation/geolocation.html?key=${key}&referer=${referer}&immediate=${immediate}&v=${Date.now()}`;
iframeDOM.allow = 'geolocation *';
/** 展示定位结果 */
const onSuccess = (result) => {
console.log('>>> 定位成功回调数据', result);
const { lat, lng } = result;
const origin = new window.TMap.LatLng(lat, lng);
markerLayer.setGeometries([{ id: 1, position: origin }]);
map.easeTo({ center: origin, zoom: 17 });
};
/** 失败回调 */
const onError = (error) => console.log('>>> 定位失败回调数据', error);
window.addEventListener('message', ({ data }) => {
if (data?.source !== 'lbs-geolocation' && !data?.func) {
return;
}
switch (data.func) {
// 返回的是getLocation方法的结果
case 'getLocation':
// 返回的是getIpLocation的结果
case 'getIpLocation':
// 返回的是watchPosition的结果
case 'watchPosition': {
const { result } = data;
result?.module ? onSuccess(result) : onError(result);
break;
}
// 未知类型可以打印查看
default: {
console.log('data.func', data.func);
break;
}
}
});
document.body.appendChild(iframeDOM);
const onPost = (payload) => iframeDOM.contentWindow.postMessage(payload, '*');
const getLocation = () => onPost({ func: 'getLocation', options: { timeout: 5000, highAccuracy: true } });
const getIpLocation = () => onPost('getIpLocation');
const watchStatusDOM = document.querySelector('#watch-status');
const watchPosition = () => {
onPost('watchPosition');
watchStatusDOM.innerHTML = '位置监听状态:开';
};
const clearWatch = () => {
onPost('clearWatch');
watchStatusDOM.innerHTML = '位置监听状态:关';
};
</script>
</body>
</html>
有帮助
没帮助