ウェブアプリで、ポインタ イベントをキャプチャするときにマウスの加速を無効にできるようになりました。
加速移動は、マウスやトラックパッドを使用して画面上でポインタを移動する場合に、人間工学に基づいた機能です。ゆっくり動かすことで正確な移動が可能になり、短い動きでポインタを画面全体に移動することもできます。具体的には、マウスを移動した物理的な距離が同じ場合、移動距離が短いほど、画面上のポインタの移動距離は長くなります。
オペレーティング システムでは、マウス アクセラレーションがデフォルトで有効になっています。一部のファースト パーソン ゲーム(主にファースト パーソン シューティング ゲーム(FPS))では、加速度調整なしでカメラの回転を制御するために、未加工のマウス入力データが使用されます。同じ物理的な動き(速い動きでも遅い動きでも)は、同じ回転になります。プロゲーマーによると、これによりゲーム エクスペリエンスが向上し、精度も高まります。
Chrome 88 以降、更新された Pointer Lock API により、ウェブアプリは加速されたマウス移動データと非加速されたマウス移動データの切り替えが可能になりました。
Google Stadia や Nvidia GeForce Now などのウェブベースのゲーム プラットフォームでは、すでにこれらの新機能を使用して FPS ゲーマーを満足させています。
API の使用
ポインタのロックのリクエスト
ポインタロックは、デスクトップ アプリケーションがポインタ アイコンを非表示にして、3D 世界を探索するなど、マウスの動きが別の何かとして解釈される場合の標準的な用語です。
mousemove
ドキュメント イベントの movementX
属性と movementY
属性は、前回の移動イベント以降にマウス ポインタが移動した距離を示します。ただし、ポインタがウェブページの外側に移動すると、それらは更新されません。
document.addEventListener("mousemove", (event) => {
console.log(`movementX: ${event.movementX} movementY: ${event.movementY}`);
});
マウス ポインタをキャプチャ(またはポインタ ロックをリクエスト)すると、ポインタが外部に移動する心配がなくなります。これは、没入型のウェブゲームで特に役立ちます。ポインタがロックされると、すべてのマウスイベントがポインタ ロックのターゲット要素に送信されます。
ターゲット要素で requestPointerLock()
を呼び出してポインタ ロックをリクエストし、pointerlockchange
イベントと pointerlockerror
イベントをリッスンしてポインタ ロックの変更をモニタリングします。
const myTargetElement = document.body;
// Call this function to request a pointer lock.
function requestPointerLock() {
myTargetElement.requestPointerLock();
}
document.addEventListener("pointerlockchange", () => {
if (document.pointerLockElement) {
console.log(`pointer is locked on ${document.pointerLockElement}`);
} else {
console.log("pointer is unlocked");
}
});
document.addEventListener("pointerlockerror", () => {
console.log("pointer lock error");
});
マウス アクセラレーションを無効にする
{ unadjustedMovement: true }
で requestPointerLock()
を呼び出して、マウス アクセラレーションの OS レベルの調整を無効にし、未加工のマウス入力にアクセスします。これにより、mousemove
イベントのマウス移動データには、ポインタがロックされているときのマウス加速度が含まれなくなります。
requestPointerLock()
から返された新しい Promise を使用して、リクエストが成功したかどうかを確認します。
function requestPointerLockWithUnadjustedMovement() {
const promise = myTargetElement.requestPointerLock({
unadjustedMovement: true,
});
if (!promise) {
console.log("disabling mouse acceleration is not supported");
return;
}
return promise
.then(() => console.log("pointer is locked"))
.catch((error) => {
if (error.name === "NotSupportedError") {
// Some platforms may not support unadjusted movement.
// You can request again a regular pointer lock.
return myTargetElement.requestPointerLock();
}
});
}
ポインタロックを解除せずに、加速されたマウス移動データと非加速されたマウス移動データの切り替えを行うことができます。目的のオプションを指定して、ポインタ ロックを再度リクエストします。そのリクエストが失敗した場合、元のロックはそのままで、返された Promise は拒否されます。変更リクエストが失敗した場合、ポインタ ロック イベントは発生しません。
ブラウザ サポート
Pointer Lock API は、さまざまなブラウザで十分にサポートされています。ただし、2020 年 10 月時点で、マウス アクセラレーションの OS レベルの調整を無効にできるのは、Chromium ベースのブラウザ(Chrome、Edge など)のみです。最新情報については、MDN のブラウザの互換性の表をご覧ください。
オペレーティング システムのサポート
マウス アクセラレーションの OS レベルの調整の無効化は、ChromeOS、macOS Catalina 10.15.1、Windows でサポートされています。Linux は後日対応する予定です。
サンプル
Glitch でサンプルを実行して、Pointer Lock API を試すことができます。ソースコードをチェックアウトしてください。
関連情報
謝辞
この記事のレビューをしてくれた James Hollyer、Thomas Steiner、Joe Medley、Kayce Basques、Vincent Scheib に感謝します。