1. 程式人生 > >JavaScript 滑鼠點選事件的整合

JavaScript 滑鼠點選事件的整合

事件種類

滑鼠事件指與滑鼠相關的事件,主要有以下一些。

(1)click事件

click事件當用戶在Element節點、document節點、window物件上,單擊滑鼠(或者按下回車鍵)時觸發。

“滑鼠單擊”定義為,使用者在同一個位置完成一次mousedown動作和mouseup動作。它們的觸發順序是:mousedown首先觸發,mouseup接著觸發,click最後觸發。

下面是一個設定click事件監聽函式的例子。

div.addEventListener("click", function( event ) {
  // 顯示在該節點,滑鼠連續點選的次數
  event.target.innerHTML
= "click count: " + event.detail; }, false);

下面的程式碼是利用click事件進行CSRF攻擊(Cross-site request forgery)的一個例子。

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;"
>偽裝的連結</a>

(2)dblclick事件

dblclick事件當用戶在elementdocumentwindow物件上,雙擊滑鼠時觸發。該事件會在mousedownmouseupclick之後觸發。

(3)mouseup事件,mousedown事件

mouseup事件在釋放按下的滑鼠鍵時觸發。

mousedown事件在按下滑鼠鍵時觸發。

(4)mousemove事件

mousemove事件當滑鼠在一個節點內部移動時觸發。當滑鼠持續移動時,該事件會連續觸發。為了避免效能問題,建議對該事件的監聽函式做一些限定,比如限定一段時間內只能執行一次程式碼。

(5)mouseover事件,mouseenter事件

mouseover事件和mouseenter事件,都是滑鼠進入一個節點時觸發。

兩者的區別是,mouseenter事件只觸發一次,而只要滑鼠在節點內部移動,mouseover事件會在子節點上觸發多次。

// HTML程式碼為
// <ul id="test">
//   <li>item 1</li>
//   <li>item 2</li>
//   <li>item 3</li>
// </ul>

var test = document.getElementById('test');

// 進入test節點以後,該事件只會觸發一次
// event.target 是 ul 節點
test.addEventListener('mouseenter', function (event) {
  event.target.style.color = 'purple';
  setTimeout(function () {
    event.target.style.color = '';
  }, 500);
}, false);

// 進入test節點以後,只要在子Element節點上移動,該事件會觸發多次
// event.target 是 li 節點
test.addEventListener('mouseover', function (event) {
  event.target.style.color = 'orange';
  setTimeout(function () {
    event.target.style.color = '';
  }, 500);
}, false);

(6)mouseout事件,mouseleave事件

mouseout事件和mouseleave事件,都是滑鼠離開一個節點時觸發。

兩者的區別是,mouseout事件會冒泡,mouseleave事件不會。子節點的mouseout事件會冒泡到父節點,進而觸發父節點的mouseout事件。mouseleave事件就沒有這種效果,所以離開子節點時,不會觸發父節點的監聽函式。

(7)contextmenu

contextmenu事件在一個節點上點選滑鼠右鍵時觸發,或者按下“上下文選單”鍵時觸發。

MouseEvent物件

滑鼠事件使用MouseEvent物件表示,它繼承UIEvent物件和Event物件。瀏覽器提供一個MouseEvent建構函式,用於新建一個MouseEvent例項。

event = new MouseEvent(typeArg, mouseEventInit);

