Geolocation

定位和跟踪

介绍

  • Geolocation工作原理
  • Geolocation API
    • getCurrentPosition方法
    • Geolocation数据
    • Handling Errors
    • PositionOptions对象
    • watchPosition()方法和clearWatch()方法
  • Example
  • 相关资源

浏览器支持情况

geolocation

Geolocation 工作原理

识别地理位置的主要方法:

  • 通过IP地址
  • 利用基站获取手机网络的接入位置
  • 通过利用卫星定位获得经纬度信息的GPS设备

Geolocation API

可以获得用户所在地理位置的经纬度信息

调用 Geolocation API 从全局 navigator 对象的 geolocation 属性开始:navigator.geolocation

<script type='text/javascript'>
  // 最简单的使用方式:没有做任何的检测,错误处理,也没有选项参数
  function find_my_location() {
    navigator.geolocation.getCurrentPosition(show_map);
  }
</script>

Geolocation API

检测浏览器是否支持地理位置API

方法1: 全局对象 navigator 是否具有 geolocation 属性

<script type='text/javascript'>
  function supports_geolocation() {
  	return !!navigator.geolocation;
  }
</script>

方法2: 使用Modernizr提供的方法

<script type='text/javascript'>
  function find_my_location() {
  	if (Modernizr.geolocation) {
	    navigator.geolocation.getCurrentPosition(show_map);
    } else {
    	// 浏览器没有提供原生支持,使用回退方案
    }
  }
</script>

Geolocation API

getCurrentPosition()

使用getCurrentPosition()方法 .

<script type='text/javascript'>
    function find_my_location() {
        if (Modernizr.geolocation) {
	        navigator.geolocation.getCurrentPosition(show_map);
        } else {
    	    // 其他方案
        }
    }
    
    function show_map(position) {
        var latitude = position.coords.latitude;
        var longitude = position.coords.longitude;
        alert('Lat: ' + latitude + ' Lon: ' + longitude);
    }
</script>

Position 数据

成功的回调函数的参数是一个 Position 对象,包括 coordstimestamp两个属性。

属性 类型 备注
coords.latitude double 纬度(度)
coords.longitude double 经度(度)
coords.accuracy double 精度(米)
coords.altitude double或null 海拔(米)
coords.altitudeAccuracy double或null 海拔精度(米)
coords.heading double或null 度(顺时针,以正北为基准)
coords.speed double或null 米/秒
timestamp DOMTimeStamp 可以转成Date对象

Handling Errors

getCurrentPosition() 的第二个参数(可选)——容错处理的回调函数:

<script type='text/javascript'>
  function find_my_location() {
    if (Modernizr.geolocation) {
      navigator.geolocation.getCurrentPosition(show_map, handle_error);
    } else {
      // 其他方案
    }
  }
  
  function handle_error(err) {
    if (err.code == 1) {
      // 用户说不!
    }
  }    
</script>    

在获取地理位置过程中有任何错误,都会调用该回调函数,并且会传入一个 PositionError 对象作为参数。

PositionError 对象

属性 类型 备注
code short 可枚举
message DOMString 与终端用户无关

其中code属性具有以下属性值:

  • PERMISSION_DENIED(1): 用户不同意被获取位置信息。
  • POSITION_UNAVAILABLE(2): 网络不可用或者无法连接到获取位置信息的卫星。
  • TIMEOUT(3): 网络可用但是花了太长时间的计算用户的位置上。
  • UNKNOWN_ERROR(0): 发生其他未知错误。

PositionOptions 对象

两种定位方式和缓存的位置信息

属性 类型 默认值 备注
enableHighAccuracy boolean false 设成 true 可能会使得获取位置的速度变慢
timeout long 没有默认值 单位:毫秒
maximumAge long 0 单位:毫秒

Device Orientation

设备事件

设备事件

设备事件可以让开发人员确定用户在怎样使用设备(智能手机,平板电脑)

  • orientationChange 事件
  • MozOrientation 事件
  • deviceorientation 事件
  • devicemotion 事件
