关于微信7.0更新后部分机型调用定位组件失败的公告 由于微信7.0版本升级了对https的安全限制,在微信7.0版本及以上版本使用http协议访问定位组件会导致定位失败。 开发者如遇到上述问题,请切换至https协议访问。给您带来的不便深感抱歉!
前端定位组件
前端定位组件,旨在优化纯HTML5 Geolocation定位能力弱,定位成功率不高的问题,提供简单、易用的接口帮助业务层获取用户当前的位置信息(需用户授权),以降低开发成本,提升定位精准度。
调用示例
调用方式一
引入封装好的JS模块,调起前端定位组件,通过封装好的接口获取位置信息。相比方式二此方式更加简单快捷。
代码地址
js引入地址:https://mapapi.qq.com/web/mapComponents/geoLocation/v/geolocation.min.js
参考类:qq.maps.Geolocation
构造函数 | 说明 |
---|---|
qq.maps.Geolocation(key, referer) | 参数: key : 必填,开发密钥(key),申请地址 https://lbs.qq.com/dev/console/key/manage referer: 必填,调用来源,一般为您的应用名称,为了保障对您的服务,请务必填写!例如: referer=mapqq |
方法 | 返回值 | 说明 |
---|---|---|
getLocation(sucCallback, errCallback, [options: {timeout: number, failTipFlag: boolean}]) | 获取当前所在地理位置,调用一次即重新定位一次,定位数据比较精确。sucCallback为定位成功回调函数,必填; errCallback为定位失败回调函数,选填,如果不填,请设为null; options为定位选项,选填,可以通过timeout参数设置定位的超时时间,默认值为10s; failTipFlag: 是否在定位失败时给出提示引导用户打开授权或打开定位开关。(即将支持) | |
getIpLocation(sucCallback, [errCallback]) | 立即获取当前所在地理位置,适用于非精确定位场景,是IP定位,城市级别。sucCallback为定位成功回调函数,必填; errCallback为定位失败回调函数,选填。 | |
watchPosition(sucCallback) | 监听位置信息的改变,类似HTML5 Geolocation的watchPosition。sucCallback为定位成功回调函数,必填。 | |
clearWatch() | 清除监听,类似HTML5 Geolocation的clearWatch。 |
完整示例
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>前端定位模块</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: 0;
}
body {
position: absolute;
width: 100%;
height: 100%;
text-align: center;
}
#pos-area {
background-color: #009DDC;
margin-bottom: 10px;
width: 100%;
overflow: scroll;
text-align: left;
color: white;
}
#demo {
padding: 8px;
font-size: small;
}
#btn-area {
height: 100px;
}
button {
margin-bottom: 10px;
padding: 12px 8px;
width: 42%;
border-radius: 8px;
background-color: #009DDC;
color: white;
}
</style>
<script type="text/javascript" src="https://mapapi.qq.com/web/mapComponents/geoLocation/v/geolocation.min.js"></script>
</head>
<body>
<div id="pos-area">
<p id="demo">点击下面的按钮,获得对应信息:<br /></p>
</div>
<div id="btn-area">
<button onClick="geolocation.getLocation(showPosition, showErr, options)">获取精确定位信息</button>
<button onClick="geolocation.getIpLocation(showPosition, showErr)">获取粗糙定位信息</button>
<button onClick="showWatchPosition()">开始监听位置</button>
<button onClick="showClearWatch()">停止监听位置</button>
</div>
<script type="text/JavaScript">
var geolocation = new qq.maps.Geolocation("your key", "myapp");
document.getElementById("pos-area").style.height = (document.body.clientHeight - 110) + 'px';
var positionNum = 0;
var options = {timeout: 8000};
function showPosition(position) {
positionNum ++;
document.getElementById("demo").innerHTML += "序号:" + positionNum;
document.getElementById("demo").appendChild(document.createElement('pre')).innerHTML = JSON.stringify(position, null, 4);
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
function showErr() {
positionNum ++;
document.getElementById("demo").innerHTML += "序号:" + positionNum;
document.getElementById("demo").appendChild(document.createElement('p')).innerHTML = "定位失败!";
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
function showWatchPosition() {
document.getElementById("demo").innerHTML += "开始监听位置!<br /><br />";
geolocation.watchPosition(showPosition);
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
function showClearWatch() {
geolocation.clearWatch();
document.getElementById("demo").innerHTML += "停止监听位置!<br /><br />";
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
</script>
</body>
</html>
调用方式二
通过内嵌一个隐藏iframe的方式调用该组件,前端定位组件在获取到用户的精准位置信息后,会通过html5 postMessage的方式回传用户的位置信息,开发者需要在自己的页面中实现一个监听函数。前端定位组件在加载完后会自动开启异步定位,定位成功或失败都会触发message事件通知业务调用方。定位所需的耗时不固定,跟用户实际的客户端环境有关。正常情况下在1-3s,网络较差时需要时间较长。
HTML结构
<iframe id="geoPage" width=0 height=0 frameborder=0 style="display:none;" scrolling="no"
src="https://apis.map.qq.com/tools/geolocation?key=your key&referer=myapp">
</iframe>
调用参数
参数名 | 必填 | 参数说明 | 示例 |
---|---|---|---|
key | 是 | 开发密钥(key) | key=your key特别说明:若您的key已设置webservice域名白名单,请在 白名单 中增加本组件域名 |
effect | 否 | 前端定位组件在定位过程中的视觉效果。若使用隐藏的iframe调用该组件,可不传该参数 | effect=zoom:呼吸圆圈动画(如上图左)effect=circle:彩色圆圈动画(如上图右) |
referer | 是 | 调用来源,一般为您的应用名称,为了保障对您的服务,请务必填写! | referer=myapp |
在父页面监听message事件
window.addEventListener('message', function(event) {
// 接收位置信息
var loc = event.data;
console.log('location', loc);
}, false);
当在页面中嵌入前端定位组件后,自动触发前端定位组件,定位消息返回后,触发监听事件。 特别提醒: 定位组件在首次定位成功 或 首次定位失败后,还会继续尝试定位,如果后续获取到精度更高的位置信息,还会继续触发父页面接收定位信息的message事件。业务层请勿在回调函数里直接使用var map = new qq.maps.Map() 否则有可能导致页面创建出多个地图对象。
定位成功时返回的结果
{ "module":"geolocation",
"nation": "中国",
"province": "广东省",
"city":"深圳市",
"district":"南山区",
"adcode":"440305", //行政区ID,六位数字, 前两位是省,中间是市,后面两位是区,比如深圳市ID为440300
"addr":"深圳大学杜鹃山(白石路北250米)",
"lat":22.530001, //火星坐标(gcj02),腾讯、Google、高德通用
"lng":113.935364,
"accuracy":13 //误差范围,以米为单位
}
注意:若定位失败,同样会触发message事件,但返回的event.data为null; 定位失败时,返回时间是不确定的,建议业务调用方可以根据自己的业务场景设置超时逻辑(例如:可以设置6s超时后认为定位失败)。
主动与前端定位组件通信(可选)
在某些场景下,业务调用方可能需要主动跟定位组件通信,比如再次获取用户的位置信息,或者在定位失败的情况下获取粗糙的IP定位结果,可以通过html5 postMessage的方式主动与定位组件发起通信,前端定位组件支持的通信事件有:
- getLocation: 获取当前所在地理位置,调用一次即重新定位一次,定位数据比较精确。
- getLocation.robust: 立即获取当前所在地理位置,适用于非精确定位场景,是IP定位,城市级别。
- watchPosition: 监听位置信息的改变,类似HTML5 Geolocation的watchPosition
- clearWatch: 清除监听,类似HTML5 Geolocation的clearWatch
document.getElementById("geoPage").contentWindow
.postMessage("getLocation", "*");
在不同的网络环境下,获取到定位的时间是不确定的。如果要获得一个精确定位,选用getLocation如果要立即获得一个粗糙定位,选用getLocation.robust
完整示例
在该示例中,页面内嵌了两个iframe, 一个是前端定位组件,另一个是位置展示组件。在前端定位组件定位成功后,会将结果post给父页面,父页面获取到经纬度后,再动态拼接位置展示组件的URL,在地图上标注用户的当前位置。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Geolocation Components Demo - zoom effect</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: 0;}
body {
position: absolute;
width: 100%;
height: 100%;
}
#geoPage, #markPage {
position: relative;
}
</style>
</head>
<body>
<!-- 通过 iframe 嵌入前端定位组件,此处没有隐藏定位组件,使用了定位组件的在定位中视觉特效 -->
<iframe id="geoPage" width="100%" height="30%" frameborder=0 scrolling="no" allow="geolocation"
src="https://apis.map.qq.com/tools/geolocation?key=your key&referer=myapp&effect=zoom"></iframe>
<script type="text/JavaScript">
var loc;
var isMapInit = false;
//监听定位组件的message事件
window.addEventListener('message', function(event) {
loc = event.data; // 接收位置信息
console.log('location', loc);
if(loc && loc.module == 'geolocation') { //定位成功,防止其他应用也会向该页面post信息,需判断module是否为'geolocation'
var markUrl = 'https://apis.map.qq.com/tools/poimarker' +
'?marker=coord:' + loc.lat + ',' + loc.lng +
';title:我的位置;addr:' + (loc.addr || loc.city) +
'&key=your key&referer=myapp';
//给位置展示组件赋值
document.getElementById('markPage').src = markUrl;
} else { //定位组件在定位失败后,也会触发message, event.data为null
alert('定位失败');
}
/* 另一个使用方式
if (!isMapInit && !loc) { //首次定位成功,创建地图
isMapInit = true;
createMap(event.data);
} else if (event.data) { //地图已经创建,再收到新的位置信息后更新地图中心点
updateMapCenter(event.data);
}
*/
}, false);
//为防止定位组件在message事件监听前已经触发定位成功事件,在此处显示请求一次位置信息
document.getElementById("geoPage").contentWindow.postMessage('getLocation', '*');
//设置6s超时,防止定位组件长时间获取位置信息未响应
setTimeout(function() {
if(!loc) {
//主动与前端定位组件通信(可选),获取粗糙的IP定位结果
document.getElementById("geoPage")
.contentWindow.postMessage('getLocation.robust', '*');
}
}, 6000); //6s为推荐值,业务调用方可根据自己的需求设置改时间,不建议太短
</script>
<!-- 接收到位置信息后 通过 iframe 嵌入位置标注组件 -->
<iframe id="markPage" width="100%" height="70%" frameborder=0 scrolling="no" src=""></iframe>
</body>
</html>
调用方式三
引入封装好的JS文件,通过调用js api的接口获取定位信息。对比前两种iframe的获取方式,优化了定位时长的体验。
代码地址
js引入地址:https://apis.map.qq.com/tools/geolocation/min?key=yourkey&referer=myapp
参考类:qq.maps.Geolocation
构造函数 | 说明 |
---|---|
qq.maps.Geolocation(key, referer) | 参数: key : 必填,开发密钥(key),申请地址 /dev/console/key/manage referer: 必填,调用来源,一般为您的应用名称,为了保障对您的服务,请务必填写!例如: referer=mapqq |
方法 | 返回值 | 说明 |
---|---|---|
getLocation(sucCallback, errCallback, [options: {timeout: number, failTipFlag: boolean}]) | 获取当前所在地理位置,调用一次即重新定位一次,定位数据比较精确。sucCallback为定位成功回调函数,必填; errCallback为定位失败回调函数,选填,如果不填,请设为null; options为定位选项,选填,可以通过timeout参数设置定位的超时时间,默认值为10s; failTipFlag: 是否在定位失败时给出提示引导用户打开授权或打开定位开关。(即将支持) | |
getIpLocation(sucCallback, [errCallback]) | 立即获取当前所在地理位置,适用于非精确定位场景,是IP定位,城市级别。sucCallback为定位成功回调函数,必填; errCallback为定位失败回调函数,选填。 | |
watchPosition(sucCallback) | 监听位置信息的改变,类似HTML5 Geolocation的watchPosition。sucCallback为定位成功回调函数,必填。 | |
clearWatch() | 清除监听,类似HTML5 Geolocation的clearWatch。 |
完整示例
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>前端定位模块</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: 0;
}
body {
position: absolute;
width: 100%;
height: 100%;
text-align: center;
}
#pos-area {
background-color: #009DDC;
margin-bottom: 10px;
width: 100%;
overflow: scroll;
text-align: left;
color: white;
}
#demo {
padding: 8px;
font-size: small;
}
#btn-area {
height: 100px;
}
button {
margin-bottom: 10px;
padding: 12px 8px;
width: 42%;
border-radius: 8px;
background-color: #009DDC;
color: white;
}
</style>
<script type="text/javascript" src="https://apis.map.qq.com/tools/geolocation/min?key=your key&referer=myapp"></script>
</head>
<body>
<div id="pos-area">
<p id="demo">点击下面的按钮,获得对应信息:<br /></p>
</div>
<div id="btn-area">
<button onClick="getCurLocation()">获取精确定位信息</button>
<button onClick="geolocation.getIpLocation(showPosition, showErr)">获取粗糙定位信息</button>
<button onClick="showWatchPosition()">开始监听位置</button>
<button onClick="showClearWatch()">停止监听位置</button>
</div>
<script type="text/JavaScript">
var geolocation = new qq.maps.Geolocation();
document.getElementById("pos-area").style.height = (document.body.clientHeight - 110) + 'px';
var options = {timeout: 9000};
var positionNum = 0;
function getCurLocation() {
geolocation.getLocation(showPosition, showErr, options);
}
function showPosition(position) {
positionNum ++;
document.getElementById("demo").innerHTML += "序号:" + positionNum;
document.getElementById("demo").appendChild(document.createElement('pre')).innerHTML = JSON.stringify(position, null, 4);
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
function showErr() {
positionNum ++;
document.getElementById("demo").innerHTML += "序号:" + positionNum;
document.getElementById("demo").appendChild(document.createElement('p')).innerHTML = "定位失败!";
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
function showWatchPosition() {
document.getElementById("demo").innerHTML += "开始监听位置!<br /><br />";
geolocation.watchPosition(showPosition);
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
function showClearWatch() {
geolocation.clearWatch();
document.getElementById("demo").innerHTML += "停止监听位置!<br /><br />";
document.getElementById("pos-area").scrollTop = document.getElementById("pos-area").scrollHeight;
};
</script>
</body>
</html>
预览
demo1: effect=zoom | demo2: effect=circle |
---|---|