MouseEvent建構函式的第一個引數是事件名稱(可能的值包括click、mousedown、mouseup、mouseover、mousemove、mouseout),第二個引數是一個事件初始化物件。該物件可以配置以下屬性。

  • screenX,設定滑鼠相對於螢幕的水平座標(但不會移動滑鼠),預設為0,等同於MouseEvent.screenX屬性。
  • screenY,設定滑鼠相對於螢幕的垂直座標,預設為0,等同於MouseEvent.screenY屬性。
  • clientX,設定滑鼠相對於視窗的水平座標,預設為0,等同於MouseEvent.clientX屬性。
  • clientY,設定滑鼠相對於視窗的垂直座標,預設為0,等同於MouseEvent.clientY屬性。
  • ctrlKey,設定是否按下ctrl鍵,預設為false,等同於MouseEvent.ctrlKey屬性。
  • shiftKey,設定是否按下shift鍵,預設為false,等同於MouseEvent.shiftKey屬性。
  • altKey,設定是否按下alt鍵,預設為false,等同於MouseEvent.altKey屬性。
  • metaKey,設定是否按下meta鍵,預設為false,等同於MouseEvent.metaKey屬性。
  • button,設定按下了哪一個滑鼠按鍵,預設為0。-1表示沒有按鍵,0表示按下主鍵(通常是左鍵),1表示按下輔助鍵(通常是中間的鍵),2表示按下次要鍵(通常是右鍵)。
  • buttons,設定按下了滑鼠哪些鍵,是一個3個位元位的二進位制值,預設為0。1表示按下主鍵(通常是左鍵),2表示按下次要鍵(通常是右鍵),4表示按下輔助鍵(通常是中間的鍵)。
  • relatedTarget,設定一個Element節點,在mouseenter和mouseover事件時,表示滑鼠剛剛離開的那個Element節點,在mouseout和mouseleave事件時,表示滑鼠正在進入的那個Element節點。預設為null,等同於MouseEvent.relatedTarget屬性。

以下屬性也是可配置的,都繼承自UIEvent建構函式和Event建構函式。

  • bubbles,布林值,設定事件是否冒泡,預設為false,等同於Event.bubbles屬性。
  • cancelable,布林值,設定事件是否可取消,預設為false,等同於Event.cancelable屬性。
  • view,設定事件的檢視,一般是window或document.defaultView,等同於Event.view屬性。
  • detail,設定滑鼠點選的次數,等同於Event.detail屬性。

下面是一個例子。

function simulateClick() {
  var event = new MouseEvent('click', {
    'bubbles': true,
    'cancelable': true
  });
  var cb = document.getElementById('checkbox');
  cb.dispatchEvent(event);
}

上面程式碼生成一個滑鼠點選事件,並觸發該事件。

以下介紹MouseEvent例項的屬性。

altKey,ctrlKey,metaKey,shiftKey

以下屬性返回一個布林值,表示滑鼠事件發生時,是否按下某個鍵。

  • altKey屬性:alt鍵
  • ctrlKey屬性:key鍵
  • metaKey屬性:Meta鍵(Mac鍵盤是一個四瓣的小花,Windows鍵盤是Windows鍵)
  • shiftKey屬性:Shift鍵
// HTML程式碼為
// <body onclick="showkey(event);">

function showKey(e){
  console.log("ALT key pressed: " + e.altKey);
  console.log("CTRL key pressed: " + e.ctrlKey);
  console.log("META key pressed: " + e.metaKey);
  console.log("SHIFT key pressed: " + e.shiftKey);
}

上面程式碼中,點選網頁會輸出是否同時按下Alt鍵。

button,buttons

以下屬性返回事件的滑鼠鍵資訊。

(1)button

button屬性返回一個數值,表示按下了滑鼠哪個鍵。

  • -1:沒有按下鍵。
  • 0:按下主鍵(通常是左鍵)。
  • 1:按下輔助鍵(通常是中鍵或者滾輪鍵)。
  • 2:按下次鍵(通常是右鍵)。
// HTML程式碼為
// <button onmouseup="whichButton(event);">點選</button>

var whichButton = function (e) {
  switch (e.button) {
    case 0:
      console.log('Left button clicked.');
      break;
    case 1:
      console.log('Middle button clicked.');
      break;
    case 2:
      console.log('Right button clicked.');
      break;
    default:
      console.log('Unexpected code: ' + e.button);
  }
}

(2)buttons

buttons屬性返回一個3個位元位的值,表示同時按下了哪些鍵。它用來處理同時按下多個滑鼠鍵的情況。

  • 1:二進位制為001,表示按下左鍵。
  • 2:二進位制為010,表示按下右鍵。
  • 4:二進位制為100,表示按下中鍵或滾輪鍵。

同時按下多個鍵的時候,每個按下的鍵對應的位元位都會有值。比如,同時按下左鍵和右鍵,會返回3(二進位制為011)。

clientX,clientY,movementX,movementY,screenX,screenY

