Web浏览器的事件类型——手势事件

835 阅读4分钟

这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战

1. 触摸事件

当手指放在屏幕上、在屏幕上滑动或从屏幕移开时,触摸事件即会触发。触摸事件有如下几种:

  • touchstart:手指放到屏幕上时触发(即使有一个手指已经放在了屏幕上)。
  • touchmove:手指在屏幕上滑动时连续触发。在这个事件中调用 preventDefault() 可以阻止滚动。
  • touchend:手指从屏幕上移开时触发。
  • touchcancel:系统停止跟踪触摸时触发。有几种可能的原因如下:
    • 由于某个事件出现而取消了触摸:例如触摸过程被弹窗打断。
    • 触点离开了文档窗口,而进入了浏览器的界面元素、插件或者其他外部内容区域。
    • 当用户产生的触点个数超过了设备支持的个数,从而导致 TouchList 中最早的 Touch 对象被取消。

每个触摸事件的 event 对象都提供了鼠标事件的公共属性:bubblescancelableviewclientXclientYscreenXscreenYdetailaltKeyshiftKeyctrlKeymetaKey。除了这些公共的 DOM 属性,触摸事件还提供了以下 3 个属性用于跟踪触点。

  • touchesTouch 对象的数组,表示当前屏幕上的每个触点。
  • targetTouchesTouch 对象的数组,表示特定于事件目标的触点。
  • changedTouchesTouch 对象的数组,表示自上次用户动作之后变化的触点。

每个 Touch 对象都包含下列属性。

  • clientX:触点在视口中的 x 坐标。
  • clientY:触点在视口中的 y 坐标。
  • identifier:触点 ID
  • pageX:触点在页面上的 x 坐标。
  • pageY:触点在页面上的 y 坐标。
  • screenX:触点在屏幕上的 x 坐标。
  • screenY:触点在屏幕上的 y 坐标。
  • target:触摸事件的事件目标。

这里我们来用 canvas 作为 touch 事件的例子:

<canvas
  id="canvas"
  width="600"
  height="600"
  style="border: solid black 1px"
>
  Your browser does not support canvas element.
</canvas>

DOMContentLoaded 事件之后,监听 canvas 内部的 touch 事件。并打印其在屏幕上的触发点。

function startup() {
  var el = document.getElementById("canvas");
  el.addEventListener("touchstart", handleStart, false);
  el.addEventListener("touchend", handleEnd, false);
  el.addEventListener("touchcancel", handleCancel, false);
  el.addEventListener("touchmove", handleMove, false);
}

document.addEventListener("DOMContentLoaded", startup);

function handleStart(evt) {
  evt.preventDefault();
  const { identifier, pageX, pageY } = evt.changedTouches[0];
  console.log('handleStart', { identifier, pageX, pageY });
}

function handleEnd(evt) {
  evt.preventDefault();
  const { identifier, pageX, pageY } = evt.changedTouches[0];
  console.log('handleEnd', { identifier, pageX, pageY });
}

function handleCancel(evt) {
  evt.preventDefault();
  const { identifier, pageX, pageY } = evt.changedTouches[0];
  console.log('handleCancel', { identifier, pageX, pageY });
}

function handleMove(evt) {
  evt.preventDefault();
  const { identifier, pageX, pageY } = evt.changedTouches[0];
  console.log('handleMove', { identifier, pageX, pageY });
}

当手指点触屏幕上的元素时,依次会发生如下事件(包括鼠标事件):

  1. touchstart
  2. mouseover
  3. mousemove(1次)
  4. mousedown
  5. mouseup
  6. click
  7. touchend

2. 手势事件

1) GestureEvent

GestureEvent 仅在 ios 中的 safari 中可以使用。手势事件会在两个手指触碰屏幕且相对距离或旋转角度变化时触发。手势事件有以下 3 种。

  • gesturestart:一个手指已经放在屏幕上,再把另一个手指放到屏幕上时触发。
  • gesturechange:任何一个手指在屏幕上的位置发生变化时触发。
  • gestureend:其中一个手指离开屏幕时触发。

只有在两个手指同时接触事件接收者时,这些事件才会触发。在一个元素上设置事件处理程序,意味着两个手指必须都在元素边界以内才能触发手势事件(这个元素就是事件目标)。

触摸事件和手势事件存在一定的关系。当一个手指放在屏幕上时,会触发 touchstart 事件。当另一个手指放到屏幕上时,gesturestart 事件会首先触发,然后紧接着触发这个手指的 touchstart 事件。如果两个手指或其中一个手指移动,则会触发 gesturechange 事件。只要其中一个手指离开屏幕,就会触发 gestureend 事件,紧接着触发该手指的 touchend 事件。

与触摸事件类似,每个手势事件的 event 对象都包含所有标准的鼠标事件属性。新增的两个 event 对象属性是 rotationscale

  • rotation:属性表示手指变化旋转的度数,负值表示逆时针旋转,正值表示顺时针旋转(从 0 开始)。
  • scale:属性表示两指之间距离变化(对捏)的程度。开始时为 1,然后随着距离增大或缩小相应地增大或缩小。

2) MSGestureEvent

MSGestureEvent 仅在 IEEdge 中可以使用,表​​示由于触摸手势而发生的事件,有以下 6 种。

  • MSGestureStart:当触摸表面上有一个新的接触点时会触发该事件,从而开始一个新的手势。
  • MSGestureEnd:当所有关联的触摸点都停止接触触摸表面,并且所有关联的惯性运动都结束时触发该事件。
  • MSGestureTap:当用户轻敲指点设备时触发该事件。
  • MSGestureHold:当用户接触触摸表面并在同一位置保持一段时间时触发该事件。
  • MSGestureChange:当触摸接触位置移动以及处理基于惯性的移动时会触发该事件。
  • MSInertiaStart:当滚动有足够的惯性继续滚动时,当与触摸表面的接触停止时触发该事件。

手势事件都是非标准的事件,将来会有很大的改变,开发使用时需要谨慎对待。

3. 引用