Pointer Lock

Pointer Lock API

指針鎖定(之前叫作 鼠標鎖定) 提供了一種輸入方法,這種方法是基於鼠標隨着時間推移的運動的(也就是說,deltas),而不只是鼠標光標的絕對位置。經過它能夠訪問原始的鼠標運動,把鼠標事件的目標鎖定到一個單獨的元素,這就消除了鼠標在一個單獨的方向上到底能夠移動多遠這方面的限制,並從視圖中刪去光標。html

這個 API 對於須要大量的鼠標輸入來控制運動,旋轉物體,以及更改項目的應用程序來講很是有用。對高度視覺化的應用程序尤爲重要,例如那些使用第一人稱視角的應用程序,以及 3D 視圖和建模。web

舉例來講,你能夠建立讓你的用戶簡單地經過移動鼠標而不須要點擊任何按鈕就能夠控制視角的應用。那麼這些按鈕就能夠被用做其餘動做。這類鼠標輸入對於查看地圖,衛星圖像,或者第一人稱場景(例如在一個遊戲中或者一個全景視頻中)是很是方便使用的。api

即便在光標移到瀏覽器或者屏幕區域以外,指針鎖定也可以讓你訪問鼠標事件。例如,你的用戶能夠經過不斷地移動鼠標來持續旋轉或操縱一個 3D 模型。若是沒有指針鎖定的話,這些旋轉或操縱會在指針到達瀏覽器或者屏幕邊緣的那一刻中止。尤爲是遊戲玩家將會由於此功能而興奮不已,由於他們能夠瘋狂地點擊按鈕,來回地滑動鼠標光標,而沒必要擔憂離開了遊戲區域,進而不當心誤點到另一個應用程序上,結果將鼠標焦點移離了遊戲。杯具了!瀏覽器

 

基本概念

指針鎖定和 鼠標捕獲有關。鼠標捕獲在一個鼠標被拖曳時能夠向一個目標元素持續傳遞有關事件,可是當鼠標按鈕被放開時就會中止。指針鎖定和鼠標捕獲在如下方面有所不一樣:異步

  • 它是持久性的。指針鎖定不釋放鼠標,直到做出一個顯式的 API 調用或是用戶使用一個專門的釋放手勢。
  • 它不侷限於瀏覽器或者屏幕邊界。
  • 它持續發送事件,而無論鼠標按鈕狀態如何。
  • 它隱藏光標。

示例

下面是一個如何在你的網頁中設置指針鎖定的示例。spa

<button onclick="lockPointer();">鎖住它!</button>
<div id="pointer-lock-element"></div>
<script>
// 注意: 截止本文撰寫時, 僅有 Mozilla 和 WebKit 支持指針鎖定。

// 咱們將要使之全屏並指針鎖定的元素。
var elem;

document.addEventListener("mousemove", function(e) {
  var movementX = e.movementX       ||
                  e.mozMovementX    ||
                  e.webkitMovementX ||
                  0,
      movementY = e.movementY       ||
                  e.mozMovementY    ||
                  e.webkitMovementY ||
                  0;

  // 打印鼠標移動的增量值。
  console.log("movementX=" + movementX, "movementY=" + movementY);
}, false);

function fullscreenChange() {
  if (document.webkitFullscreenElement === elem ||
      document.mozFullscreenElement === elem ||
      document.mozFullScreenElement === elem) { // 較舊的 API 大寫 'S'.
    // 元素進入全屏模式了,如今咱們能夠請求指針鎖定。
    elem.requestPointerLock = elem.requestPointerLock    ||
                              elem.mozRequestPointerLock ||
                              elem.webkitRequestPointerLock;
    elem.requestPointerLock();
  }
}

document.addEventListener('fullscreenchange', fullscreenChange, false);
document.addEventListener('mozfullscreenchange', fullscreenChange, false);
document.addEventListener('webkitfullscreenchange', fullscreenChange, false);

function pointerLockChange() {
  if (document.mozPointerLockElement === elem ||
      document.webkitPointerLockElement === elem) {
    console.log("指針鎖定成功了。");
  } else {
    console.log("指針鎖定已丟失。");
  }
}

document.addEventListener('pointerlockchange', pointerLockChange, false);
document.addEventListener('mozpointerlockchange', pointerLockChange, false);
document.addEventListener('webkitpointerlockchange', pointerLockChange, false);

function pointerLockError() {
  console.log("鎖定指針時出錯。");
}

document.addEventListener('pointerlockerror', pointerLockError, false);
document.addEventListener('mozpointerlockerror', pointerLockError, false);
document.addEventListener('webkitpointerlockerror', pointerLockError, false);

function lockPointer() {
  elem = document.getElementById("pointer-lock-element");
  // 開始於使元素進入全屏模式。目前的實現
  // 要求元素在請求指針鎖定前要處於全屏模式下
  // -- 這在之後可能會發生改變。
  elem.requestFullscreen = elem.requestFullscreen    ||
                           elem.mozRequestFullscreen ||
                           elem.mozRequestFullScreen || // 較舊的 API 把 ‘S’ 大寫
                           elem.webkitRequestFullscreen;
  elem.requestFullscreen();
}
</script>

方法/屬性 概述

Pointer lock API, 和 Fullscreen API 相似,經過添加新方法來擴展 DOM 元素, requestPointerLock, 目前仍是廠商前綴。按下面這樣來寫:指針

element.webkitRequestPointerLock(); // Chrome

element.mozRequestPointerLock(); // Firefox