http://dev.w3.org/geo/api/spec-source-orientation

orientationchange 事件

苹果公司为移动 Safari 添加了 orientationchange 事件,以便开发人员能确定用户何时将设备由横向查看模式切换为纵向查看模式。移动 Safari 的 window.orientation 属性中可能包含3个值:

  • 0 表示肖像模式(Portrait)
  • 90 表示向左旋转的横向模式(“主屏幕”按钮在右侧)
  • -90 表示向右旋转的横向模式(“主屏幕”按钮在左侧)

处理 orientationchange 事件

这时的 event 对象不包含任何有价值信息,唯一相关的信息可以通过 window.orientation 访问到。

    function updateOrientation() {
        switch(window.orientation) {
        case 0:
        // ...
        case -90:                        
        // ....
        case 90:
        // ...
        case 180:
        // ...
        }
    };    
    window.addEventListener('orientationchange', updateOrientation, false);
      

Demo: orientationchange

根据 orientationchange 事件动态更改图像大小

orientationchange example

landscape 模式下把图片宽高调小

Description
iPad 下:http://192.168.1.113:8000/demo/device-access/orientation/orientationchange.html

Demo:orientation-mediaquery

实现这个效果也可以使用媒体查询方式

deviceorientation 事件

加速度计检测到设备的方向发生变化时,会在 window 对象上触发 deviceorientation 事件。用于告诉我们设备在空间上朝向哪儿。

设备坐标系的概念:x 轴方向是从左往右,y 轴方向是从下往上,z 轴方向是从后往前。当设备静止放在水平桌面时,这三个值都是 0

deviceorientation

deviceorientation 事件对象

事件对象包含着每个轴相对于设备静止状态下发生变化的信息。

设备坐标系的概念:x 轴方向是从左往右,y 轴方向是从下往上,z 轴方向是从后往前。当设备静止放在水平桌面时,这三个值都是 0

其中三个主要的属性:

  • alpha: 在围绕 z 轴旋转时(即左右旋转时),y 轴的度数差。
  • beta: 在围绕 x 轴旋转时(即前后旋转时),z 轴的度数差。
  • gamma: 在围绕 y 轴旋转时(即扭转设备时),z 轴的度数差。

alpha

围绕 z 轴旋转会引起 alpha 旋转角度发生变化。

当设备顶部指向地球正北方向时,alpha 角是 0 度,设备向左边旋转时增大,介于 0 - 360 度之间。

deviceorientation

beta

围绕 x 轴旋转,也就是前后翻转(朝着用户或者远离用户)时,会引起 beta 旋转角度变化。

设备水平放置时,beta 角度是 0 度;向上翻逐步增加到 180 度;向下翻减少到 -180 度。

deviceorientation

gamma

围绕 y 轴旋转,会引起 gamma 角度值的变化。

水平放置角度是 0,向右拧增加到 90 度;向左拧减少到 -90 度。

deviceorientation

Demo: deviceorientation

  • Rotate Chrome
  • 模拟 orientation 事件:http://louisremi.github.com/orientation-devtool/

MozOrientation 事件

兼容移动版 Firefox

Firefox 移动浏览器上实现的检测设备方向的事件。静止状态下,x 值为 0,y 值为 0,z 值为 1。这几个值都介于1和-1之间。

  • 向右倾斜,x 会减少到 -1;向左倾斜,x 会增大到 1
  • 向远离用户方向倾斜,y 值会减少到 -1;向接近用户方向倾斜,y 值会增大到 1;
			// 针对 Android 版的 Firefox
      if (!evt.gamma && !evt.beta) {
        evt.gamma = -(evt.x * (180 / Math.PI));
        evt.beta = (evt.y * (180 / Math.PI));
      }
      

deviceorientation 补充说明

截止2013年1月,Mozilla 声称自 FF6+ 之后都支持 deviceorientation 事件,实际并不支持;反而是号称从 3.6 开始支持,但是后面又移走的 MozOrientation 事件在 Android 版的 Firefox 上支持 MozOrientation 事件。

