--- title: Pointer events slug: Web/API/Pointer_events tags: - API - Landing - Overview - Pointer Events translation_of: Web/API/Pointer_events ---
{{DefaultAPISidebar("Pointer Events")}}
今日のウェブコンテンツの多くは、ユーザーのポインティングデバイスがマウスであることを前提としています。 しかしながら、多くのデバイスがペン/スタイラスおよびタッチ面のような他のタイプのポインティング入力デバイスをサポートしているので、既存のポインティングデバイスのイベントモデルへの拡張が必要であり、そしてポインタイベントはその必要性に対処します。
ポインタイベントは、ポインティングデバイスに対して発生する DOM イベントです。 これらは、マウス、ペン/スタイラス、(1本以上の指でなどの)タッチなどのポインティング入力デバイスを処理する単一の DOM イベントモデルを作成するように設計されています。 ポインタは、特定の画面座標セットをターゲットにできるハードウェアにとらわれないデバイスです。 ポインタに単一のイベントモデルを使用すると、ウェブサイトやウェブアプリの作成が簡単になり、ユーザーのハードウェアに関係なく優れたユーザーエクスペリエンスを提供できます。 しかしながら、デバイス固有の処理が必要なシナリオのために、ポインタイベントはイベントを生成したデバイスタイプを調べるための {{domxref("PointerEvent.pointerType","pointerType")}} プロパティを定義しています。
一般的なポインタ入力を処理するために必要なイベントは、{{domxref("MouseEvent","マウスイベント")}}に似ています(mousedown/pointerdown
、mousemove/pointermove
など)。 したがって、ポインタイベントタイプは意図的にマウスイベントタイプと似せています。 さらに、ポインタイベントには、マウスイベントに存在する通常のプロパティ(クライアント座標、ターゲット要素、ボタンの状態など)、およびその他の入力形式のための新しいプロパティ(圧力、接触ジオメトリ、傾きなど)が含まれています。 実際、{{domxref("PointerEvent")}} インターフェイスはすべての {{domxref("MouseEvent")}} のプロパティを継承するため、マウスイベントからポインタイベントへのコンテンツの移行が容易になります。
buttons
プロパティに対してゼロ以外の値を持つ場合の条件。 例えば、ペンの場合は、ペンがデジタイザと物理的に接触しているか、ホバー中に少なくとも1つのボタンが押されているときです。主なインターフェイスは、{{domxref("PointerEvent.PointerEvent","コンストラクタ")}}といくつかのイベントタイプおよび関連するグローバルイベントハンドラを持つ {{domxref("PointerEvent")}} インターフェイスです。 この標準には、{{domxref("Element")}} インターフェイスと {{domxref("Navigator")}} インターフェイスの拡張も含まれています。 以下のサブセクションでは、各インターフェイスとプロパティについて簡単に説明します。
{{domxref("PointerEvent")}} インターフェイスは、{{domxref("MouseEvent")}} インターフェイスを拡張したもので、次のプロパティがあります(それらはすべて{{readonlyInline}}です)。
ポインタイベントには10のイベントタイプがあり、そのうち7つはマウスイベントと同等の意味を持ちます(ダウン(down
)、アップ(up
)、移動(move
)、オーバー(over
)、アウト(out
)、進入(enter
)、離脱(leave
))。 以下は、各イベントタイプとそれに関連する{{domxref("GlobalEventHandlers","グローバルイベントハンドラ")}}の簡単な説明です。
イベント | イベントハンドラ | 説明 |
---|---|---|
{{event('pointerover')}} | {{domxref('GlobalEventHandlers.onpointerover','onpointerover')}} | ポインタが要素のヒットテスト境界内に移動したときに発生します。 |
{{event('pointerenter')}} | {{domxref('GlobalEventHandlers.onpointerenter','onpointerenter')}} | ポインタが要素またはその子孫の1つのヒットテスト境界内に移動したときに発生します。 これには、ホバーをサポートしていないデバイスからの pointerdown イベントの結果も含まれます(pointerdown を参照)。 |
{{event('pointerdown')}} | {{domxref('GlobalEventHandlers.onpointerdown','onpointerdown')}} | ポインタがアクティブボタン状態になったときに発生します。 |
{{event('pointermove')}} | {{domxref('GlobalEventHandlers.onpointermove','onpointermove')}} | ポインタが座標を変更したときに発生します。 また、ポインタの状態の変化がこれ以外のイベントで報告できない場合もこのイベントが使われます。 |
{{event('pointerup')}} | {{domxref('GlobalEventHandlers.onpointerup','onpointerup')}} | ポインタがアクティブボタン状態でなくなったときに発生します。 |
{{event('pointercancel')}} | {{domxref('GlobalEventHandlers.onpointercancel','onpointercancel')}} | ブラウザーは、ポインタがイベントを生成できなくなったと判断した場合(例えば、関連デバイスが無効になった場合)、このイベントを発生させます。 |
{{event('pointerout')}} | {{domxref('GlobalEventHandlers.onpointerout','onpointerout')}} | 次のようないくつかの理由で発生します。 ポインタが要素のヒットテスト境界外に移動した。 ホバーをサポートしていないデバイスの pointerup イベントが発生した(pointerup を参照)。 pointercancel イベントの発生後(pointercancel を参照)。 ペン/スタイラスがデジタイザで検出可能なホバー範囲を離脱したとき。 |
{{event('pointerleave')}} | {{domxref('GlobalEventHandlers.onpointerleave','onpointerleave')}} | ポインタが要素のヒットテスト境界外に移動したときに発生します。 ペンデバイスの場合、このイベントは、スタイラスがデジタイザで検出可能なホバー範囲を離脱したときに発生します。 |
{{event('gotpointercapture')}} | {{domxref('GlobalEventHandlers.ongotpointercapture','ongotpointercapture')}} | 要素がポインタキャプチャを受け取ったときに発生します。 |
{{event('lostpointercapture')}} | {{domxref('GlobalEventHandlers.onlostpointercapture','onlostpointercapture')}} | ポインタに対するポインタキャプチャが解放された後に発生します。 |
{{domxref("Element")}} インターフェイスには次の3つの拡張機能があります。
{{domxref("Navigator.maxTouchPoints")}} プロパティは、任意の時点でサポートしている同時タッチポイントの最大数を決定するために使用します。
このセクションでは、ポインタイベントのインターフェイスを使用した基本的な使い方の例を紹介します。
この例では、特定の要素のすべてのイベントタイプに対してハンドラを登録します。
<html> <script> function over_handler(event) { } function enter_handler(event) { } function down_handler(event) { } function move_handler(event) { } function up_handler(event) { } function cancel_handler(event) { } function out_handler(event) { } function leave_handler(event) { } function gotcapture_handler(event) { } function lostcapture_handler(event) { } function init() { var el=document.getElementById("target"); // ポインタイベントハンドラの登録 el.onpointerover = over_handler; el.onpointerenter = enter_handler; el.onpointerdown = down_handler; el.onpointermove = move_handler; el.onpointerup = up_handler; el.onpointercancel = cancel_handler; el.onpointerout = out_handler; el.onpointerleave = leave_handler; el.gotpointercapture = gotcapture_handler; el.lostpointercapture = lostcapture_handler; } </script> <body onload="init();"> <div id="target"> Touch me ... </div> </body> </html>
この例では、タッチイベントのすべてのプロパティにアクセスする方法を示します。
<html> <script> var id = -1; function process_id(event) { // イベントの識別子に基づいて、このイベントを処理する } function process_mouse(event) { // マウスポインタイベントを処理する } function process_pen(event) { // ペンポインタイベントを処理する } function process_touch(event) { // タッチポインタイベントを処理する } function process_tilt(tiltX, tiltY) { // 傾斜データハンドラ } function process_pressure(pressure) { // 圧力ハンドラ } function process_non_primary(event) { // 非プライマリハンドラ } function down_handler(ev) { // タッチポイントの接触面積を計算する var area = ev.width * ev.height; // キャッシュされた id とこのイベントの id を比較し、それに応じて処理する if (id == ev.identifier) process_id(ev); // 適切なポインタタイプのハンドラを呼び出す switch (ev.pointerType) { case "mouse": process_mouse(ev); break; case "pen": process_pen(ev); break; case "touch": process_touch(ev); break; default: console.log("pointerType " + ev.pointerType + " はサポートしていません"); } // 傾斜ハンドラを呼び出す if (ev.tiltX != 0 && ev.tiltY != 0) process_tilt(ev.tiltX, ev.tiltY); // 圧力ハンドラを呼び出す process_pressure(ev.pressure); // このイベントがプライマリではない場合は、非プライマリハンドラを呼び出す if (!ev.isPrimary) process_non_primary(ev); } function init() { var el=document.getElementById("target"); // pointerdown ハンドラの登録 el.onpointerdown = down_handler; } </script> <body onload="init();"> <div id="target"> Touch me ... </div> </body> </html>
シナリオによっては、複数のポインタ(例えば、タッチ画面とマウスの両方を備えたデバイス)やポインタが複数の接触点をサポートする(例えば、複数の指でのタッチをサポートするタッチ画面)ことがあります。 アプリは、{{domxref("PointerEvent.isPrimary","isPrimary")}} プロパティを使用して、各ポインタタイプのアクティブポインタのセットの中からマスターポインタを識別できます。 アプリがプライマリポインタのみをサポートしたい場合は、プライマリではないすべてのポインタイベントを無視できます。
マウスの場合、ポインタは1つだけなので、常にプライマリポインタになります。 タッチ入力の場合、他にアクティブなタッチがなかったときにユーザーが画面にタッチした場合、ポインタはプライマリと見なされます。 ペンとスタイラスの入力では、他のアクティブなペンが画面に接触していないときにユーザーのペンが最初に画面に接触した場合、ポインタはプライマリと見なされます。
マウスやペンなどの一部のポインタデバイスは複数のボタンをサポートしており、ボタンの押下で和音を弾くことができます。 すなわち、ポインタデバイス上の別のボタンが既に押されている間に、追加のボタンを押すことができます。 ボタンが押された状態を判断するために、ポインタイベントは({{domxref("PointerEvent")}} の継承元の){{domxref("MouseEvent")}} インターフェイスの {{domxref("MouseEvent.button","button")}} プロパティおよび {{domxref("MouseEvent.buttons","buttons")}} プロパティを使用します。 次の表は、さまざまなデバイスボタンの状態に対応する button
および buttons
の値を示しています。
デバイスボタンの状態 | button | buttons |
---|---|---|
最後のイベント以降、ボタンもタッチ/ペンの接触も変更されませんでした | -1 | — |
ボタンを押さずにマウスを動かした、ボタンを押さずにホバー中にペンを動かした | — | 0 |
左マウス、タッチ接触、ペン接触 | 0 | 1 |
中マウス | 1 | 4 |
右マウス、ペンのバレルボタン | 2 | 2 |
X1(戻る)マウス | 3 | 8 |
X2(進む)マウス | 4 | 16 |
ペンの消しゴムボタン | 5 | 32 |
button
プロパティは、ボタンの状態の変化を示していることに注意してください。 ただし、タッチの場合のように、1つのイベントに伴って複数のイベントが発生する場合は、それらはすべて同じ値になります。
ポインタキャプチャでは、ポインタの位置での通常のヒットテストではなく、特定の{{domxref("PointerEvent","ポインタイベント")}}のイベントを特定の要素にターゲットしなおすことができます。 これは、ポインタデバイスの接触が要素から外れた場合でも、要素がポインタイベントを受信し続けるようにするために使用できます(例えば、スクロールで)。
次の例では、要素にポインタキャプチャを設定しています。
<html> <script> function downHandler(ev) { var el=document.getElementById("target"); // 要素 'target' はそれ以上のイベントを受信/キャプチャします el.setPointerCapture(ev.pointerId); } function init() { var el=document.getElementById("target"); el.onpointerdown = downHandler; } </script> <body onload="init();"> <div id="target"> Touch me ... </div> </body> </html>
次の例は、({{event("pointercancel")}} イベントが発生したときに)ポインタキャプチャを解放しています。 {{event("pointerup")}} イベントや {{event("pointercancel")}} イベントが発生すると、ブラウザーはこれを自動的に行います。
<html> <script> function downHandler(ev) { var el=document.getElementById("target"); // 要素 "target" はそれ以上のイベントを受信/キャプチャします el.setPointerCapture(ev.pointerId); } function cancelHandler(ev) { var el=document.getElementById("target"); // ポインタキャプチャを解放する el.releasePointerCapture(ev.pointerId); } function init() { var el=document.getElementById("target"); // pointerdown と pointercancel のハンドラの登録 el.onpointerdown = downHandler; el.onpointercancel = cancelHandler; } </script> <body onload="init();"> <div id="target"> Touch me ... </div> </body> </html>
{{cssxref("touch-action")}} CSS プロパティは、ブラウザーがデフォルトの(ネイティブな)タッチの振る舞い(ズームやパンなど)を領域に適用するかどうかを指定するために使用します。 このプロパティは、置換されていないインライン要素、テーブル行、行グループ、テーブル列、および列グループを除くすべての要素に適用できます。
auto
の値は、ブラウザーがそのデフォルトのタッチの振る舞いを(指定された領域に)自由に適用できることを意味し、none
の値はブラウザーのその領域に対するデフォルトのタッチの振る舞いを無効にします。 値 pan-x
および pan-y
は、指定された領域で始まるタッチがそれぞれ水平スクロールおよび垂直スクロール専用であることを意味します。 値 manipulation
は、ブラウザーがその要素から始まるタッチをスクロールとズームのみを考慮していることを意味します。
次の例では、ブラウザーのデフォルトのタッチの振る舞いは div
要素に対して無効になります。
<html> <body> <div style="touch-action:none;">Can't touch this ... </div> </body> </html>
次の例では、一部の button
要素ではデフォルトのタッチの振る舞いが無効になります。
button#tiny { touch-action: none; }
次の例では、target
要素にタッチすると、水平方向にのみパンします。
#target { touch-action: pan-x; }
ポインタイベントのインターフェイスを使用すると、アプリはポインタ対応デバイスで高度なユーザーエクスペリエンスを作成できますが、現実での今日のウェブコンテンツの大部分はマウス入力でのみ機能するように設計されています。 その結果、ブラウザーがポインタイベントをサポートしていても、マウスのみの入力が直接変更せずにそのまま機能することを前提として、ブラウザーはマウスイベントを処理する必要があります。 理想的には、ポインタ対応アプリはマウス入力を明示的に処理する必要はありません。 ただし、ブラウザーはマウスイベントを処理する必要があるため、対処する必要がある互換性の問題がいくつかあるかもしれません。 このセクションでは、ポインタイベントとマウスイベントの相互作用、およびアプリ開発者への影響について説明します。
ブラウザーは、マウスベースのコンテンツとの互換性のために、汎用ポインタ入力をマウスイベントにマッピングすることができます。 このイベントのマッピングは、互換性マウスイベントと呼ばれます。 作成者は pointerdown
イベントをキャンセルすることで特定の互換性マウスイベントの生成を防ぐことができますが、次の点に注意してください。
mouseover
、mouseout
、mouseenter
、mouseleave
の各イベントが防止されることはありません(ポインタがダウンしている場合でも)。ポインタイベントを使用する際に考慮すべき、いくつかのベストプラクティスは次のとおりです。
ポインタイベントのブラウザーの互換性のデータ(英語)は、デスクトップブラウザーとモバイルブラウザーの間のポインタイベントのサポートが、Safari を除くほぼすべてで利用可能であることを示しています。
Pointer Events Level 2 仕様の一部として、CSS の {{cssxref("touch-action")}} プロパティに新しい値が提案されていますが、現在これらの新しい値には実装サポートがありません。