高德地图api定位精度问题

新手上路,请多包涵

我在弄一个实验室预约项目,学生到预约的时间后在实验室的电脑上进行签到定位。使用高德地图api进行定位,功能弄好了,可是定位的距离和实际的距离差了几百米。(我在图书馆点击定位,但是在浏览器上定位到了宿舍楼;在宿舍楼点击定位,但是定位到了教学楼)。请问这个怎么解决?谢谢。
https://segmentfault.com/q/10...,这篇文章我也看过了,跟着弄也不行)

阅读 9k
4 个回答

地图类应用由于政府管制一直是有精度丢失的,但是不会相差这么大!看看你的代码坐标转换有没有问题。

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme() + "://"
            + request.getServerName() + ":" + request.getServerPort()
            + path + "/";
%>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">


    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <meta name="format-detection" content="telephone=no">
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache" content="no-cache">
    <link type="text/css" href="../static/atd/css/common-9baddc8954.css" rel="stylesheet">
    <link href="../static/atd/css/layer.css" rel="stylesheet" type="text/css">
    <link type="text/css" href="../static/atd/css/stuCourse-06127df797.css" rel="stylesheet">
    <%--加载高德地图--%>
    <script type="text/javascript"
            src="http://webapi.amap.com/maps?v=1.4.3&key=ec3226d69643a423012abef447eb8db1"></script>
    <!-- UI组件库 1.0 -->
    <script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
    <script src="../static/atd/js/jquery-3.2.1.min.js"></script>              <%--444444444--%>
    <style type="text/css">body {
        position: relative;
        max-width: 520px;
        margin: 0 auto;
        overflow: hidden;
    }
    </style>
    <base href="<%=basePath%>">

</head>

<body onload="javascript:toolBar.doLocation()">
<div class="page-inner" id="page-getlocation-confirm">
    <form action="lab_info/${msg }.do" method="post" id="confirmAttendForm">
        <header class="header-item" style="background-color: rgb(0, 117, 142);">
            <a href="javascript:history.back(-1)" class="icon-back" data-pjax="">
                <img src="static/atd/img/backWhite.png" style="vertical-align: middle;text-align: center;">
            </a>
            <i class="line"></i>
            <h3 class="fs36 text-overflow" id="attencename">确认签到位置</h3>

        </header>

        <div id="wrapper-getLocation">
            <div class="location-map-checkin" style="height:80px;">
                <a href="javascript:document:confirmAttendForm.submit();" class="gotocheckin">
                    <span class="top">定位准确</span>
                    <span class="bottom">点击签到</span>
                </a>
                <a href="javascript:void(0)" onclick="location.reload()" class="reloadcation" id="start">
                    <span class="top">定位有误</span>
                    <span class="bottom">重新定位</span>
                </a>
            </div>
            <%--显示位置--%>
            <div style="padding-bottom: 10px">
                <input type="text" id="location" name="LOCATION" class="fs30" readonly="readonly" style="width: 100%;font-size: 15px">
                <input type="text" id="position" name="LOCATION" class="fs30" readonly="readonly" style="width: 100%;font-size: 15px">
                <input type="text" id="location_type" name="LOCATION" class="fs30" readonly="readonly" style="width: 100%;font-size: 15px">

                <input type="hidden" name="LAB_ID" value="${LAB_ID}">
            </div>

        </div>

        <%--显示地图--%>
        <div id="container"
             style="height:560px;overflow: hidden; position: relative;  background-color: rgb(243, 241, 236); color: rgb(0, 0, 0); text-align: left;">
        </div>



    </form>
</div>


</body>
<%--提示框--%>
<div class="" id="tipWindow">
    <div class="gTips"><span style="background-color: #EA3640" id="tip">${tipInfo}</span></div>
</div>
</html>

<script>
    setTimeout('$("#tipWindow").addClass("hidden")', 3000);
    /**/
    //自定义定位标记
    var toolBar;
