关于微信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的方式主动与定位组件发起通信,前端定位组件支持的通信事件有:

  1. getLocation: 获取当前所在地理位置,调用一次即重新定位一次,定位数据比较精确。
  2. getLocation.robust: 立即获取当前所在地理位置,适用于非精确定位场景,是IP定位,城市级别。
  3. watchPosition: 监听位置信息的改变,类似HTML5 Geolocation的watchPosition
  4. 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

这篇文章对您解决问题是否有帮助?

已解决
未解决