使用 HTML5 实现地理位置的定位

  据说,华丽的 HTML5 浪潮已经打湿了众多网站设计师,而且还将继续在国内刮起龙卷风。而且,HTML5 取代传统 APP 的声音也渐渐多了起来,正因为如此,微歌也非常喜欢收集这方面的资料。今天介绍的这个东东来源于网络,具体地说是来自博客园,当然不是本站原创的。收集这篇文章只是微歌个人对其介绍的内容非常有兴趣,想收藏起来供有时间的时候来深入学习,当然,也想推荐给喜欢 HTML5 的同学看看。

  首先,HTML5 的出现会使得手机中的原生态 APP 减少。因为 HTML5 能够产生一种假的 APP,使得用户无需下载安装 APP,而是通过利用手机浏览器运行。
  第二,HTML5 的出现大大节省了人们的开发成本。因为它通吃 PC、 Mac、 iPhone、 iPad、 Android、 Windows Phone 等跨语言平台。程序员们再也不必为不同款的手机做不同的 APP 了。
  第三,HTML5 的出现使得手机里可以不用再有 Flash 了。因为 HTML5 就有这种魔力使得我们观看多媒体时不必安装 Flash 等第三方插件。
  第四,由于第三方插件的减少,手机得到了减肥瘦身,那么手机电量自然也会相对持久一些。
  第五,HTML5 使得手机定位服务更便捷,因为它实现了基于地理位置的功能,想定位,直接点击『附近』就能轻松搞定。
  第六,HTML5 使得设计师们可以设计出更加美观、更加炫酷的网页,创造出更加有强大视觉效果的界面。
  看到这里,你对 HTML5 动心了吗?下面为大家介绍一个 HTML5 的酷炫功能:定位系统!

  以下内容转载自博客园,作者:韩子迟,微歌没有作任何修改:

  Geolocation

  HTML5 的 geolocation 是一个令人兴奋的 API,通过这套 API,Javascript 代码就能够访问到用户的当前位置。当然,访问之前必须得到用户的明确认可,即同意在页面共享位置。如果页面尝试访问地理位置信息,浏览器就会显示一个对话框,请求用户许可共享其地理位置信息,比如这样:
  用户同意(允许)之后,Geolocation 的 api 就能起作用了。

  getCurrentPosition() 方法

  Geolocation API 在浏览器中的实现是 navigator.geolocation 对象,这个对象包含 3 个方法。第一个方法是 getCurrentPosition(),调用这个方法就会触发请求用户共享地理定位信息的对话框。这个方法接收 3 个参数:成功回调函数,可选的失败回调函数和可选的选项对象。

  其中,成功回调函数会接收到一个 Position 对象参数,该对象有两个属性:coords 和 timestamp。而 coords 对象中将包含下列与位置相关的信息。

  latitude:以十进制度数表示的维度
  longtitude:以十进制度数表示的经度
  accuracy:经纬度坐标的精度,以米为单位
  有些浏览器可能会在 coords 对象中提供如下属性。

  altitude:以米为单位的海拔高度,如果没有相关数据则值为 null
  altitudeAccuracy:海拔高度的精度,以米为单位,数值越大越不精确
  heading:指南针的方向,0°表示正北,值为 NaN 表示没有检测到数据
  speed:速度,即每秒移动多少米,如果没有相关数据则值为 null
  说了这么多,我们来简单应用下,写一段代码获取当前的经纬度,然后输出:

navigator.geolocation.getCurrentPosition(geo_success, geo_error);

function geo_success(position) {
  console.log(position.coords.latitude, position.coords.longitude);
}

function geo_error(msg) {
  console.log(msg.code, msg.message);
}

 

  代码很简单,如果请求成功了就执行 geo_success() 函数,打印经纬度,如果失败了,输出一些信息(失败回调)。

  getCurrentPosition() 的第二个参数,即失败回调函数,在被调用的时候也会接收到一个参数。这个参数是一个对象,包含两个属性:message 和 code。其中,message 属性中保存着给人看的文本消息,解释为什么会出错,而 code 属性中保存着一个数值,表示错误的类型:用户拒绝共享(1),位置无效(2)或者超时(3)。实际开发中,大多数 Web 应用只会讲错误消息保存到日志文件中,而不一定会修改用户界面。

  我们在 PC 端的 chrome 浏览器中执行这段代码,结果是令人遗憾的:
  掐指一算,估计是被墙了… 事实上,以 Chrome 浏览器为例,如果您允许 Chrome 浏览器与网站共享您的位置,Chrome 浏览器会向 Google 位置服务(此环节被墙)发送本地网络信息,估计您所在的位置。然后,浏览器会与请求使用您位置的网站共享您的位置。

  接着在 Android 机上测试了下,没被墙,毕竟谷歌是 Android 的亲爹啊。打印出来的信息如下:

