为了更好地为移动设备服务,HTML 5推出了一系列针对移动设备的API。
[TOC]
## Viewport
Viewport指的是网页的显示区域,也就是不借助滚动条的情况下,用户可以看到的部分网页大小,中文译为“视口”。正常情况下,viewport和浏览器的显示窗口是一样大小的。但是,在移动设备上,两者可能不是一样大小。
比如,手机浏览器的窗口宽度可能是640像素,这时viewport宽度就是640像素,但是网页宽度有950像素,正常情况下,浏览器会提供横向滚动条,让用户查看窗口容纳不下的310个像素。另一种方法则是,将viewport设成950像素,也就是说,浏览器的显示宽度还是640像素,但是网页的显示区域达到950像素,整个网页缩小了,在浏览器中可以看清楚全貌。这样一来,手机浏览器就可以看到网页在桌面浏览器上的显示效果。
viewport缩放规则,需要在HTML网页的head部分指定。
~~~
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
</head>
~~~
上面代码指定,viewport的缩放规则是,缩放到当前设备的屏幕宽度(device-width),初始缩放比例(initial-scale)为1倍,禁止用户缩放(user-scalable)。
viewport 全部属性如下。
* width: viewport宽度
* height: viewport高度
* initial-scale: 初始缩放比例
* maximum-scale: 最大缩放比例
* minimum-scale: 最小缩放比例
* user-scalable: 是否允许用户缩放
其他的例子如下。
~~~
<meta name = "viewport" content = "width = 320,
initial-scale = 2.3, user-scalable = no">
~~~
## Geolocation API
Geolocation接口用于获取用户的地理位置。它使用的方法基于GPS或者其他机制(比如IP地址、Wifi热点、手机基站等)。
下面的方法,可以检查浏览器是否支持这个接口。
~~~
if(navigator.geolocation) {
// 支持
} else {
// 不支持
}
~~~
这个API的支持情况非常好,所有浏览器都支持(包括IE 9+),所以上面的代码不是很必要。
### getCurrentPosition方法
getCurrentPosition方法,用来获取用户的地理位置。使用它需要得到用户的授权,浏览器会跳出一个对话框,询问用户是否许可当前页面获取他的地理位置。必须考虑两种情况的回调函数:一种是同意授权,另一种是拒绝授权。如果用户拒绝授权,会抛出一个错误。
~~~
navigator.geolocation.getCurrentPosition(geoSuccess,geoError);
~~~
上面代码指定了处理当前地理位置的两个回调函数。
(1)同意授权
如果用户同意授权,就会调用geoSuccess。
~~~
function geoSuccess(event) {
console.log(event.coords.latitude + ', ' + event.coords.longitude);
}
~~~
geoSuccess的参数是一个event对象。event有两个属性:timestamp和coords。timestamp属性是一个时间戳,返回获得位置信息的具体时间。coords属性指向一个对象,包含了用户的位置信息,主要是以下几个值:
* coords.latitude:纬度
* coords.longitude:经度
* coords.accuracy:精度
* coords.altitude:海拔
* coords.altitudeAccuracy:海拔精度(单位:米)
* coords.heading:以360度表示的方向
* coords.speed:每秒的速度(单位:米)
大多数桌面浏览器不提供上面列表的后四个值。
(2)拒绝授权
如果用户拒绝授权,就会调用getCurrentPosition方法指定的第二个回调函数geoError。
~~~
function geoError(event) {
console.log("Error code " + event.code + ". " + event.message);
}
~~~
geoError的参数也是一个event对象。event.code属性表示错误类型,有四个值:
* 0:未知错误,浏览器没有提示出错的原因,相当于常量event.UNKNOWN_ERROR。
* 1:用户拒绝授权,相当于常量event.PERMISSION_DENIED。
* 2:没有得到位置,GPS或其他定位机制无法定位,相当于常量event.POSITION_UNAVAILABLE。
* 3:超时,GPS没有在指定时间内返回结果,相当于常量event.TIMEOUT。
(3)设置定位行为
getCurrentPosition方法还可以接受一个对象作为第三个参数,用来设置定位行为。
~~~
var option = {
enableHighAccuracy : true,
timeout : Infinity,
maximumAge : 0
};
navigator.geolocation.getCurrentPosition(geoSuccess, geoError, option);
~~~
这个参数对象有三个成员:
* enableHighAccuracy:如果设为true,就要求客户端提供更精确的位置信息,这会导致更长的定位时间和更大的耗电,默认设为false。
* Timeout:等待客户端做出回应的最大毫秒数,默认值为Infinity(无限)。
* maximumAge:客户端可以使用缓存数据的最大毫秒数。如果设为0,客户端不读取缓存;如果设为infinity,客户端只读取缓存。
### watchPosition方法和clearWatch方法
watchPosition方法可以用来监听用户位置的持续改变,使用方法与getCurrentPosition方法一样。
~~~
var watchID = navigator.geolocation.watchPosition(geoSuccess,geoError, option);
~~~
一旦用户位置发生变化,就会调用回调函数geoSuccess。这个回调函数的事件对象,也包含timestamp和coords属性。
watchPosition和getCurrentPosition方法的不同之处在于,前者返回一个表示符,后者什么都不返回。watchPosition方法返回的标识符,用于供clearWatch方法取消监听。
~~~
navigator.geolocation.clearWatch(watchID);
~~~
## Vibration API
Vibration接口用于在浏览器中发出命令,使得设备振动。显然,这个API主要针对手机,适用场合是向用户发出提示或警告,游戏中尤其会大量使用。由于振动操作很耗电,在低电量时最好取消该操作。
使用下面的代码检查该接口是否可用。目前,只有Chrome和Firefox的Android平台最新版本支持它。
~~~
navigator.vibrate = navigator.vibrate
|| navigator.webkitVibrate
|| navigator.mozVibrate
|| navigator.msVibrate;
if (navigator.vibrate) {
// 支持
}
~~~
vibrate方法可以使得设备振动,它的参数就是振动持续的毫秒数。
~~~
navigator.vibrate(1000);
~~~
上面的代码使得设备振动1秒钟。
vibrate方法还可以接受一个数组作为参数,表示振动的模式。偶数位置的数组成员表示振动的毫秒数,奇数位置的数组成员表示等待的毫秒数。
~~~
navigator.vibrate([500, 300, 100]);
~~~
上面代码表示,设备先振动500毫秒,然后等待300毫秒,再接着振动500毫秒。
vibrate是一个非阻塞式的操作,即手机振动的同时,JavaScript代码继续向下运行。要停止振动,只有将0毫秒或者一个空数组传入vibrate方法。
~~~
navigator.vibrate(0);
navigator.vibrate([]);
~~~
如果要让振动一直持续,可以使用setInterval不断调用vibrate。
~~~
var vibrateInterval;
function startVibrate(duration) {
navigator.vibrate(duration);
}
function stopVibrate() {
if(vibrateInterval) clearInterval(vibrateInterval);
navigator.vibrate(0);
}
function startPeristentVibrate(duration, interval) {
vibrateInterval = setInterval(function() {
startVibrate(duration);
}, interval);
}
~~~
## Luminosity API
Luminosity API用于屏幕亮度调节,当移动设备的亮度传感器感知外部亮度发生显著变化时,会触发devicelight事件。目前,只有Firefox部署了这个API。
~~~
window.addEventListener('devicelight', function(event) {
console.log(event.value + 'lux');
});
~~~
上面代码表示,devicelight事件的回调函数,接受一个事件对象作为参数。该对象的value属性就是亮度的流明值。
这个API的一种应用是,如果亮度变强,网页可以显示黑底白字,如果亮度变弱,网页可以显示白底黑字。
~~~
window.addEventListener('devicelight', function(e) {
var lux = e.value;
if(lux < 50) {
document.body.className = 'dim';
}
if(lux >= 50 && lux <= 1000) {
document.body.className = 'normal';
}
if(lux > 1000) {
document.body.className = 'bright';
}
});
~~~
CSS下一个版本的Media Query可以单独设置亮度,一旦浏览器支持,就可以用来取代Luminosity API。
~~~
@media (light-level: dim) {
/* 暗光环境 */
}
@media (light-level: normal) {
/* 正常光环境 */
}
@media (light-level: washed) {
/* 明亮环境 */
}
~~~
## Orientation API
Orientation API用于检测手机的摆放方向(竖放或横放)。
使用下面的代码检测浏览器是否支持该API。
~~~
if (window.DeviceOrientationEvent) {
// 支持
} else {
// 不支持
}
~~~
一旦设备的方向发生变化,会触发deviceorientation事件,可以对该事件指定回调函数。
~~~
window.addEventListener("deviceorientation", callback);
~~~
回调函数接受一个event对象作为参数。
~~~
function callback(event){
console.log(event.alpha);
console.log(event.beta);
console.log(event.gamma);
}
~~~
上面代码中,event事件对象有alpha、beta和gamma三个属性,它们分别对应手机摆放的三维倾角变化。要理解它们,就要理解手机的方向模型。当手机水平摆放时,使用三个轴标示它的空间位置:x轴代表横轴、y轴代表竖轴、z轴代表垂直轴。event对象的三个属性就对应这三根轴的旋转角度。
* alpha:表示围绕z轴的旋转,从0到360度。当设备水平摆放时,顶部指向地球的北极,alpha此时为0。
* beta:表示围绕x轴的旋转,从-180度到180度。当设备水平摆放时,beta此时为0。
* gramma:表示围绕y轴的选择,从-90到90度。当设备水平摆放时,gramma此时为0。
## 参考链接
* Ryan Stewart, [Using the Geolocation API](http://www.adobe.com/devnet/html5/articles/using-geolocation-api.html)
* Rathnakanya K. Srinivasan, [HTML5 Geolocation](http://www.sitepoint.com/html5-geolocation/)
* Craig Buckler, [How to Use the HTML5 Vibration API](http://www.sitepoint.com/use-html5-vibration-api/)
* Tomomi Imura, [Responsive UI with Luminosity Level](http://girliemac.com/blog/2014/01/12/luminosity/)
* Aurelio De Rosa, [An Introduction to the Geolocation API](http://code.tutsplus.com/tutorials/an-introduction-to-the-geolocation-api--cms-20071)
* David Walsh, [Vibration API](http://davidwalsh.name/vibration-api)
* Ahmet Mermerkaya, [Using Device Orientation in HTML5](http://www.sitepoint.com/using-device-orientation-html5/)
- 第一章 导论
- 1.1 前言
- 1.2 为什么学习JavaScript?
- 1.3 JavaScript的历史
- 第二章 基本语法
- 2.1 语法概述
- 2.2 数值
- 2.3 字符串
- 2.4 对象
- 2.5 数组
- 2.6 函数
- 2.7 运算符
- 2.8 数据类型转换
- 2.9 错误处理机制
- 2.10 JavaScript 编程风格
- 第三章 标准库
- 3.1 Object对象
- 3.2 Array 对象
- 3.3 包装对象和Boolean对象
- 3.4 Number对象
- 3.5 String对象
- 3.6 Math对象
- 3.7 Date对象
- 3.8 RegExp对象
- 3.9 JSON对象
- 3.10 ArrayBuffer:类型化数组
- 第四章 面向对象编程
- 4.1 概述
- 4.2 封装
- 4.3 继承
- 4.4 模块化编程
- 第五章 DOM
- 5.1 Node节点
- 5.2 document节点
- 5.3 Element对象
- 5.4 Text节点和DocumentFragment节点
- 5.5 Event对象
- 5.6 CSS操作
- 5.7 Mutation Observer
- 第六章 浏览器对象
- 6.1 浏览器的JavaScript引擎
- 6.2 定时器
- 6.3 window对象
- 6.4 history对象
- 6.5 Ajax
- 6.6 同域限制和window.postMessage方法
- 6.7 Web Storage:浏览器端数据储存机制
- 6.8 IndexedDB:浏览器端数据库
- 6.9 Web Notifications API
- 6.10 Performance API
- 6.11 移动设备API
- 第七章 HTML网页的API
- 7.1 HTML网页元素
- 7.2 Canvas API
- 7.3 SVG 图像
- 7.4 表单
- 7.5 文件和二进制数据的操作
- 7.6 Web Worker
- 7.7 SSE:服务器发送事件
- 7.8 Page Visibility API
- 7.9 Fullscreen API:全屏操作
- 7.10 Web Speech
- 7.11 requestAnimationFrame
- 7.12 WebSocket
- 7.13 WebRTC
- 7.14 Web Components
- 第八章 开发工具
- 8.1 console对象
- 8.2 PhantomJS
- 8.3 Bower:客户端库管理工具
- 8.4 Grunt:任务自动管理工具
- 8.5 Gulp:任务自动管理工具
- 8.6 Browserify:浏览器加载Node.js模块
- 8.7 RequireJS和AMD规范
- 8.8 Source Map
- 8.9 JavaScript 程序测试
- 第九章 JavaScript高级语法
- 9.1 Promise对象
- 9.2 有限状态机
- 9.3 MVC框架与Backbone.js
- 9.4 严格模式
- 9.5 ECMAScript 6 介绍
- 附录
- 10.1 JavaScript API列表
- 草稿一:函数库
- 11.1 Underscore.js
- 11.2 Modernizr
- 11.3 Datejs
- 11.4 D3.js
- 11.5 设计模式
- 11.6 排序算法
- 草稿二:jQuery
- 12.1 jQuery概述
- 12.2 jQuery工具方法
- 12.3 jQuery插件开发
- 12.4 jQuery.Deferred对象
- 12.5 如何做到 jQuery-free?
- 草稿三:Node.js
- 13.1 Node.js 概述
- 13.2 CommonJS规范
- 13.3 package.json文件
- 13.4 npm模块管理器
- 13.5 fs 模块
- 13.6 Path模块
- 13.7 process对象
- 13.8 Buffer对象
- 13.9 Events模块
- 13.10 stream接口
- 13.11 Child Process模块
- 13.12 Http模块
- 13.13 assert 模块
- 13.14 Cluster模块
- 13.15 os模块
- 13.16 Net模块和DNS模块
- 13.17 Express框架
- 13.18 Koa 框架