12 9 6 3
just a phper
HTML5 地理位置定位(HTML5 Geolocation)

前言

昨天,想到给本博客的日记加个发布地址。于是想到了两个办法:

  • 后端实现,通过发布日记的客户端外网IP,查找IP分享服务器查找 改IP的地理位置
  • 前端实现,利用html5的新特性之一(地理位置 Geolocation)

据我之前的对这两种方法的探究,有以下印象:

  • 通过IP分享服务器查找相对应的地理位置的成功率是很高的
    但是精度不咋地,一般只能定位到市,eg:(广东省广州市 电信) 额外能查到网络提供商
  • 通过html5能定位到相对更高精度的地理位置,细到门牌号,甚至第几楼(ps:不准确)
    但是这方式的定位成功率不高
  • 另外,html5定位需要授权,外网IP不需要,但外网IP可以被伪装

解决方式

考虑了下, 还是决定用html5的新特性。
后来发现在台式电脑上,定位成功率略低,不同浏览器定位成功率也不一样。
在台式电脑调试中,我居然发现chrome浏览器定位成功率很低,IE的成功率高多了,出乎我意外
再后来,做了优化,在html5失败的情况下,通过外网IP去定位做下补救。


具体实现

  • php通过IP获取地理位置:

    $ip = $request->get('ip');
    if (!$ip){
    $ip = $request->ip();
    }
    //通过ip.cn获取地理位置
    $curl = new MyCurl();
    $curl->url = "http://www.ip.cn/index.php?ip={$ip}";
    $curl->header = ['User-Agent:curl/7.29.0'];
    $result = $curl->request();
    $match = [];
    preg_match('/来自:(\S*)/', $result['result'], $match);
    $address = isset($match[1]) ? $match[1] : "unknown";
    echo $address;
  • 前端h5获取地理位置(h5获取经纬度,通过百度jsapi获取具体地理位置):

    <script src="https://api.map.baidu.com/api?v=2.0&ak=xyLg35B5IHOZ8x86EZLR6bRXAlUn4iHa&s=1"></script>
    <script>
    function getaddress(){
    $.ajax({
    async:true,
    type:'get',
    url:"{{ route('api.ip') }}",
    cache:false,
    timeout:5000,//毫秒
    data:{
    },
    beforeSend:function(){
    $("#address").val($("#address").val() + ";正在向服务器请求定位...");
    },
    error:function(){
    $("#address").val("sorry,定位彻底失败!");
    },
    success:function(ret){
    $("#address").val(ret);
    }
    });
    }
    //console.log(navigator.geolocation);
    if (navigator.geolocation) {
    //setTimeout("console.log('ip location')", 3000 );
    navigator.geolocation.getCurrentPosition(function (position) {
    console.log(position);
    var lat = position.coords.latitude;
    var lon = position.coords.longitude;
    var point = new BMap.Point(lon, lat); // 创建点坐标
    var gc = new BMap.Geocoder();
    gc.getLocation(point, function (rs) {
    var addComp = rs.addressComponents;
    $("#address").val(addComp.province + addComp.city + addComp.district + addComp.street + addComp.streetNumber);
    });
    },
    function (error) {
    console.log(error);
    var err = "获取失败:";
    switch (error.code) {
    case 1:
    err += "位置服务被拒绝。";
    break;
    case 2:
    err += "暂时获取不到位置信息。";
    break;
    case 3:
    err += "获取位置信息超时。";
    break;
    default:
    err += "未知错误。";
    break;
    }
    $("#address").val(err);
    getaddress();
    }, { timeout: 5000, enableHighAccuracy: true });
    } else {
    $("#address").val("你的浏览器不支持获取地理位置信息。");
    getaddress();
    }
    $('.biaoqing').click(function(){
    $('#content').insertContent(' {'+$(this).attr('title')+'} ');
    });
    </script>
  • 温馨提示
    本以为这样就简单获得地理位置了, 其实本不是,能通过以上h5获取到地理位置的概率甚低
    经过试验我发现,在控制面板手动执行navigator.geolocation.getCurrentPosition(function(){});
    之后,下次请求得到地理位置的概率高很多。
    所以在获取地址位置前可以console.log(navigator.geolocation);
    或者对获取地理位置事件延时处理 ,
    这只是投机取巧,并没有找到根本原因。。。。。
    希望H5以后会更加完善
  • 后来发现
    原来h5定位是向https://www.googleapis.com 请求的位置信息,由于google已经退出了中国
    况且中间有高墙,所以定位的稳定性决定于网络的稳定性了,
    如果翻墙了,定位成功率高很多了,也可以把定位等待时间增大。
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证