以下屬性與事件的位置相關。

(1)clientX,clientY

clientX屬性返回滑鼠位置相對於瀏覽器視窗左上角的水平座標,單位為畫素,與頁面是否橫向滾動無關。

clientY屬性返回滑鼠位置相對於瀏覽器視窗左上角的垂直座標,單位為畫素,與頁面是否縱向滾動無關。

// HTML程式碼為
// <body onmousedown="showCoords(event)">

function showCoords(evt){
  console.log(
    "clientX value: " + evt.clientX + "\n" +
    "clientY value: " + evt.clientY + "\n"
  );
}

(2)movementX,movementY

movementX屬性返回一個水平位移,單位為畫素,表示當前位置與上一個mousemove事件之間的水平距離。在數值上,等於currentEvent.movementX = currentEvent.screenX - previousEvent.screenX。

movementY屬性返回一個垂直位移,單位為畫素,表示當前位置與上一個mousemove事件之間的垂直距離。在數值上,等於currentEvent.movementY = currentEvent.screenY - previousEvent.screenY。

(3)screenX,screenY

screenX屬性返回滑鼠位置相對於螢幕左上角的水平座標,單位為畫素。

screenY屬性返回滑鼠位置相對於螢幕左上角的垂直座標,單位為畫素。

// HTML程式碼為
// <body onmousedown="showCoords(event)">

function showCoords(evt){
  console.log(
    "screenX value: " + evt.screenX + "\n"
    + "screenY value: " + evt.screenY + "\n"
  );
}

relatedTarget

relatedTarget屬性返回事件的次要相關節點。對於那些沒有次要相關節點的事件,該屬性返回null。

下表列出不同事件的target屬性和relatedTarget屬性含義。

事件名稱 target屬性 relatedTarget屬性
focusin 接受焦點的節點 喪失焦點的節點
focusout 喪失焦點的節點 接受焦點的節點
mouseenter 將要進入的節點 將要離開的節點
mouseleave 將要離開的節點 將要進入的節點
mouseout 將要離開的節點 將要進入的節點
mouseover 將要進入的節點 將要離開的節點
dragenter 將要進入的節點 將要離開的節點
dragexit 將要離開的節點 將要進入的節點

下面是一個例子。

// HTML程式碼為
// <div id="outer" style="height:50px;width:50px;border-width:1px solid black;">
//   <div id="inner" style="height:25px;width:25px;border:1px solid black;"></div>
// </div>

var inner = document.getElementById("inner");

inner.addEventListener("mouseover", function (){
  console.log('進入' + event.target.id + " 離開" + event.relatedTarget.id);
});
inner.addEventListener("mouseenter", function (){
  console.log('進入' + event.target.id + " 離開" + event.relatedTarget.id);
});
inner.addEventListener("mouseout", function (){
  console.log('離開' + event.target.id + " 進入" + event.relatedTarget.id);
});
inner.addEventListener("mouseleave", function (){
  console.log('離開' + event.target.id + " 進入" + event.relatedTarget.id);
});

// 滑鼠從outer進入inner,輸出
// 進入inner 離開outer
// 進入inner 離開outer

// 滑鼠從inner進入outer,輸出
// 離開inner 進入outer
// 離開inner 進入outer

wheel事件

wheel事件是與滑鼠滾輪相關的事件,目前只有一個wheel事件。使用者滾動滑鼠的滾輪,就觸發這個事件。

該事件除了繼承了MouseEvent、UIEvent、Event的屬性,還有幾個自己的屬性。

  • deltaX:返回一個數值,表示滾輪的水平滾動量。
  • deltaY:返回一個數值,表示滾輪的垂直滾動量。
  • deltaZ:返回一個數值,表示滾輪的Z軸滾動量。
  • deltaMode:返回一個數值,表示滾動的單位,適用於上面三個屬性。0表示畫素,1表示行,2表示頁。

瀏覽器提供一個WheelEvent建構函式,可以用來生成滾輪事件的例項。它接受兩個引數,第一個是事件名稱,第二個是配置物件。

var syntheticEvent = new WheelEvent("syntheticWheel", {"deltaX": 4, "deltaMode": 0});