zoukankan      html  css  js  c++  java
  • Geolocation 基于浏览器的定位服务

    1. 关于 Geolocation 对象

    随着 Opera 10.6 和 Safari 5的相继发布,截止到目前为止,W3C 中一个名为 Geolocation 的 API 规范在所有非 IE 浏览器中都得到了实现。简单地说,Geoloaction 的作用就是通过浏览器感知用户的地理位置。

    HTML 5 --- Geolocation 对象

    事实上,对于用户地理位置的探测在互联网上早已经有了很多案例,其中一个最常见的应用就是当在地址栏输入 google.com 并按下回车键的时候,google 并没有把我们带向刚才输入的地址,而是转向了 google 在我们所处地区的页面,比如大陆和香港用户会到达 google.com.hk,当然我们很怀念 google.cn,但这并不是今天所要讨论的话题。

    如果说地理位置的感知已经成为了一项成熟的技术,那么紧接着的问题就是 Geolocation 存在的意义是什么?就我目前对 Geolocation 的理解,我认为它存在的理由至少包含以下两点:
    1. 公共数据:目前的地理位置探测,其资料往往来源于服务商各自的数据,而使用浏览器内置的统一接口,将高效整合这一信息。
    2. 精确定位:无论是谷歌还是谷姐们,实现定位的原理无非是通过 IP 地址来探测用户的所在位置,众所周知,IP 的定位能力是比较差的,绝大多数情况下,它的精确度能达到数十公里就已经不错了,除此之外,没有别的任何办法,无论是服务器端语言还是客户端的 JavaScript 脚本,都无法从用户那里获取到更多对定位有所帮助的信息。然而作为用户机器上更为底层的浏览器,它将有权利支配其他有助于定位的设备,比如 GPS 和 WIFI。GPS 大家都已经很熟悉了,在信号良好的情况下,它可以精确到数米之内。而 WIFI 在国内基本上被废了,对于这项技术普及的国家,WIFI 的定位基本上可以精确到百米左右,据说经常可以见到一些公司的人,整天什么都不干,就开着小车到处晃,到一个热点( Hot Spot ),就记录下当前的地理位置,然后传回到公司的数据库。

    该对象位于我们非常熟悉的 Navigator 对象下面,可以通过 navigator.geolocation 来访问,当然前面也可以加上 window.。不支持 geolocation 的浏览器并不包含这一对象,那么可以通过下面的代码来做能力检测,对不同的浏览器做不同的处理。

    if (navigator.geolocation) {
            alert( ' 你的浏览器支持 geolocation ' );
    }else{
            alert( ' 你的浏览器不支持 geolocation ' )
    }
    

    在访问 geolocation 对象时,即调用 geolocation 下面的方法时,浏览器会弹出提示,询问用户是否许可网站提供的位置服务,只有在得到用户许可过后,服务才会继续,否则将被停止,在稍后你将会了解到,我们能够捕获到用户拒绝服务的动作。下面这张图分别是 Chrome , Firefox 和 Opera 在初次访问 geolocation 时,给用户的提示:

    浏览器询问用户是否接受位置服务

    2. 获取当前地理位置 --- getCurrentPosition

    当获得用户的许可过后,便一切就绪。我们将通过 geolocation 下的 getCurrentPosition 方法来获取用户的信息,这个方法是今天整篇文章的核心部分,也是 geolocation 一个非常重要的方法。

            navigator.geolocation.getCurrentPosition( getPositionSuccess , getPositionError );
    

    在上面的代码中,我们调用了 getCurrentPosition 方法,并为其传递了两个参数,事实上这个方法可以接受三个参数,前两个参数是函数,最后一个是对象:第一个参数是成功获取位置信息的回调函数,它是方法唯一必须的参数;第二个参数用于捕获获取位置信息出错的情况,第三个参数是配置项。

    当浏览器成功获取到用户的位置信息时,getCurrentPosition 的第一个函数类型的参数将被调用,一个 position 对象会被传入到调用的函数中,这个对象中包含了浏览器传回的数据,这非常重要。

    function getPositionSuccess( position ){
            var lat = position.coords.latitude;
            var lng = position.coords.longitude;
            document.write( "您所在的位置: 经度" + lat + ",纬度" + lng );
    }
    

    是的,position 对象包含了用户的地理位置信息,该对象下面的 coords 子对象包含了用户所在的纬度和经度信息,通过 position.coords.latitude 可以访问纬度,而 position.coords.longitude 中存放了经度的信息,用户的位置信息越精确,这两个数字后面的小数点越长。事实上,在 Firefox 中,position 对象下还附带有另一个 address 对象,这个对象包含这个经纬度下的国家名,城市名甚至街道名。

    function getPositionSuccess( position ){
            var lat = position.coords.latitude;
            var lng = position.coords.longitude;
            alert( "您所在的位置: 经度" + lat + ",纬度" + lng );
            if(typeof position.address !== "undefined"){
                    var country = position.address.country;
                    var province = position.address.region;
                    var city = position.address.city;
                    alert(' 您位于 ' + country + province + '省' + city +'市');
            }
    }
    

    错误捕获:上面都是成功获取到用户位置信息的处理,但是出现问题的情况在所难免,当获取用户的位置信息出错时,传递到 getCurrentPosition 的第二个函数类型参数被调用,一个包含具体出错信息的对象会被传递进去,错误将被捕获。

    function getPositionError(error){
    	switch(error.code){
    		case error.TIMEOUT :
    			alert( " 连接超时,请重试 " );
    			break;
    		case error.PERMISSION_DENIED :
    			alert( " 您拒绝了使用位置共享服务,查询已取消 " );
    			break;
    		case error.POSITION_UNAVAILABLE : 
    			alert( " 亲爱的火星网友,非常抱歉,我们暂时无法为您所在的星球提供位置服务 " );
    			break;
    	}
    }
    

    error 对象下面,存放了3个常量:
    TIMEOUT 表示获取信息超时。
    PERMISSION_DENIED 表示用户选择了拒绝了位置服务。
    POSITION_UNAVAILABLE 表示位置不可知。
    而每一次出错时 error.code 将指向3个常量之中的一个。

    配置项:getCurrentPosition 方法的第三个参数是一个对象,该对象影响了获取位置时的一些细节。
    enableHighAccuracy,它将告诉浏览器是否启用高精度设备,所谓的高精度设备包含但不局限于前面所提到的 GPS 和 WIFI,值为 true 的时候,浏览器会尝试启用这些设备,默认指为 true,在这种情况下,浏览器会尽可能地进行更为精确的查询,简单地说,如果用户有可用的 GPS 设备,会返回 GPS 设备的查询结果,IP 是最后的选择,对于移动设备来说,网络接入点(基站)或许成为另一个选择,对此我还没有完全了解,但根据测试,即时没有任何额外功能的手机,也能够得到更为精确的查询结果。
    timeout,超时,获取位置信息时超出设定的这个时长,将会触发错误,捕获错误的函数将被调用,并且错误码指向TIMEOUT
    这样我们尝试修改调用 getCurrentPosition 时传递的参数

    navigator.geolocation.getCurrentPosition( getPositionSuccess , getPositionError,{
            timeout : 5000    // 5 秒超时
    } );
    
    3. 持续追踪位置 --- watchPosition

    对于使用移动设备的用户来说,位置并不是固定的,W3C 当然也考虑到了这一点,watchPosition 是一个专门用来处理这一情况的方法,watchPosition 被调用后,浏览器会跟踪设备的位置,每一次位置的变化,watchPosition 中的代码都将会被执行。对于致力于移动设备 web 开发的同学来说,这个方法是及其重要的,它也许将会改变 web 移动客户端的格局。

            navigator.geolocation.watchPosition( refreshPosition );
    

    上面的代码表示,但设置位置发生改变时,refreshPosition 将会被调用。事实上 watchPosition 和 getCurrentPosition 几乎一模一样,同样包含了一个成功获取位置的回调函数,一个获取失败的回调函数和一个配置项,区别仅仅是在触发的时机上。所以具体的方法就不再重复了。上面的代码表示在每一次位置发生改变时,调用 refreshPosition 函数。

    4. 实例 --- 与 Google Map 交互

    接下来,我们通过一个实例,来具体应用一下 Geolocation ,实例的最终效果是,获取用户的位置,并通过 Google Map 在地图上标记出来,当用户的位置发生改变后,更新之前在地图上的标记到新的位置。首先我们准备好 DOM,并加载 Google Map

    <!-- 按钮,被点击时开始获取用户位置信息 -->
    <input type="button" id="getPos" value="获取我的位置" />
    <!-- 用来存放反馈给用户信息的 div -->
    <div id="info"></div>
    <!-- 为 Google Map 准备 -->
    <div id="map"></div>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false" ></script>
    

    接下来我们在 JavaScript 中获取这些 DOM,并为 Google Map 提供一个对象用来存放地图和标记。这些都是准备工作,很烦,但是不得不做。

    var dom = {
            btn : document.getElementById('getPos'),
            info : document.getElementById('info'),
            map : document.getElementById('map')
    };
    var gmap = {
            map : null,
            marker : null
    }
    

    接下来监听按钮的事件,当按钮被点击的时候,将触发获取用户的位置信息。在这里我们对浏览器进行了检测,如果不支持 Geolocation 接口,将提示用户,并停止进一步的动作。

    dom.btn.onclick = function(){
            if (navigator.geolocation) {
                    dom.info.innerHTML = "请等待查询结果返回";
                    dom.info.className = "warn";
                    navigator.geolocation.getCurrentPosition(getPositionSuccess,getPositionError,{timeout:5000});
            }else {
                    dom.info.innerHTML = "抱歉,您所使用的浏览器不支持 Geolocation 接口";
                    dom.info.className = "warn";
            }
    }
    

    在上面我们向 getCurrentPosition 传递了两个函数,现在我们来具体写这两个函数,首先是 getPositionSuccess ,当成功获取到用户的位置信息时,这个函数被调用,我们将在这时更新页面上的显示值,并配置追踪用户的位置的函数,最后调用 Google Map 的 API 在 id 为 map 的 div 中显示地图,并在地图上标记出用户的当前位置。

    function getPositionSuccess(position){
    	var lat = position.coords.latitude;
    	var lng = position.coords.longitude;
            dom.info.innerHTML = "您所在的位置: 经度" + lat + ",纬度" + lng;
    	navigator.geolocation.watchPosition(refreshPosition);
    	
    	// 载入 Google 地图
    	var latlng = new google.maps.LatLng(lat, lng);
    	var myOptions = {
    		zoom : 16,
    		center : latlng,
    		mapTypeId : google.maps.MapTypeId.ROADMAP
    	};
    	gmap.map = new google.maps.Map(document.getElementById("map"), myOptions);
    	
    	// 向地图中添加标记
    	gmap.marker = new google.maps.Marker({
    		position: latlng,
    		map: gmap.map
    	});
    }
    

    对于错误处理的函数,则非常简单,可以参看前面的内容。我们来关注一下追踪位置的函数,在这个函数中,我们实时更新显示信息,并更新地图到用户所处的位置。

    function refreshPosition(position){
    	var lat = position.coords.latitude;
    	var lng = position.coords.longitude;
    	var latlng = new google.maps.LatLng(lat, lng);
    
            // 重设地图位置
    	gmap.map.setCenter(latlng);
    	dom.info.innerHTML = '您所在的位置: 经度' + lat ' + ',纬度' + lng;
    
            // 重设标记位置
    	gmap.marker.setOptions({
    		position: new google.maps.LatLng(lat, lng)
    	});
    }
    

    以上关于 Google Map 的代码不是很了解的同学可以到 Google Code 去看一下 手册,这里只是很简单的应用,有兴趣的同学可以进一步延伸。下面是这个 Demo 的最终效果。

     

    正在为您准备地图,请稍候

    这个 Demo 在具备 GPS 功能的手机上,能够非常精确地定位,在我的测试中,在信号良好的地方,基本上能够定位到所在地方,并且位置追踪工作良好。下面是我在手机上浏览本 Demo 的效果,平台是 S60v5 ,浏览器 Opera Mobile 10.1 beta 1。需要说明一点的是,Opera Mobile 正是从这个版本开始支持 Geolocation 的。

    移动设备下的 Geolocation

  • 相关阅读:
    how to pass a Javabean to server In Model2 architecture.
    What is the Web Appliation Archive, abbreviation is "WAR"
    Understaning Javascript OO
    Genetic Fraud
    poj 3211 Washing Clothes
    poj 2385 Apple Catching
    Magic Star
    关于memset的用法几点
    c++ 函数
    zoj 2972 Hurdles of 110m
  • 原文地址:https://www.cnblogs.com/mount/p/2262812.html
Copyright © 2011-2022 走看看