使用触摸事件

如今,大多数 Web 内容都是为键盘和鼠标输入设计的。然而,带触摸屏的设备(尤其是便携式设备)已成为主流,Web 应用程序可以通过使用 触摸事件 直接处理基于触摸的输入,或者应用程序可以使用解释后的鼠标事件作为应用程序输入。使用鼠标事件的一个缺点是它们不支持并发用户输入,而触摸事件支持多个同时输入(可能位于触摸表面的不同位置),从而增强了用户体验。

触摸事件接口支持应用程序特定的单点和多点触摸交互,例如双指手势。多点触摸交互在手指(或触控笔)首次接触接触面时开始。随后可能有其他手指接触表面,并可选择性地在触摸表面上移动。当手指从表面移开时,交互结束。在此交互过程中,应用程序会在开始、移动和结束阶段接收触摸事件。应用程序可以为其触摸输入应用自己的语义。

接口

触摸事件由三个接口(TouchTouchEventTouchList)以及以下事件类型组成:

  • touchstart - 当触摸点放置在触摸表面上时触发。
  • touchmove - 当触摸点沿触摸表面移动时触发。
  • touchend - 当触摸点从触摸表面移除时触发。
  • touchcancel - 当触摸点以实现特定方式中断时触发(例如,创建了过多的触摸点)。

Touch 接口代表触摸感应设备上的单个接触点。接触点通常被称为触摸点或简称为触摸。触摸通常由手指或触控笔在触摸屏、笔或触控板上产生。触摸点的属性包括一个唯一的标识符、触摸点的目标元素以及触摸点相对于视口、页面和屏幕位置的XY坐标。

TouchList 接口代表一个触摸表面的接触点列表,每个接触点对应一个触摸点。因此,如果用户用一根手指激活了触摸表面,列表将包含一项;如果用户用三根手指触摸了表面,列表长度将为三。

TouchEvent 接口表示在触摸感应表面的接触状态发生变化时发送的事件。状态变化包括开始接触触摸表面、在保持接触表面的同时移动触摸点、释放触摸点以及取消触摸事件。此接口的属性包括几个修饰键(例如 shift 键)的状态以及以下触摸列表:

  • touches - 当前屏幕上所有触摸点的列表。
  • targetTouches - 目标 DOM 元素上触摸点的列表。
  • changedTouches - 其项目取决于关联事件类型的触摸点的列表。
    • 对于 touchstart 事件,它是当前事件激活的触摸点的列表。
    • 对于 touchmove 事件,它是自上次事件以来发生变化的触摸点的列表。
    • 对于 touchend 事件,它是从表面移除的触摸点的列表(即,对应于不再触摸表面的手指的触摸点集)。

这些接口共同定义了一套相对底层的特性,但它们支持多种基于触摸的交互,包括熟悉的诸如多指滑动、旋转、捏合和缩放的多点触摸手势。

从接口到手势

应用程序在定义手势语义时可能会考虑不同的因素。例如,触摸点从起始位置到结束位置的移动距离。另一个潜在的因素是时间;例如,触摸开始和触摸结束之间经过的时间,或者旨在创建双击手势的两次连续点击之间的时间间隔。滑动的方向(例如从左到右,从右到左等)是另一个需要考虑的因素。

应用程序使用的触摸列表取决于应用程序手势的语义。例如,如果应用程序支持在单个元素上进行单点触摸(点击),它将在 touchstart 事件处理程序中使用 targetTouches 列表来以应用程序特定的方式处理触摸点。如果应用程序支持任意两个触摸点的双指滑动,它将在 touchmove 事件处理程序中使用 changedTouches 列表来确定是否有两个触摸点已移动,然后以应用程序特定的方式实现该手势的语义。

当只有一个活动的触摸点时,浏览器通常会分派模拟的鼠标和点击事件。涉及两个或更多活动触摸点的多点触摸交互通常只会生成触摸事件。要防止发送模拟的鼠标事件,请在触摸事件处理程序中使用 preventDefault() 方法。如果您想同时与鼠标和触摸进行交互,请改用 指针事件

基本步骤

本节包含使用上述接口的基本用法。有关更详细的示例,请参阅 触摸事件概述

为每种触摸事件类型注册事件处理程序。

js
// Register touch event handlers
someElement.addEventListener("touchstart", process_touchstart);
someElement.addEventListener("touchmove", process_touchmove);
someElement.addEventListener("touchcancel", process_touchcancel);
someElement.addEventListener("touchend", process_touchend);

在事件处理程序中处理事件,实现应用程序的手势语义。

js
// touchstart handler
function process_touchstart(ev) {
  // Use the event's data to call out to the appropriate gesture handlers
  switch (ev.touches.length) {
    case 1:
      handle_one_touch(ev);
      break;
    case 2:
      handle_two_touches(ev);
      break;
    case 3:
      handle_three_touches(ev);
      break;
    default:
      gesture_not_supported(ev);
      break;
  }
}

访问触摸点的属性。

js
// Create touchstart handler
someElement.addEventListener("touchstart", (ev) => {
  // Iterate through the touch points that were activated
  // for this element and process each event 'target'
  for (const touch of ev.targetTouches) {
    process_target(touch.target);
  }
});

阻止浏览器处理模拟的鼠标事件

js
// touchmove handler
function process_touchmove(ev) {
  // Set call preventDefault()
  ev.preventDefault();
}

最佳实践

以下是使用触摸事件时需要考虑的一些最佳实践

  • 尽量减少在触摸处理程序中完成的工作量。
  • 将触摸点处理程序添加到特定的目标元素(而不是整个文档或文档树中更高的节点)。
  • touchstart 中添加 touchmovetouchendtouchcancel 事件处理程序。
  • 目标触摸元素或节点应足够大,以便容纳手指触摸。如果目标区域太小,触摸它可能会导致相邻元素触发其他事件。

实现和部署状态

触摸事件浏览器兼容性数据表明,移动浏览器对触摸事件的支持相对广泛,而桌面浏览器的支持则滞后,尽管正在进行其他实现。

关于触摸点的 触摸区域(用户与触摸表面之间的接触区域)的一些新功能正在标准化过程中。新功能包括最能概括触摸点与触摸表面接触区域的椭圆的XY半径。触摸点的旋转角度(描述椭圆以使其与接触区域对齐所需的旋转度数)以及施加到触摸点的压力量也正在标准化。

指针事件呢?

新输入机制的引入增加了处理各种输入事件(如按键事件、鼠标事件、笔/触控笔事件和触摸事件)的应用程序的复杂性。为了帮助解决这个问题,指针事件 API 定义了用于处理来自鼠标、笔、触摸屏等设备的硬件无关指针输入的事件和相关接口。也就是说,抽象的指针创建了一个统一的输入模型,可以表示手指、笔/触控笔或鼠标的接触点。

指针事件模型可以简化应用程序的输入处理,因为指针代表来自任何输入设备的输入。此外,指针事件类型与鼠标事件类型(例如 pointerdownpointerup)非常相似,因此处理指针事件的代码与鼠标处理代码非常接近。

指针事件在浏览器中的实现状态相对较高,Chrome、Firefox、IE11 和 Edge 具有完整的实现。

另见