DeviceOrientationEvent 规范也定义了 devicemotion 事件。这个事件用于提示设备实际上在移动, 而不仅仅是改变了朝向。例如,devicemotion 事件可以用来确定设备正在掉落或者正拿在一个行走的 人手里。
当 devicemotion 事件触发时,event 对象中包含如下额外的属性。
acceleration:对象,包含 x、y 和 z 属性,反映不考虑重力情况下各个维度的加速信息。
accelerationIncludingGravity:对象,包含 x、y 和 z 属性,反映各个维度的加速信息,
包含 z 轴自然重力加速度。
interval:毫秒,距离下次触发 devicemotion 事件的时间。此值在事件之间应为常量。
rotationRate:对象,包含 alpha、beta 和 gamma 属性,表示设备朝向。
如果无法提供 acceleration、accelerationIncludingGravity 和 rotationRate 信息,则 属性值为 null。为此,在使用这些属性前必须先检测它们的值是否为 null。比如:
window.addEventListener("devicemotion", (event) => {
let output = document.getElementById("output");
if (event.rotationRate !== null) {
output.innerHTML += `Alpha=${event.rotationRate.alpha}` +
`Beta=${event.rotationRate.beta}` +
触摸及手势事件
`Gamma=${event.rotationRate.gamma}`;
Safari 为 iOS 定制了一些专有事件,以方便开发者。因为 iOS 设备没有鼠标和键盘,所以常规的鼠 25 标和键盘事件不足以创建具有完整交互能力的网页。同时,WebKit 也为 Android 定制了很多专有事件, 成为了事实标准,并被纳入 W3C 的 Touch Events 规范。本节介绍的事件只适用于触屏设备。
1. 触摸事件
iPhone 3G 发布时,iOS 2.0 内置了新版本的 Safari。这个新的移动 Safari 支持一些与触摸交互有关的 新事件。后来的 Android 浏览器也实现了同样的事件。当手指放在屏幕上、在屏幕上滑动或从屏幕移开 时,触摸事件即会触发。触摸事件有如下几种。
touchstart:手指放到屏幕上时触发(即使有一个手指已经放在了屏幕上)。
touchmove:手指在屏幕上滑动时连续触发。在这个事件中调用 preventDefault()可以阻止
touchend:手指从屏幕上移开时触发。
touchcancel:系统停止跟踪触摸时触发。文档中并未明确什么情况下停止跟踪。 这些事件都会冒泡,也都可以被取消。尽管触摸事件不属于 DOM 规范,但浏览器仍然以兼容 DOM
的方式实现了它们。因此,每个触摸事件的 event 对象都提供了鼠标事件的公共属性:bubbles、 cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、 ctrlKey 和 metaKey。
除了这些公共的 DOM 属性,触摸事件还提供了以下 3 个属性用于跟踪触点。
touches:Touch 对象的数组,表示当前屏幕上的每个触点。
targetTouches:Touch 对象的数组,表示特定于事件目标的触点。
changedTouches:Touch 对象的数组,表示自上次用户动作之后变化的触点。 每个 Touch 对象都包含下列属性。
clientX:触点在视口中的 x 坐标。
clientY:触点在视口中的 y 坐标。
identifier:触点 ID。
pageX:触点在页面上的 x 坐标。
pageY:触点在页面上的 y 坐标。
screenX:触点在屏幕上的 x 坐标。
screenY:触点在屏幕上的 y 坐标。
target:触摸事件的事件目标。 这些属性可用于追踪屏幕上的触摸轨迹。例如:
function handleTouchEvent(event) { // 只针对一个触点
if (event.touches.length == 1) {
let output = document.getElementById("output");
switch(event.type) {
case "touchstart":
output.innerHTML += `<br>Touch started:` +
`(${event.touches[0].clientX}` +
` ${event.touches[0].clientY})`;
break;
case "touchend":
output.innerHTML += `<br>Touch ended:` +
`(${event.changedTouches[0].clientX}` +
` ${event.changedTouches[0].clientY})`;
break;
case "touchmove":
event.preventDefault(); // 阻止滚动 output.innerHTML += `<br>Touch moved:` +
break; }
} }
`(${event.changedTouches[0].clientX}` +
` ${event.changedTouches[0].clientY})`;
document.addEventListener("touchstart", handleTouchEvent); document.addEventListener("touchend", handleTouchEvent); document.addEventListener("touchmove", handleTouchEvent);
以上代码会追踪屏幕上的一个触点。为简单起见,代码只会在屏幕有一个触点时输出信息。在 touchstart 事件触发时,触点的位置信息会输出到 output 元素中。在 touchmove 事件触发时,会 取消默认行为以阻止滚动(移动触点通常会滚动页面),并输出变化的触点信息。在 touchend 事件触 发时,会输出触点最后的信息。注意,touchend 事件触发时 touches 集合中什么也没有,这是因为 没有滚动的触点了。此时必须使用 changedTouches 集合。
这些事件会在文档的所有元素上触发,因此可以分别控制页面的不同部分。当手指点触屏幕上的元 素时,依次会发生如下事件(包括鼠标事件):
(1) touchstart
(2) mouseover
(3) mousemove(1 次)
(4) mousedown
(5) mouseup
(6) click 19 (7) touchend