【HTML5 API】地理位置

HTML5 API

HTML5不仅仅指的是最新版的HTML标准,它还指代目前一整套的Web应用技术,其中包括HTML相关技术。这里所谓的Web应用技术更正规的术语其实是开放的Web平台。然而,在实际开发过程中,“HTML5”更像一个方便的简写。

地理位置

地理位置API(http://www.w3.org/TR/geolocation-API/)允许JavaScript程序向浏览器询问用户真实的地理位置。识别地理位置的一些应用就可以使用它来显示地图、导航和其他一些和用户当前位置相关的信息。当然,考虑到这些信息牵涉用户的隐私,支持地理位置API的浏览器在JavaScript程序获取用户物理位置前总是会询问用户是否允许。

支持地理位置API的浏览器会定义navigator.geolocation。此属性指代一个拥有如下这三个方法的对象:

  • navigator.geolocation.getCurrentPosition()
    获取用户当前位置。

  • navigator.geolocation.watchPosition()
    获取当前位置,同时不断地监视当前位置,一旦用户位置发生更改,就会调用指定的回调函数。

  • navigator.geolocation.clearWatch()
    停止监视用户位置。传递给此方法的参数应当是调用watchPosition()方法获得的返回值。

在包含GPS硬件的设备上,通过GPS单元可以获取精确的位置信息。不过,绝大多数情况下,位置信息都是通过Web获取的。当浏览器提交Internet IP地址给一个Web服务的时候,该服务通常能够知道(基于ISP记录)该IP属于哪个城市(通常广告商会在服务器端这么做)。浏览器还可以通过请求操作系统获取附近无线网络的列表和它们的信号强度,来得到更加精确的位置信息。当将这些信息提交给高级的Web服务的时候,允许非常精确地计算位置(通常在一个城市范围中)。

这些地理位置相关的技术都包含通过网络的数据交换或者和多个卫星之间的通信,因此地理位置API是异步的:getCurrentPosition()方法和watchPosition()方法需要接受一个回调函数作为参数,在判断用户的位置信息(或者当位置改变信息)时,浏览器会调用该函数。如下代码展示了一个获取位置的简单例子:

navigator.geolocation.getCurrentPosition(function(pos) {
  var latitude = pos.coords.latitude;
  var longitude = pos.coords.longitude;
  alert("Your position: " + latitude + ", " + longitude);
});

除了经度和纬度外,凡是成功获取到的地理位置信息还包括一个精度值(米为单位),该值表示获取到的位置信息精度是多少。如下例所示:它调用getCurrentPosition()方法来获取当前位置,并用获取到的位置信息,在一张地图中(来自Google地图)中显示当前位置,并且当前位置是根据位置精度进行过适当的缩放。

例:通过获取地理位置信息在地图上显示当前位置
// 返回一个新创建的<img>元素,该元素用于在获取到地理位置信息后,显示一张Coogle地图,
// 该地图上显示了当前的位置。要注意的是,此函数的调用者必须要将返回的元素
// 插入到文档中,以使它可见
// 如果当前浏览器不支持地理位置API,则抛出一个错误
function getmap() {
  // 检査是否支持地理位置API
  if (!navigator.geolocation) throw "Ceolocation not supported";
  // 创建一个新的<img>元素,并开始请求地理位置信息,
  // img元素显示包含当前位置的地图,然后再将返回该图片
  var image = document.createElement("img");
  navigator.geolocation.getCurrentPosition(setMapURL);
  return image;

  // 当(如果)成功获取到地理位置信息后,会在返回image对象后调用此方法 
  function setMapURL(pos) {
  //  从参数对象(pos)中获取位置信息
      var latitude = pos.coords.latitude;     // 经度
      var longitude = pos.coords.longitude;   // 纬度
      var accuracy = pos.coords.accuracy;     // 米

      // 构造一个URL,用于请求一张显示当前位置的静态Google地图
      var url = "http://maps.google.com/maps/api/staticmap" +
          "?center=" + latitude +	"," + longitude + "&size=640x640&sensor=true";

      // 设置一个大致的缩放级别
      var zoomlevel = 20; // 以各种方式开始缩放
      if (accuracy > 80)  // 在低精度情况下进行放大
      zoomlevel -= Math.round(Math.log(accuracy/50)/Math.LN2);
      url += "&zoom=" + zoomlevel; // 将缩放级别添加到URL中
      
      // 现在在image对象中显示该地图。感谢Google 
      image.src = url;
  }
}

地理位置API还有如下一些特性,上例子中没有体现:

  • 除了第一个回调函数的参数之外,getCurrentPosition()方法和watchPosition()方法还接受第二个可选的回调函数,当获取地理位置信息失败的时候,会调用该回调函数。

  • 除了成功和失败情况下的回调函数这两个参数之外,这两个方法还接受一个配置对象作为可选的第三个参数。该对象的属性指定了是否需要高精度的位置信息,该位置信息的过期时间,以及允许系统在多长时间内获取位置信息。

  • 作为参数传递给成功情况下的回调函数的对象,还包含一个时间戳,也有可能(在某些设备上)包含诸如海拔、速度和航向之类的额外信息。

下例展示了如何使用这些额外的特性。

例:展示如何使用所有地理位置特性
// 异步的获取我的位置,并在指定的元素中展示出来
function whereami(elt) {
  // 将此对象作务第三个参数传递给getCurrentPosition()方法
  var options = {
  //  设置为true,表示如果可以的话
  //  获取高精度的位置信息(例如,通过GPS获取)
  //  但是,要注意的是,这会影响电池寿命
  enableHighAccuracy: false, // 可以近似:这是默认值

  //  如果获取缓存过的位置信息就足够的话,可以设置此属性
  //  默认值为0,表示强制检査新的位置信息
  maximumAge: 300000, // 5分钟左后
  //  愿意等待多长时间来获取位置信息?
  //  默认值为无限长,getCurrentPosition()方法永不超时
  timeout: 15000 // 不要超过15秒
};

if (navigator.geolocation) // 如果支持的话,就获取位置信息
  navigator.geolocation.getCurrentPosition(success, error, options);
else
  elt.innerHTMl = "Geolocation not supported in this browser";

//  当获取位置信息失败的时候,会调用此函数
function error(e) {
  // error对象包含一些数字编码和文本消息,如下所示:
  // 1:用户不允许分享他/她的位置信息
  // 2:浏览器无法确定位置
  // 3:发生超时
  elt.innerHTML = "Geolocation error " + e.code + ": " + e.message;
}

  // 当获取位置信息成功的时候,会调用此函数
  function success(pos) {
    // 总是可以获取如下这些字段
    // 但是要注意的是时间戳信息在outer对象中,而不在inner, coords对象中
    var msg = "At " +
        new Date(pos.timestamp).toLocaleString() + " you were within " +
        pos.coords.accuracy + " meters of latitude " +
        pos.coords.latitude + " longitude " +
        pos.coords.longitude +

    // 如果设备还返回了海拔信息,则将其添加进去
    if (pos.coords.altitude) {
        msg += " You are " + pos.coords.altitude + " ± " +
            pos.coords.altitudeAccuracy + "meters above sea level.";
    }
    // 如果设备还返回了速度和航向信息,也将它们添加进去
    if (pos.coords.speed) {
      msg += " You are travelling at " +
          pos.coords.speed + "m/s on heading " +
          pos.coords.heading + ".";
    }

    elt.innerHTMl = msg; // 显示所有的位置信息
  }
}
上一篇:Linux配置NTP服务器


下一篇:从零入门 Serverless | 一文详解 Serverless 技术选型