31.188199 121.632919

  当然只是知道经纬度或许不太那么直观,如果能把位置显示在地图上那就直观多了!这里我用了高德地图的 API(猛戳这里看效果):

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
  <title>地图显示</title>
  <link rel="stylesheet" href="http://cache.amap.com/lbs/static/main.css?v=1.0" />
  <script src="http://webapi.amap.com/maps?v=1.3&key=您申请的key值"></script>
</head>
<body>
  <div id="mapContainer"></div>
  <script>
    navigator.geolocation.getCurrentPosition(geo_success, geo_error);

    function geo_success(position) {
      var map = new AMap.Map('mapContainer', {
        // 设置中心点
        center: [position.coords.longitude, position.coords.latitude],

        // 设置缩放级别
        zoom: 13
      });

      var marker = new AMap.Marker({
        //复杂图标
        icon: new AMap.Icon({
            //图标大小
            size: new AMap.Size(28, 37),
            //大图地址
            image: "http://webapi.amap.com/images/custom_a_j.png",
            imageOffset: new AMap.Pixel(-28, 0)
        }),
        //在地图上添加点
        position: [position.coords.longitude, position.coords.latitude]
      });

      marker.setMap(map);
    }

    function geo_error(msg) {
      console.log(msg.code, msg.message);
    }
  </script>
</body>
</html>

 

  在手机上打开后:
  我的天哪!实在是太准了!如果我把代码里的 zoom 参数再加大点,能精确到小区了……当然,这并不奇怪,因为这本来就是高德地图百度地图定位的一部分嘛。

  事实上,getCurrentPosition() 还有第三个参数,该参数是一个选项对象,用于设定信息的类型。可以设置的选项有三个:enableHighAccuracy 是一个布尔值,表示必须尽可能使用最精确的位置信息;timeout 是以毫秒数表示的等待位置信息的最长时间;maximumAge 表示上一次取得的坐标信息的有效时间,以毫秒表示,如果时间到则重新取得新坐标信息。

  除非确实需要非常精确的信息,否则建议保持 enableHighAccuracy 的 false 值(默认值)。将这个选项设置为 true 需要更长的时候,而且在移动设备上更耗电。类似的,如果不需要频繁更新用户的位置信息,那么可以将 maximumAge 设置为 Infinity,从而始终都使用上一次的坐标信息。

navigator.geolocation.getCurrentPosition(locationSuccess, locationError, {
  // 指示浏览器获取高精度的位置,默认为false
  enableHighAcuracy: true,
  // 指定获取地理位置的超时时间,默认不限时,单位为毫秒
  timeout: 5000,
  // 最长有效期,在重复获取地理位置时,此参数指定多久再次获取位置。
  maximumAge: 3000
});

 

  watchPosition() 方法
  如果要跟踪用户的位置,那么可以使用 watchPosition() 方法。这个方法的使用和 getCurrentPosition() 完全相同。实际上 watchPosition() 与定时调用 getCurrentPosition() 能得到相同效果。在第一次调用 watchPosition() 方法后,会取得当前位置,执行成功回调或者错误回调。然后,watchPosition() 就地等待系统发出位置已改变的信号。

  调用 watchPosition() 会返回一个数值标识符,用于跟踪监控的操作。基于这个返回值可以取消监控操作,只要将其传递给 clearWatch() 方法即可(与使用 setTimeout() 和 clearTimeout() 类似),例如:

var watchId = navigator.geolocation.watchPosition(geo_success, geo_error);
clearWatch(watchId);

 

  Geolocation 定位原理
  Geolocation API 的数据来源可能是 GPS、IP 地址、RFID、WiFi、蓝牙 MAC 地址、GSM/CDMA 卡 ID 等。因为 Geolocation API 是运行在你本地设备上的。所以,在使用 VPN 或代理的情况下,Geo API 仍能获得你准确的 IP 地址信息(除非因为某些因素浏览器获取不到这些信息)。

  在HTML5的实现中,手机等移动设备当然优先使用GPS定位,而笔记本和部分平板,最准的定位是WIFI,至于网线上网的台式机,一般就只能使用IP来定位了,这个准确度最低。

欢迎留下宝贵意见和建议!