この章では、マウスイベントとそのプロパティの詳細を説明します。
注意: マウスイベント は “マウスデバイス” だけではなく、スマートフォンやタブレットなど互換性のためにエミュレートされた他のデバイスから来ることもあります。
マウスイベントの種類
ここまでで、既にいくつかのイベントは見てきました:
mousedown/mouseup
- 要素上でマウスボタンがクリックされた/離されました。
mouseover/mouseout
- マウスポイントが要素に来る/出ていきました。
mousemove
- 要素上でのマウス移動毎にこのイベントが発生します。
click
mousedown
の後に発生し、マウスの左ボタンを使われた場合は同じ要素にmouseup
が発生します。dblclick
- 短時間の間に同じ要素で2回クリックされた後に発生します。最近はめったに使われません。
contextmenu
- マウスの右ボタンが使われた場合に発生します。が、コンテキストメニューを開く方法は他にもあります。例 特別なキーボードのキーを使用する場合です。この場合でもイベントが発生するので、正確にはマウスイベントではありません。
…他にもいくつかイベントがあります。後ほど説明します。
イベント順
上の一覧を見てわかるように、ユーザアクションは複数のイベントを発生させることがあります。
例えば、左ボタンのクリックは最初に mousedown
を発生させ、ボタンが押された後、それが離されたときに mouseup
と click
が発生します。
1つのアクションが複数イベントを発生させる場合、順序は決まっています。つまり、ハンドラは mousedown
→ mouseup
→ click
の順番で呼び出されます。
下のボタンをクリックし、イベントを見てみてください。ダブルクリックも試してみてください。
下のテストスタンドでは、すべてのマウスイベントが記録され、イベント間で1秒以上の時間がある場合には水平ルーラーで区切っています。
また、マウスのボタンを検出するための button
プロパティが見えますが、これについては後述します。
マウスボタン
クリック関連のイベントには常に button
プロパティがあり、正確なマウスボタンが取得できます。
通常、click
や contextmenu
では使いません。なぜなら前者は左クリックのときだけ、後者は – 右クリックのときにだけ起こるからです。
一方、mousedown
と mouseup
ハンドラが event.button
を必要とする場合があります。これらのイベントはどちらのボタンでも発生するためです。このとき、button
で “右マウスダウン” と “左マウスダウン” が区別できます。
event.button
がとり得る値は以下です:
ボタン状態 | event.button |
---|---|
左ボタン (主) | 0 |
中央ボタン (補助) | 1 |
右ボタン (副) | 2 |
X1 ボタン (戻る) | 3 |
X2 ボタン (進む) | 4 |
ほとんどのマウスデバイスは、左右の2つのボタンのみなので、取り得る値は 0
か 2
です。タッチデバイスもタップ時に同様のイベントを生成します。
また、event.buttons
というプロパティもあり、これは現在押されているすべてのボタンを整数値として持っています。実際にはこのプロパティはほとんど使われませんが、MDN で詳細が確認できます。
event.which
は非推奨です古いコードでは event.which
プロパティが使われていることがあります。これは、ボタンを取得する古い非標準の方法で、以下の値が取られます:
event.which == 1
– 左ボタンevent.which == 2
– 中央ボタンevent.which == 3
– 右ボタン
現時点では、event.which
は推奨されていないので使用しないでください。
修飾子: shift, alt, ctrl と meta
すべてのマウスイベントは押された修飾子のキーに関する情報も含みます。
イベントプロパティ:
shiftKey
: ShiftaltKey
: Alt (or Mac は Opt)ctrlKey
: CtrlmetaKey
: Mac は Cmd
イベント時に対応するキーが押されていた場合 true
になります。
例えば、下のボタンは Alt+Shift + クリック でのみ動作します:
<button id="button">Alt+Shift+Click on me!</button>
<script>
button.onclick = function(event) {
if (event.altKey && event.shiftKey) {
alert('Hooray!');
}
};
</script>
Ctrl
ではなく Cmd
ですWindows と Linux には、Alt, Shift と Ctrl の修飾子があります。Mac ではもう一つあります: Cmd、これはプロパティ metaKey
に相当します。
多くのアプリケーションでは、Windows/Linux が Ctrl を使う時、Mac では Cmd を使います。
つまり: Windows ユーザが Ctrl+Enter あるいは Ctrl+A を押すとき、Mac ユーザは Cmd+Enter あるいは Cmd+A となります。
したがって、Ctrl + クリック のような組み合わせをサポートしたいとき、Mac では Cmd + クリック とするのが理にかなっています。それがMacユーザにとってより快適です。
たとえ Mac ユーザに Ctrl + クリックを強制したいとしても、それは難しいです。問題は Ctrl で左クリックすると、Mac では 右クリック と解釈され、Windows/Linux のように click
ではなく contextmenu
イベントが生成されるからです。
なので、すべての OS の人々に快適に感じてもらうためには、ctrlKey
と一緒に metaKey
を使うべきです。
JS-codeの場合、if (event.ctrlKey || event.metaKey)
というチェックを意味します。
キーボードの組み合わせは便利です。利用者がキーボードを使う場合は、それを使えるようにします。
ですが、モバイルデバイスのように、デバイスにキーボードがない場合は、修飾キーがなくても動作するようにする必要があります。
座標: clientX/Y, pageX/Y
すべてのマウスイベントは2種類の座標を持っています:
- ウィンドウに相対:
clientX
とclientY
. - ドキュメントに相対:
pageX
とpageY
.
座標 の章で、これらの違いについては既に説明しました。
簡単に言うと、ドキュメント相対座標 pageX/Y
はドキュメントの左上の端から数えた数値で、ページがスクールしても変わりません。一方、clientX/Y
は現在のウィンドウの左上の端からになります。そのため、ページがスクロールされると値は変わります。
例えば、 500x500 サイズのウィンドウがあり、マウスが左上端にあるとき、clientX
と clientY
はページがスクロールされているかに関係なく 0
です。
そして、マウスが中央にある場合、ドキュメント内のどの場所にあっても、clientX
と clientY
は 250
です。それらは position:fixed
に似ています。
入力フィールドにマウスを移動し clientX/clientY
を見てみてください (例は iframe
の中にあるので、座標は iframe
への相対です):
<input onmousemove="this.value=event.clientX+':'+event.clientY" value="Mouse over me">
マウスダウンでの選択を防ぐ
マウスのダブルクリックは、インターフェースによってはじゃまになる副作業があります。
例えば、下のテキストをダブルクリックすると、ハンドラに加えてそのテキストを選択します:
<b ondblclick="alert('dblclick')">Double-click me</b>
左のマウスボタンを押した後、離さずにマウスを動かすとそれも選択範囲になりますが、この動作はしばしば望まれないことがあります。
選択を防ぐ方法はいくつかあり、選択(Selection) と 範囲(Range) の章を読んでください。
この特定のケースで、最も理にかなった方法はブラウザの mousedown
のアクションを無効にすることです。これで、これらの選択を防ぐことができます:
Before...
<b ondblclick="alert('Click!')" onmousedown="return false">
Double-click me
</b>
...After
これで太字部分の要素はダブルクリックで選択されません。また左ボタンを押しても選択は開始されません。
補足: 内側のテキストは依然として選択可能です。ですが、選択はそのテキスト自身ではなく、その前後から始める必要があります。通常ユーザにとってこれは問題になりません。
ページのコンテンツをコピーペーストから守るために選択を無効にしたい場合は、別のイベントが利用できます: oncopy
<div oncopy="alert('Copying forbidden!');return false">
Dear user,
The copying is forbidden for you.
If you know JS or HTML, then you can get everything from the page source though.
</div>
<div>
のテキストの一部をコピーしようとしても動作しません。なぜならデフォルトアクション oncopy
が防止されているためです。
確かに、ユーザーがページのHTMLソースを開き、そこからコンテツを取ることを止めることはできません。が、誰もがHTMLソースを開く方法を知っているわけではありません。
サマリ
マウスイベントには次のプロパティがあります:
-
ボタン:
button
. -
修飾子 (押された場合
true
):altKey
,ctrlKey
,shiftKey
とmetaKey
(Mac).- Ctrl を扱いたい場合に Mac ユーザを忘れてはいけません、Mac では Cmd を使うので、
if (e.metaKey || e.ctrlKey)
とチェックするのが良いです。
- Ctrl を扱いたい場合に Mac ユーザを忘れてはいけません、Mac では Cmd を使うので、
-
ウィンドウ相対座標:
clientX/clientY
. -
ドキュメント相対座標:
pageX/clientX
.
mousedown
のブラウザのデフォルトアクションはテキストの選択ですが、インターフェースにとってそれが良くない場合には選択を止めるべきです。
次の章では、ポインタの動きに関するイベントと、ポインタの下の要素の変化を追跡する方法についてより詳しく見ていきます。
コメント
<code>
タグを使ってください。複数行の場合は<pre>
を、10行を超える場合にはサンドボックスを使ってください(plnkr, JSBin, codepen…)。