Chrome 和 Android 版的 WebKit,iOS4.2+ 的 Safari 均支持 deviceorientation 事件。

参见:http://caniuse.com/#feat=deviceorientation

devicemotion 事件

deviceorientation 的超集,除了方向信息以外,还有加速度信息。

  • acceleration: 一个包含 x,y,z 属性的对象,不考虑重力加速度的情况。
  • accelerationIncludingGravity: 考虑 z 轴自然重力加速的情况下,告诉你每个方向上的加速度。

Touch Events

触控事件

触控和手势

Notes: 有些手势不产生事件,有些手势需要在一定的条件下才会产生事件;但是我们可以通过组合各种手势进行处理。

  • One-Finger Events
    • The panning gesture
    • The touch and hold gesture
    • The double-tap gesture
  • Two-Finger Events
    • The pinch open gesture
    • Two-finger panning gesture
  • Multi-Touch Events

Multi-touch Events

  • TouchEvent
  • Touch
  • TouchList

TouchEvent 事件类型

  • touchstart: 当手指触摸屏幕时触发(即使已经有一个手指已经放在了屏幕上)
  • touchmove: 当手指在屏幕上滑动时连续的触发
  • touchend: 当手指从屏幕上移开时触发
  • touchcancel: 当系统停止跟踪触摸时触发

TouchEvent 的属性

  • 首先是在鼠标事件中常见的属性: bubbles, cancelable, detail, altKey, ctrlKey ...
  • 其次是三个用于跟踪触摸的属性:
    • touches: 表示当前跟踪的触摸操作的 Touch 对象的数组
    • targetTouches: 特定于事件目标的 Touch 对象的数组
    • changeTouches: 表示自上次触摸以来发生了什么改变的 Touch 对象的数组

Touch 对象的属性

  • clientX: 相对于 viewport 的 x 坐标,类型 long,单位像素
  • clientY: 相对于 viewport 的 y 轴坐标
  • identifier:触控点的唯一标识(比方说一根手指就是一个一个触控点)
  • pageX: 页面中的 x 坐标
  • pageY:页面中的 y 坐标
  • screenX:屏幕中的 x 坐标
  • screenY:屏幕中的 y 坐标
  • target:触摸的 DOM 节点目标

Multi-touch Demo

Touch Events + Canvas

  • 设置触控事件处理程序
  • 跟踪新的触控(touchstart)发生
  • 随着滑动(touchmove)进行 Canvas 绘制
  • 处理触控结束(touchend)事件
  • 处理触控取消(touchcancel)事件

The panning gesture

直到用户停止 panning 的时候,One-finger panning 才会产生一个 onscroll 事件

The panning gesture
A touch-scrollable div: http://eightmedia.github.com/hammer.js/scroll/

The touch and hold gesture

长按不会产生事件;但是如果触控的是图片,可点击链接或是可编辑内容等往往会生成一个 information bubble。(复制,粘贴,全选,图片另存为 ...)

The touch and hold gesture
Basic demo: http://eightmedia.github.com/hammer.js/demo/

The double-tap gesture

double tap 也不产生任何事件

The double-tap gesture
Basic demo: http://eightmedia.github.com/hammer.js/demo/

The pinch open gesture

pinch open gesture 不产生任何鼠标事件

The pinch open gesture
http://eightmedia.github.com/hammer.js/zoom/, http://eightmedia.github.com/hammer.js/zoom/index2.html

Two finger panning gesture

  • 两根手指按住屏幕并移动,如果落在可滚动的元素上,产生 mousewheel 事件
  • 如果元素不是可滚动的,移动网页。在 panning 过程中不产生事件
  • 当用户停止 panning 时,产生一个 onscroll 事件
Two-finger panning gesture
http://eightmedia.github.com/hammer.js/zoom/, http://eightmedia.github.com/hammer.js/zoom/index2.html

扩展阅读

<Thank you!>