HTML5的Device API中提供了几个DOM事件,可以获得设备的物理方向及运动的信息,API提供的数据不是来源于原始的传感器信息,而是来源于设备上的陀螺仪、加速计以及指南针等。
首先我们来关注一下deviceorientation和devicemotion这两个事件的兼容性:
只能算是部分支持,所以在使用时,首先需要检测支持能力,很简单:
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', function(event) {}, false);
} else {
alert('本设备不支持deviceorientation事件');
}
if (window.DeviceMotionEvent) {
window.addEventListener('devicemotion', deviceMotionHandler, false);
} else {
alert('本设备不支持devicemotion事件');
}
对于不支持的平台,就不要想太炫酷的效果了,老老实实用触摸滑动等基础操作与用户交互,对于各种动态效果或者交互,我认为第一原则是保证可用且性能良好。
// 注册一个deviceorientation事件的接收器:
window.addEventListener("deviceorientation", function(event) {
// 处理event.alpha、event.beta及event.gamma
}, true);
event.alpha、event.beta及event.gamma表示设备坐标系上的旋角,这个角度具体是怎么理解的呢?先来看看从标准上贴过来的一段话:对于一个移动设备,例如电话或平板,设备坐标系的定义于屏幕的标准方向相关。这意味着类似于键盘的滑动元素没有展开、类似于显示器的选择元素折叠至其默认位置。如果在设备旋转或展开滑动键盘时屏幕方向发生变化,这不会影响关于设备的坐标系的方向。用户希望获得这些屏幕方向的变化可以使用现有的orientationchange事件。
这段话的重点是,因为设备坐标系是一个相对的方向坐标系,所以设备旋转等事件发生后,设备坐标系会根据基准的改变相对应改变。 地球坐标系:
对于笔记本电脑,设备的坐标系定义于集成键盘:
以两个坐标系重合为初始状态,旋转应用下列规则:
deviceorientation事件提供一个absolute属性参数,值为true时,提供三个角度绝对值, 为false时,提供任意方向的相对值。
// 注册一个devicemotion时间的接收器:
window.addEventListener("devicemotion", function(event) {
// 处理event.acceleration、event.accelerationIncludingGravity、
// event.rotationRate和event.interval
}, true);
每当设备运动状态出现加速或者减速时,devicemotio事件都会被触发。event事件包含acceleration、accelerationIncludingGravity、rotationRate以及interval四个属性。
既然我们可以获取设备当前的3D角度,并且可以获得设备在空间中的运动速度,很容易就能想到摇一摇这样有趣的应用。 摇一摇判断即判定设备是否有超过加速度变化临界值的晃动:
if (window.DeviceMotionEvent) {
window.addEventListener('devicemotion', shakeEventHandler, false);
} else {
alert('本设备不支持devicemotion事件');
}
var THRESHOLD = 1000;
var preX = preY = preZ = x = y = z = 0;
var preTime = 0;
function shakeEventHandler(event) {
var acceleration = event.accelerationIncludingGravity;
var curTime = new Date().getTime();
var diffTime = curTime-preTime;
if (diffTime > 100) {
preTime = curTime;
x = acceleration.x;
y = acceleration.y;
z = acceleration.z;
var accelerationDiff = Math.abs(x + y + z - preX - preY - preZ) / diffTime * 10000;
if (accelerationDiff > THRESHOLD) {
alert("摇一摇有惊喜!");
}
preX = x;
preY = y;
preZ = z;
}
}