跨浏览器获取 Geolocation
- - 幸福收藏夹年末,这一年的工作都差不多搞完了. 因为下一年的目标是 HTML5 应用,所以在做一些小尝试. 距离 第一次在支付宝分享 HTML5,已经有一年半了,时间好快,就这么过去了. 前几天和同事聊到可能可以做个基于 LBS 的服务,回到家里就尝试了一下 HTML5 的 Geolocation API. 翻开一年前写的文档,很快就熟悉起来.
年末,这一年的工作都差不多搞完了。因为下一年的目标是 HTML5 应用,所以在做一些小尝试。距离 第一次在支付宝分享 HTML5,已经有一年半了,时间好快,就这么过去了。而我似乎还是那个我。话多了。前几天和同事聊到可能可以做个基于 LBS 的服务,回到家里就尝试了一下 HTML5 的 Geolocation API。翻开一年前写的文档,很快就熟悉起来。主要有两个函数,下面是对比:
用于 | 方法 | 参数描述 |
---|---|---|
单次 | getCurrentPosition( successCallback [, errorCallBack, [, positionOptions]) |
|
重复 | var watchPositionHandler = watchPosition( successCallback [, errorCallBack, [, positionOptions]) | |
clearWatch(watchPositionHandler) |
理论上来说,watchPosition 对于需要重复执行的操作是非常有用的,比如不断在地图上显示目标的位置。但事情上 W3C 并没有规定获取的频率是多少(难道是我找不到?),所以导致了浏览器处理的结果非我们想要,下面这个截图分别是 Chrome 和 Firefox 的获取频率,Chrome 显示频率非常混乱,而 Firefox 则是每分钟/一次:
因此,如果想执行重复操作,最好还是利用定时器来重用执行 getCurrentLocation 以使你的程序能够显示正确的数据。当然,这是一方面的问题,只要浏览器支持 HTML5 的 Geolocation API,那么什么事都好商量,而我们问题就在于,像 IE 或者一下其他的,更老的浏览器,是不支持的。我们是不是有办法可以解决。
其实网站有很多提供免费 IP 获取的工具,比如 google Gears(停止开发了)、hostIP.info 等。所以利用这些工具,我们还是可以在其他只支持 javascript 的浏览器上获取地理位置信息的。下面是我写一个纯 JS 解决方案:
// Github 地址: geolocation.js // 结合这个 js 和 QQ 地图做的一个简单 Web APP: Between US /* * @Name: Geolocation * @Overview: the javascript way to fetch the geolocation * @Author: sofish Lin <http://sofish.de> */ // TODO: error handler for ie function Geo(successCallback, errorCallback) { var that = this, // native geolocation API _w3cAPI = navigator.geolocation; // get ip-base geolocation // fallback for the w3c way function _ipBaseWay(){ var that = this; var doc = document, script = doc.createElement('script'); script.setAttribute('src','http://j.maxmind.com/app/geoip.js'); doc.body.appendChild(script); script.attachEvent('onreadystatechange', function(){ var target = window.event.srcElement; if(/loaded|complete/.test(target.readyState)){ var coords = { latitude: geoip_latitude(), longitude: geoip_longitude() }; return successCallback.call(that, coords); } }); }; // fetch coords using w3c Geoloactions API function _w3cWay (){ var that = this; _w3cAPI.getCurrentPosition(function(position){ successCallback.call(that, position.coords); },function(error){ var err; switch (error.code) { case error.PERMISSION_DENIED: err = 'You did not share geolocation data!'; break; case error.POSITION_UNAVAILABLE: err = 'Could not detect current position!'; break; case error.TIMEOUT: err = 'Retrieving position timedout!'; break; default: err = 'Unknown error'; }; errorCallback.call(that, err); }); }; // create the position !!(_w3cAPI) ? _w3cWay() : _ipBaseWay(); };