ウェブアプリで、ポインタ イベントをキャプチャするときにマウスの加速を無効にできるようになりました。
加速移動は、マウスやトラックパッドを使用して画面上でポインタを移動する場合に役立つ人間工学に基づく機能です。ゆっくり動かすことで正確な移動が可能になり、短い動きでポインタを画面全体に移動することもできます。具体的には、マウスを動かすのと同じ物理的な距離で、より速く移動した場合、画面上のポインタがさらに移動します。
オペレーティング システムでは、マウス アクセラレーションがデフォルトで有効になっています。一般的なファースト パーソン シューティング(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 のブラウザの互換性の表をご覧ください。
オペレーティング システムのサポート
ChromeOS、macOS Catalina 10.15.1、Windows では、OS レベルでのマウス アクセラレーションの調整を無効にできます。Linux は後日対応する予定です。
サンプル
Pointer Lock API を試すには、Glitch でサンプルを実行します。ソースコードをチェックアウトしてください。
関連情報
謝辞
この記事のレビューをしてくれた James Hollyer、Thomas Steiner、Joe Medley、Kayce Basques、Vincent Scheib に感謝します。