/*offset: new AMap.Pixel(-14, -34),//相对于基点的位置*/
    var customMarker = new AMap.Marker({
        offset: new AMap.Pixel(-14, -34),//相对于基点的位置
        icon: new AMap.Icon({  //复杂图标
            size: new AMap.Size(27, 36),//图标大小
            image: "http://webapi.amap.com/images/custom_a_j.png", //大图地址
            imageOffset: new AMap.Pixel(-28, 0)//相对于大图的取图位置
        })
    });

    //初始化地图对象,加载地图
    var map = new AMap.Map('container', {
        resizeEnable: true
    });

    //地图中添加地图操作ToolBar插件
    map.plugin(["AMap.ToolBar"], function () {
        toolBar = new AMap.ToolBar({locationMarker: customMarker}); //设置地位标记为自定义标记
        map.addControl(toolBar);
    });

    var GPS = {

        PI: 3.14159265358979324,
        x_pi: 3.14159265358979324 * 3000.0 / 180.0,
        delta: function (lat, lon)
        {
            // Krasovsky 1940
            //
            // a = 6378245.0, 1/f = 298.3
            // b = a * (1 - f)
            // ee = (a^2 - b^2) / a^2;
            var a = 6378245.0; //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
            var ee = 0.00669342162296594323; //  ee: 椭球的偏心率。
            var dLat = this.transformLat(lon - 105.0, lat - 35.0);
            var dLon = this.transformLon(lon - 105.0, lat - 35.0);
            var radLat = lat / 180.0 * this.PI;
            var magic = Math.sin(radLat);
            magic = 1 - ee * magic * magic;
            var sqrtMagic = Math.sqrt(magic);
            dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);
            return { 'lat': dLat, 'lon': dLon };
        },

        //WGS-84 to GCJ-02
        gcj_encrypt: function (wgsLat, wgsLon)
        {
            if (this.outOfChina(wgsLat, wgsLon))
                return { 'lat': wgsLat, 'lon': wgsLon };

            var d = this.delta(wgsLat, wgsLon);
            return { 'lat': wgsLat + d.lat, 'lon': wgsLon + d.lon };
        },
        //GCJ-02 to WGS-84
        gcj_decrypt: function (gcjLat, gcjLon)
        {
            if (this.outOfChina(gcjLat, gcjLon))
                return { 'lat': gcjLat, 'lon': gcjLon };

            var d = this.delta(gcjLat, gcjLon);
            return { 'lat': gcjLat - d.lat, 'lon': gcjLon - d.lon };
        },
        //GCJ-02 to WGS-84 exactly
        gcj_decrypt_exact: function (gcjLat, gcjLon)
        {
            var initDelta = 0.01;
            var threshold = 0.000000001;
            var dLat = initDelta, dLon = initDelta;
            var mLat = gcjLat - dLat, mLon = gcjLon - dLon;
            var pLat = gcjLat + dLat, pLon = gcjLon + dLon;
            var wgsLat, wgsLon, i = 0;
            while (1)
            {
                wgsLat = (mLat + pLat) / 2;
                wgsLon = (mLon + pLon) / 2;
                var tmp = this.gcj_encrypt(wgsLat, wgsLon)
                dLat = tmp.lat - gcjLat;
                dLon = tmp.lon - gcjLon;
                if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold))
                    break;

                if (dLat > 0) pLat = wgsLat; else mLat = wgsLat;
                if (dLon > 0) pLon = wgsLon; else mLon = wgsLon;

                if (++i > 10000) break;
            }
            //console.log(i);
            return { 'lat': wgsLat, 'lon': wgsLon };
        },
        //GCJ-02 to BD-09
        bd_encrypt: function (gcjLat, gcjLon)
        {
            var x = gcjLon, y = gcjLat;
            var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);
            var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);
            bdLon = z * Math.cos(theta) + 0.0065;
            bdLat = z * Math.sin(theta) + 0.006;
            return { 'lat': bdLat, 'lon': bdLon };
        },
        //BD-09 to GCJ-02
        bd_decrypt: function (bdLat, bdLon)
        {
            var x = bdLon - 0.0065, y = bdLat - 0.006;
            var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);
            var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);
            var gcjLon = z * Math.cos(theta);
            var gcjLat = z * Math.sin(theta);
            return { 'lat': gcjLat, 'lon': gcjLon };
        },
        //WGS-84 to Web mercator
        //mercatorLat -> y mercatorLon -> x
        mercator_encrypt: function (wgsLat, wgsLon)
        {
            var x = wgsLon * 20037508.34 / 180.;
            var y = Math.log(Math.tan((90. + wgsLat) * this.PI / 360.)) / (this.PI / 180.);
            y = y * 20037508.34 / 180.;
            return { 'lat': y, 'lon': x };
            /*
            if ((Math.abs(wgsLon) > 180 || Math.abs(wgsLat) > 90))
                return null;
            var x = 6378137.0 * wgsLon * 0.017453292519943295;
            var a = wgsLat * 0.017453292519943295;
            var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
            return {'lat' : y, 'lon' : x};
            //*/
        },
        // Web mercator to WGS-84
        // mercatorLat -> y mercatorLon -> x
        mercator_decrypt: function (mercatorLat, mercatorLon)
        {
            var x = mercatorLon / 20037508.34 * 180.;
            var y = mercatorLat / 20037508.34 * 180.;
            y = 180 / this.PI * (2 * Math.atan(Math.exp(y * this.PI / 180.)) - this.PI / 2);
            return { 'lat': y, 'lon': x };
            /*
            if (Math.abs(mercatorLon) < 180 && Math.abs(mercatorLat) < 90)
                return null;
            if ((Math.abs(mercatorLon) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892))
                return null;
            var a = mercatorLon / 6378137.0 * 57.295779513082323;
            var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0);
            var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323;
            return {'lat' : y, 'lon' : x};
            //*/
        },
        // two point's distance
        distance: function (latA, lonA, latB, lonB)
        {
            var earthR = 6371000.;
            var x = Math.cos(latA * this.PI / 180.) * Math.cos(latB * this.PI / 180.) * Math.cos((lonA - lonB) * this.PI / 180);
            var y = Math.sin(latA * this.PI / 180.) * Math.sin(latB * this.PI / 180.);
            var s = x + y;
            if (s > 1) s = 1;
            if (s < -1) s = -1;
            var alpha = Math.acos(s);
            var distance = alpha * earthR;
            return distance;
        },
        outOfChina: function (lat, lon)
        {
            if (lon < 72.004 || lon > 137.8347)
                return true;
            if (lat < 0.8293 || lat > 55.8271)
                return true;
            return false;
        },
        transformLat: function (x, y)
        {
            var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
            return ret;
        },
        transformLon: function (x, y)
        {
            var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
            return ret;
        }
    };


    var geolocation;
    map.plugin('AMap.Geolocation', function () {
        geolocation = new AMap.Geolocation({
            enableHighAccuracy: true,//是否使用高精度定位,默认:true
            timeout: 10000,          //超过10秒后停止定位,默认:无穷大
            buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
            zoomToAccuracy: true,      //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
            buttonPosition: 'RB',
            maximumAge: 0,           //定位结果缓存0毫秒,默认:0
            convert: true,           //自动偏移坐标,偏移后的坐标为高德坐标,默认:true
            showButton: true,        //显示定位按钮,默认:true
            showMarker: true,        //定位成功后在定位到的位置显示点标记,默认:true
            showCircle: true,        //定位成功后用圆圈表示定位精度范围,默认:true
            panToLocation: true,     //定位成功后将定位到的位置作为地图中心点,默认:true
            zoomToAccuracy: true      //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false

        });
        map.addControl(geolocation);
        geolocation.getCurrentPosition();
        AMap.event.addListener(geolocation, 'complete', onComplete);//返回定位信息
        AMap.event.addListener(geolocation, 'error', onError);      //返回定位出错信息
    });

    //解析定位结果
    function onComplete(data) {
        var str = ["定位成功"];
        var location = data.formattedAddress;
        var position = data.position;
        var location_type=data.location_type;
        //gcj-02转换为wgt84
        var gpsPoint = GPS.gcj_decrypt_exact(data.position.getLat(), data.position.getLng());

        document.getElementById('tip').innerHTML = str;
        document.getElementById('location').value = "地址:" + location;
        document.getElementById('position').value = "position:" + position;
        document.getElementById('location_type').value = "location_type:" + location_type + "===" + gpsPoint.lat + "," + gpsPoint.lon;

    }

    //解析定位错误信息
    function onError(data) {
        var error = ['定位失败'];
        document.getElementById('tip').innerHTML = error;
        document.getElementById('location').value = "错误提示:" + data.info + '--' + data.message;
    }


</script>


</script>

问题有点模糊,但根据偏差信息,大约是坐标系的问题。高德默认是GCJ2000的米制坐标,如果你当成wgs48的,偏差大概在500米左右。如果只是定位误差,不考虑gps偏移的情况,误差不会超过10米。所以,我估计是第一种情况。不过你描述的环境并不具体,所以也只能猜

浏览器是指PC浏览器?

PC没有GPS模块,定位靠IP,准不准看人品了.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题