目前 requestPointerLock 的實現仍是和 requestFullScreen 以及 Fullscreen API 牢牢地綁在一塊兒的。一個元素在可以被指針鎖定以前,必須首先進入全屏模式。就像上面演示的那樣,鎖定指針的過程是異步的,使用 (pointerlockchangepointerlockerror) 事件來代表請求是成功仍是失敗了。這和 Fullscreen API 的工做方式是一致的,它使用 requestFullScreen 方法,以及 fullscreenchange 和 fullscreenerror 事件。code

Pointer lock API 還擴展了 document 接口,添加了一個新的屬性和一個新的方法。新的屬性被用於訪問當前被鎖定的元素(若是有的話),並被命名爲 pointerLockElement,目前也使用廠商前綴。 document 添加的新方法是 exitPointerLock ,顧名思義,它是用來退出指針鎖定的。視頻

pointerLockElement 屬性適用於肯定當前是否有被指針鎖定的元素(例如,用來作一個布爾檢查),以及當有元素被鎖定時獲取該元素的一個引用。下面是這兩種用法的一個例子:htm

document.pointerLockElement = document.pointerLockElement    ||
                              document.mozPointerLockElement ||
                              document.webkitPointerLockElement;

// 1) 用於布爾檢查--咱們被指針鎖定了嗎?
if (!!document.pointerLockElement) {
  // 指針被鎖定
} else {
  // 指針未被鎖定
}

// 2) 用於訪問指針鎖定的元素
if (document.pointerLockElement === someElement) {
  // someElement 當前被指針鎖定
}

document 的 exitPointerLock 方法被用來退出指針鎖定,並且和 requestPointerLock 同樣,使用 pointerlockchange 和 pointerlockerror事件以異步方式工做:

document.exitPointerLock = document.exitPointerLock    ||
                           document.mozExitPointerLock ||
                           document.webkitExitPointerLock;

function pointerLockChange() {
  document.pointerLockElement = document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement; if (!!document.pointerLockElement) { console.log("目前仍是被鎖定。"); } else { console.log("已經退出鎖定。"); } } document.addEventListener('pointerlockchange', pointerLockChange, false); document.addEventListener('mozpointerlockchange', pointerLockChange, false); document.addEventListener('webkitpointerlockchange', pointerLockChange, false); // 試圖解除鎖定 document.exitPointerLock();

pointerlockchange 事件

當指針鎖定狀態改變時 – 例如,當調用 requestPointerLockexitPointerLock,用戶按下 ESC 鍵,等等。— pointerlockchange 事件被分發到document。 這是一個簡單事件因此不包含任何的額外數據。

該事件目前在 Firefox 中使用前綴的格式是  mozpointerlockchange ,在 Chrome 中是  webkitpointerlockchange

pointerlockerror 事件

當調用 requestPointerLock 或 exitPointerLock而引起錯誤時,  pointerlockerror 事件被分發到 document。這是一個簡單事件因此不包含任何的額外數據。

該事件目前在 Firefox 中被加上前綴爲  mozpointerlockerror ,在 Chrome 中爲  webkitpointerlockerror

鼠標事件擴展

Pointer lock API 使用 movement 屬性擴展了標準的 MouseEvent

partial interface MouseEvent {  readonly attribute long movementX;  readonly attribute long movementY; };
movement 屬性目前在 Firefox 中被加上前綴爲  .mozMovementX 和  .mozMovementY , 在 Chrome 中爲 .webkitMovementX 和  .webkitMovementY

鼠標事件的兩個新參數—movementX 和 movementY—提供了鼠標位置的變化狀況。這兩個參數的值,等於兩個MouseEvent 屬性(screenX 和 screenY)之間值的變化程度,這些 MouseEvent 屬性被存儲在兩個連續的鼠標移動事件( eNow 和 ePrevious)中。換言之,指針鎖定參數 movementX = eNow.screenX - ePrevious.screenX。(譯註:不存在名爲 eNow 或 ePrevious 的事件或屬性,eNow 代指當前的鼠標移動事件,ePrevious 代指前一個鼠標移動事件)

鎖定狀態

當指針鎖定被啓動以後,正常的 MouseEvent 屬性 clientXclientYscreenX, 和 screenY ,保持不變,就像鼠標沒有在移動同樣。movementX 和 movementY 屬性持續提供鼠標的位置變化。若是鼠標在一個方向上持續移動,movementX 和 movementY的值是沒有限制的。不存在鼠標光標的概念,並且光標沒法移到窗口以外,並且也不會被屏幕邊緣所固定。

未鎖定狀態

不管鼠標鎖定狀態是怎樣的, movementX 和 movementY 參數一直有效,而且爲了方便起見,甚至在未鎖定狀態也是有效的。

當鼠標被解除鎖定,系統光標能夠退出並從新進入瀏覽器窗口。若是發生這種狀況,movementX 和 movementY 可能會被設置成0。

iframe 的限制

指針鎖定一次只能鎖定一個 iframe。若是你鎖定了一個 iframe,你不能試圖鎖定另一個 iframe 而後把目標轉移到這個 iframe 上;指針鎖定將會出錯。爲了不這一問題,首先解鎖那個鎖定的 iframe,而後再鎖定另一個。

在 iframe 默認的狀況下, 「sandboxed」 iframes 會阻止指針鎖定。避免這種限制的能力,即以屬性/值 <iframe sandbox="allow-pointer-lock">組合的形式 , 有望很快在 Chrome 中出現。

譯自:https://developer.mozilla.org/en-US/docs/API/Pointer_Lock_API;原文地址:http://www.tfan.org/pointer-lock-api

轉自:http://www.tfan.org/pointer-lock-api/

相關文章
相關標籤/搜索