在本章節中,我們將深入探討滑鼠事件及其屬性。
請注意:此類事件可能不僅來自「滑鼠裝置」,也來自其他裝置,例如手機和平板電腦,這些裝置會模擬這些事件以確保相容性。
滑鼠事件類型
我們已經看過其中一些事件
mousedown/mouseup
- 滑鼠按鈕在某個元素上按一下/放開。
mouseover/mouseout
- 滑鼠指標移到/移出某個元素。
mousemove
- 每個滑鼠移到元素上的動作都會觸發該事件。
click
- 在同一個元素上使用滑鼠左鍵後,觸發
mousedown
,然後觸發mouseup
。 dblclick
- 在短時間內,同一個元素上連續點擊兩次。現在很少使用。
contextmenu
- 按下滑鼠右鍵時觸發。還有其他開啟內容選單的方法,例如使用特殊鍵盤鍵,這種情況下也會觸發,所以它不完全是滑鼠事件。
…還有其他幾個事件,我們稍後會介紹。
事件順序
從上面的清單中可以看到,使用者的動作可能會觸發多個事件。
例如,左鍵點擊會先觸發mousedown
,當按鈕按下時,然後在釋放時觸發mouseup
和click
。
當一個動作啟動多個事件時,它們的順序是固定的。也就是說,處理程序會按mousedown
→ mouseup
→ click
的順序呼叫。
點擊下面的按鈕,你會看到這些事件。也可以嘗試雙擊。
在下面的測試台上,會記錄所有滑鼠事件,如果它們之間的延遲超過 1 秒,就會以水平線分隔。
此外,我們可以看到button
屬性,它允許我們偵測滑鼠按鈕;說明如下。
滑鼠按鈕
與點擊相關的事件總是會有button
屬性,它允許取得確切的滑鼠按鈕。
我們通常不會將它用於click
和contextmenu
事件,因為前者只會在左鍵點擊時發生,而後者只會在右鍵點擊時發生。
另一方面,mousedown
和mouseup
處理程序可能需要event.button
,因為這些事件會在任何按鈕上觸發,所以button
允許區分「右鍵按下」和「左鍵按下」。
event.button
可能的數值為
按鈕狀態 | event.button |
---|---|
左鍵(主鍵) | 0 |
中鍵(輔助鍵) | 1 |
右鍵(次要鍵) | 2 |
X1 按鈕(返回) | 3 |
X2 按鈕(前進) | 4 |
大多數滑鼠裝置只有左右鍵,所以可能的數值是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(或 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>
Cmd
取代 Ctrl
在 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+點擊,這也是很困難的。問題是:在 MacOS 上,使用 Ctrl 的左鍵點擊會被解釋為右鍵點擊,它會產生 contextmenu
事件,而不是像 Windows/Linux 一樣的 click
。
因此,如果我們希望所有作業系統的使用者都能感到舒適,那麼我們應該與 ctrlKey
一起檢查 metaKey
。
對於 JS 程式碼,這表示我們應該檢查 if (event.ctrlKey || event.metaKey)
。
鍵盤組合鍵作為工作流程的補充很好用。這樣,如果訪客使用鍵盤,它們就會運作。
但是,如果他們的裝置沒有鍵盤,那麼應該有辦法在沒有修飾鍵的情況下使用。
座標:clientX/Y、pageX/Y
所有滑鼠事件都提供兩種不同形式的座標
- 相對於視窗:
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">
防止在 mousedown 時選取
雙擊滑鼠會產生一個副作用,這可能會在某些介面中造成困擾:它會選取文字。
例如,雙擊以下文字會選取它,而且會額外執行我們的處理常式
<span ondblclick="alert('dblclick')">Double-click me</span>
如果按下滑鼠左鍵,而且不放開,然後移動滑鼠,這也會選取文字,而且通常是不需要的。
有多種方法可以防止選取,你可以在 選取和範圍 章節中閱讀。
在這個特定情況下,最合理的方法是在 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 原始碼,並從中取得內容,但並非所有人都知道如何這麼做。
摘要
滑鼠事件具有下列屬性
-
按鈕:
button
。 -
修改鍵(若按下則為
true
):altKey
、ctrlKey
、shiftKey
和metaKey
(Mac)。- 若要處理 Ctrl,請別忘了 Mac 使用者,他們通常使用 Cmd,因此最好檢查
if (e.metaKey || e.ctrlKey)
。
- 若要處理 Ctrl,請別忘了 Mac 使用者,他們通常使用 Cmd,因此最好檢查
-
相對於視窗的座標:
clientX/clientY
。 -
相對於文件座標:
pageX/pageY
。
mousedown
的瀏覽器預設動作為選取文字,若這對介面不好,則應加以避免。
在下一章節中,我們將看到更多關於追蹤指標移動的事件,以及如何追蹤其下的元素變更。
留言
<code>
標籤,對於多行程式碼,請將它們包覆在<pre>
標籤中,對於超過 10 行的程式碼,請使用沙盒 (plnkr、jsbin、codepen…)