【JavaScript】pointerdown / pointerup / pointermove – ポインターがアクティブになったときに発生するイベント

pointerdownpointeruppointermoveは、ポインタデバイス(マウス、タッチスクリーン、スタイラスなど)による操作を検知するためのイベントです。これらのイベントを利用することで、ドラッグ操作や描画、ジェスチャーの実装が可能になります。今回は、それぞれのイベントの特徴や使い方をまとめていきたいと思います。

ポインターイベントとは?

ポインターイベントは、複数の入力デバイス(マウス、タッチ、ペンなど)を統一的に扱うために導入されました。これにより、従来のmousedowntouchstartなどのイベントを個別に処理する必要がなくなり、コードがシンプルになります。

ポインターイベントの主な種類

  • pointerdown: ポインターデバイスがターゲットを押したときに発生します。
  • pointerup: ポインターデバイスがターゲットから離されたときに発生します。
  • pointermove: ポインターが動いたときに発生します。

基本的な使い方

ポインターイベントは、addEventListenerなどメソッドを使用します。

JavaScript
const element = document.getElementById('target');

element.addEventListener('pointerdown', (event) => {
  console.log('Pointer down detected', event);
});

element.addEventListener('pointerup', (event) => {
  console.log('Pointer up detected', event);
});

element.addEventListener('pointermove', (event) => {
  console.log('Pointer moved', event);
});

サンプルコード

以下の例では、pointerdownpointermovepointerupを使用してキャンバス上に線を描画します。

See the Pen pointerdown / pointerup / pointermove by tones (@tonescodedesign) on CodePen.

JavaScript
const canvas = document.getElementById('drawingCanvas');
const ctx = canvas.getContext('2d');
let isDrawing = false;

canvas.addEventListener('pointerdown', (event) => {
  isDrawing = true;
  ctx.beginPath();
  ctx.moveTo(event.offsetX, event.offsetY);
});

canvas.addEventListener('pointermove', (event) => {
  if (!isDrawing) return;
  ctx.lineTo(event.offsetX, event.offsetY);
  ctx.stroke();
});

canvas.addEventListener('pointerup', () => {
  isDrawing = false;
});

canvas.addEventListener('pointerleave', () => {
  isDrawing = false; // キャンバス外にポインタが移動した場合も描画を停止
});
HTML
<canvas id="drawingCanvas" width="500" height="400"></canvas>
CSS
canvas {
  border: 1px solid #ccc;
  cursor: crosshair;
}

このコードを使うと、マウスやタッチ操作でキャンバス上に線を描くことができます。pointerdownで描画を開始し、pointermoveで線を描き、pointerupで描画を終了します。

ドラッグアンドドロップの実装

次の例では、ポインターイベントを利用して簡単なドラッグアンドドロップを実装します。

See the Pen pointerdown / pointerup / pointermove by tones (@tonescodedesign) on CodePen.

JavaScript
const box = document.getElementById('draggableBox');
let isDragging = false;

box.addEventListener('pointerdown', (event) => {
  isDragging = true;
  box.setPointerCapture(event.pointerId);
  box.style.cursor = 'grabbing';
});

box.addEventListener('pointermove', (event) => {
  if (!isDragging) return;
  box.style.left = `${event.clientX - box.offsetWidth / 2}px`;
  box.style.top = `${event.clientY - box.offsetHeight / 2}px`;
});

box.addEventListener('pointerup', () => {
  isDragging = false;
  box.style.cursor = 'grab';
});
HTML
<div class="draggable" id="draggableBox"></div>
CSS
 .draggable {
  width: 100px;
  height: 100px;
  background-color: lightblue;
  border: 1px solid #000;
  position: absolute;
  cursor: grab;
}

このコードでは、pointerdownでドラッグを開始し、pointermoveで要素を移動し、pointerupでドラッグを終了します。

使用時の注意点

ポインタのキャプチャ

setPointerCaptureを使用することで、pointermoveイベントをその要素に限定できます。これにより、ドラッグ操作中にポインタが要素外に移動しても正しく動作します。

クロスブラウザ対応

ポインターイベントは多くのブラウザでサポートされていますが、古いブラウザや特殊な環境ではサポートされていない場合があります。pointerdownの代わりにmousedowntouchstartをフォールバックとして実装することを検討してください。

パフォーマンス

pointermoveイベントは非常に頻繁に発生するため、不要な処理を避けるよう心掛けてください。必要であれば、デバウンスやスロットリングを利用しましょう。