使用指针事件

本指南演示了如何使用指针事件和 HTML <canvas> 元素构建多点触控绘图应用程序。此示例基于 触控事件概述 中的示例,只是它使用了指针事件 输入事件模型。另一个区别是,由于指针事件与指针设备无关,因此应用程序使用相同的代码接受来自鼠标、笔或指尖的基于坐标的输入。

此应用程序仅在支持指针事件的浏览器中有效。

定义

表面

一个触控敏感的表面。这可能是触控板、触控屏,甚至是用户桌面表面(或鼠标垫)与物理屏幕的虚拟映射。

触控点

与表面的一个接触点。这可能是手指(或肘部、耳朵、鼻子,无论什么,但通常是手指)、触控笔、鼠标,或任何其他指定表面上的单个点的的方法。

示例

注意: 下面的文字在描述与表面的接触时使用“手指”一词,但这当然也可能是触控笔、鼠标或其他指向某个位置的方法。

绘图应用程序

HTML

HTML 由一个 <canvas> 元素组成。曲线将根据用户的触控手势绘制。还包括一个按钮来清除画布。

html
<canvas id="canvas" width="600" height="600">
  Your browser does not support the canvas element.
</canvas>
<button id="clear">Clear canvas</button>

CSS

touch-action 属性被设置为 none,以防止浏览器将默认的触控行为应用于应用程序。

css
#canvas {
  border: solid black 1px;
  touch-action: none;
  display: block;
}

JavaScript

我们将跟踪所有正在进行的触控,并为每个触控绘制线条。colors 用于区分不同的手指。

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

// Mapping from the pointerId to the current finger position
const ongoingTouches = new Map();
const colors = ["red", "green", "blue"];

handleStart 函数监听 pointerdown 事件,并在触控开始时绘制一个圆圈。

js
function handleStart(event) {
  const touch = {
    pageX: event.pageX,
    pageY: event.pageY,
    color: colors[ongoingTouches.size % colors.length],
  };
  ongoingTouches.set(event.pointerId, touch);

  ctx.beginPath();
  ctx.arc(touch.pageX, touch.pageY, 4, 0, 2 * Math.PI, false);
  ctx.fillStyle = touch.color;
  ctx.fill();
}

canvas.addEventListener("pointerdown", handleStart, false);

handleEnd 函数监听 pointerup 事件,并在触控结束时绘制一个正方形。

js
function handleEnd(event) {
  const touch = ongoingTouches.get(event.pointerId);

  if (!touch) {
    console.error(`End: Could not find touch ${event.pointerId}`);
    return;
  }

  ctx.lineWidth = 4;
  ctx.fillStyle = touch.color;
  ctx.beginPath();
  ctx.moveTo(touch.pageX, touch.pageY);
  ctx.lineTo(event.pageX, event.pageY);
  ctx.fillRect(event.pageX - 4, event.pageY - 4, 8, 8);
  ongoingTouches.delete(event.pointerId);
}

canvas.addEventListener("pointerup", handleEnd, false);

handleCancel 函数监听 pointercancel 事件,并停止跟踪触控。

js
function handleCancel(event) {
  const touch = ongoingTouches.get(event.pointerId);

  if (!touch) {
    console.error(`Cancel: Could not find touch ${event.pointerId}`);
    return;
  }

  ongoingTouches.delete(event.pointerId);
}

canvas.addEventListener("pointercancel", handleCancel, false);

handleMove 函数监听 pointermove 事件,并在触控的开始和结束之间绘制一条线。

js
function handleMove(event) {
  const touch = ongoingTouches.get(event.pointerId);

  // Event was not started
  if (!touch) {
    return;
  }

  ctx.beginPath();
  ctx.moveTo(touch.pageX, touch.pageY);
  ctx.lineTo(event.pageX, event.pageY);
  ctx.lineWidth = 4;
  ctx.strokeStyle = touch.color;
  ctx.stroke();

  const newTouch = {
    pageX: event.pageX,
    pageY: event.pageY,
    color: touch.color,
  };

  ongoingTouches.set(event.pointerId, newTouch);
}

canvas.addEventListener("pointermove", handleMove, false);

最后,添加清除功能。

js
document.getElementById("clear").addEventListener("click", () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
});

规范

规范
指针事件
# pointerevent-interface

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