前言
最近在了解webgl的一些东西, 突然看到一个第一人称的3d小游戏网站,游戏里可以锁定鼠标位置,使其不会移出浏览器,激发了我的学习欲望, 在我的知识储备里面不记得浏览器还有这个特性呀,今天来研究研究在浏览器里如何锁定鼠标位置
网站地址:
https://jblaha.art/sketchbook/0.4/ 一个第三人称的游乐场场景
去他Github看源码
经过不懈努力! 找到啦! Pointer Lock API
,
Experimental: 这是一个实验中的功能
此功能某些浏览器尚在开发中,请参考浏览器兼容性表格以得到在不同浏览器中适合使用的前缀。由于该功能对应的标准文档可能被重新修订,所以在未来版本的浏览器中该功能的语法和行为可能随之改变。
方法/属性
Pointer lock API, 和 Fullscreen API 类似,通过添加新方法来扩展 DOM 元素, requestPointerLock
, 目前还是厂商前缀。按下面这样来写:
element.webkitRequestPointerLock(); // Chrome
element.mozRequestPointerLock(); // Firefox
// 兼容写法
element.requestPointerLock = element.requestPointerLock ||
element.mozRequestPointerLock ||
element.webkitRequestPointerLock;
element.requestPointerLock();
目前MDN文档表示 requestPointerLock
的实现还是和 requestFullScreen
以及 Fullscreen API 紧紧地绑在一起的。一个元素在能够被指针锁定之前,必须首先进入全屏模式。(目前在chrome测试是不用进入全屏模式也可以锁定),锁定指针的过程是异步的,使用 (pointerlockchange
, pointerlockerror
) 事件来表明请求是成功还是失败了。这和 Fullscreen API
的工作方式是一致的,它使用 requestFullScreen
方法,以及 fullscreenchange
和 fullscreenerror
事件。
Pointer lock API 还扩展了 document 接口,添加了一个新的属性和一个新的方法。新的属性被用于访问当前被锁定的元素(如果有的话),并被命名为 pointerLockElement
,目前也使用厂商前缀。 document 添加的新方法是 exitPointerLock
,顾名思义,它是用来退出指针锁定的。
pointerlockchange 事件
当指针锁定状态改变时 - 例如,当调用 requestPointerLock
, exitPointerLock
,用户按下 ESC 键,等等
该事件目前在 Firefox 中使用前缀的格式是
mozpointerlockchange
,在 Chrome 中是webkitpointerlockchange
。
pointerlockerror 事件
当调用 requestPointerLock
或 exitPointerLock
而引发错误时, pointerlockerror
事件被分发到 document
对鼠标事件的扩展
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 代指前一个鼠标移动事件)
demo
截屏看着是有鼠标的 实际上在浏览器上看鼠标是消失了的 上代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#pointer-lock-element{
position: relative;
width: 500px;
height: 500px;
background-color: #fff;
}
#movable-block{
position: absolute;
left: 0;
top: 0;
width: 50px;
height: 50px;
background-color: hotpink;
}
</style>
</head>
<body>
<button onclick="lockPointer();">锁定鼠标</button>
<div id="pointer-lock-element">
<div id="movable-block"></div>
</div>
<script>
// 注意: 截止本文撰写时, 仅有 Mozilla 和 WebKit 支持指针锁定。
// 我们将要使之全屏并指针锁定的元素。
let elem;
let movableBlock = document.querySelector('#movable-block')
document.addEventListener("mousemove", function (e) {
var movementX = e.movementX ||
e.mozMovementX ||
e.webkitMovementX ||
0,
movementY = e.movementY ||
e.mozMovementY ||
e.webkitMovementY ||
0;
var left = parseInt(movableBlock.style.left || 0)
var top = parseInt(movableBlock.style.top || 0)
left += movementX
top += movementY
movableBlock.style.left = left + 'px'
movableBlock.style.top = top + 'px'
// 打印鼠标移动的增量值。
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();
// 直接启用鼠标锁定
// 当前测试Chrome版本 97.0.4672.2(正式版本)canary (x86_64)
// elem.requestPointerLock = elem.requestPointerLock ||
// elem.mozRequestPointerLock ||
// elem.webkitRequestPointerLock;
// elem.requestPointerLock();
}
</script>
</body>
</html>