event.movement 返回奇数
event.movement returning odd values
我一直在玩 webGL,我已经达到了可以制作图形非常可怜的小型三维游戏的地步(这更像是 concept/functionality 截至目前的证明)。对于三维体验,鼠标向任意方向无限移动无缝旋转第一人称视角是不错的选择。 Pointerlock 允许我锁定和隐藏光标位置,这非常有帮助,但我需要找到另一种跟踪鼠标移动的方法。在我的研究中,event.movementX
和 event.movementY
似乎是标准的,但我经常在鼠标移动的相反方向上出现大的移动点(通常在 500 到 583 之间)。我用许多鼠标和触控板对此进行了测试,并遇到了相同的现象。
这是我的相关事件监听器:
document.addEventListener("mousemove", function(event) {
xMovement += event.movementX;
yMovement += event.movementY;
console.log(event.movementX)
}, false);
document.addEventListener("pointerlockchange", function(event) {
if(pointerLockEnabled) pointerLockEnabled = false;
else pointerLockEnabled = true;
xMovement = 0; yMovement = 0;
} , false);
以及相关的渲染循环代码:
function render() {
if(pointerLockEnabled) {
camera.rotation.y = -xMovement / 1000;
camera.rotation.x = -yMovement / 1000;
if(rightKey && !leftKey) {
camera.position.x += 10 * Math.cos(camera.rotation.y);
camera.position.z -= 10 * Math.sin(camera.rotation.y);
}
else if(leftKey && !rightKey) {
camera.position.x -= 10 * Math.cos(camera.rotation.y);
camera.position.z += 10 * Math.sin(camera.rotation.y);
}
if(upKey&& !downKey) {
camera.position.z -= 10 * Math.cos(camera.rotation.y);
camera.position.x -= 10 * Math.sin(camera.rotation.y);
}
else if(downKey && !upKey) {
camera.position.z += 10 * Math.cos(camera.rotation.y);
camera.position.x += 10 * Math.sin(camera.rotation.y);
}
}
}
但是我的控制台出现了这样的情况:
我添加了更改 xMovement
的条件以防止摄像机角度大幅转动,但我仍然留下非常烦人的动作。有什么想法可以修补或替换为更无缝的界面移动吗?
如果您能以某种方式限制您的 mousemove 事件,这可能会有所帮助。例如 lodash throttle 版本:
function handleMouseMove(event) {
xMovement += event.movementX;
yMovement += event.movementY;
console.log(event.movementX)
}
var throttledHandleMouseMove = _.throttle(handleMouseMove, 75);
document.addEventListener("mousemove", throttledHandleMouseMove, false);
使用这种方法 handleMouseMove
不会每 75 毫秒执行超过 1 次。
我有同样的问题,但对我来说,错误的价值观总是与运动方向相同。我发现如果我用最后一个值替换任何超过 50 的值,我会得到非常好的准确性。唯一的问题是当错误值在 30-49 范围内时,但我不想取消这些值,以防用户实际移动鼠标的速度如此之快,或者他们的鼠标轮询率很差。一些趋势线比较可以平滑那些,但如果你不需要太精确,这很好:
const movement = {X: 0, Y: 0};
const lastMovement = {X: 0, Y: 0};
function onMouseMove(evt) {
if (checkPointerLock()) {
['X', 'Y'].forEach(axis => {
const checkValue = evt['movement' + axis] || evt['mozMovement' + axis]|| 0;
//ignore >=50. probably erroneous. smooth to last value
if (Math.abs(checkValue) < 50) {
lastMovement[axis] = checkValue;
}
movement[axis] = lastMovement[axis];
});
yaw += movement.X * -0.001 * data.sensitivityX;
pitch += movement.Y * (data.invertY ? .001 : -.001) * data.sensitivityY;
pitch = Math.max(-Math.PI/2, Math.min(Math.PI/2, pitch));
}
}
我知道我来晚了,但我对 OP 中提到的第一个问题有一个解释,并且对@KiranKota 提出的第二个问题有解决方法。
第一个问题实际上是 64 之前的 Chromium 版本中的一个错误。它一直处于休眠状态,直到 Windows 10 Fall Creator 的更新中发生了一些事情,最终暴露了它。即使您处于指针锁定状态,您的“光标”虽然不可见,但基本上会环绕到 window 的另一侧,从而导致相反方向的运动尖峰。
解决这个问题的方法是简单地忽略第一个向相反方向移动的鼠标移动事件;那就是如果您仍然关心支持 Chromium < 67。
第二个问题,尖峰向同一个方向移动,完全无关,并且仍然是 Chromium 94 的问题。这个问题与轮询率高的鼠标有关,许多游戏都是这种情况老鼠。通过我的实验,我发现 1000 的轮询率非常糟糕,500 更少,250 似乎可以使问题消失。我还发现尖峰与当前 window 的宽度一致。它们总是 window.innerWidth (or innerHeight) / ~2.3... ,再加上我只能假设是当前鼠标移动的“真实”距离。为什么是 2.3-ish...?我不知道。无论我是 运行 1000 还是 500 的比率,系数都是相同的。
我将对此进行更多试验,看看我能否可靠地过滤掉这些异常情况。与此同时,也许这些信息会有用。
我一直在玩 webGL,我已经达到了可以制作图形非常可怜的小型三维游戏的地步(这更像是 concept/functionality 截至目前的证明)。对于三维体验,鼠标向任意方向无限移动无缝旋转第一人称视角是不错的选择。 Pointerlock 允许我锁定和隐藏光标位置,这非常有帮助,但我需要找到另一种跟踪鼠标移动的方法。在我的研究中,event.movementX
和 event.movementY
似乎是标准的,但我经常在鼠标移动的相反方向上出现大的移动点(通常在 500 到 583 之间)。我用许多鼠标和触控板对此进行了测试,并遇到了相同的现象。
这是我的相关事件监听器:
document.addEventListener("mousemove", function(event) {
xMovement += event.movementX;
yMovement += event.movementY;
console.log(event.movementX)
}, false);
document.addEventListener("pointerlockchange", function(event) {
if(pointerLockEnabled) pointerLockEnabled = false;
else pointerLockEnabled = true;
xMovement = 0; yMovement = 0;
} , false);
以及相关的渲染循环代码:
function render() {
if(pointerLockEnabled) {
camera.rotation.y = -xMovement / 1000;
camera.rotation.x = -yMovement / 1000;
if(rightKey && !leftKey) {
camera.position.x += 10 * Math.cos(camera.rotation.y);
camera.position.z -= 10 * Math.sin(camera.rotation.y);
}
else if(leftKey && !rightKey) {
camera.position.x -= 10 * Math.cos(camera.rotation.y);
camera.position.z += 10 * Math.sin(camera.rotation.y);
}
if(upKey&& !downKey) {
camera.position.z -= 10 * Math.cos(camera.rotation.y);
camera.position.x -= 10 * Math.sin(camera.rotation.y);
}
else if(downKey && !upKey) {
camera.position.z += 10 * Math.cos(camera.rotation.y);
camera.position.x += 10 * Math.sin(camera.rotation.y);
}
}
}
但是我的控制台出现了这样的情况:
我添加了更改 xMovement
的条件以防止摄像机角度大幅转动,但我仍然留下非常烦人的动作。有什么想法可以修补或替换为更无缝的界面移动吗?
如果您能以某种方式限制您的 mousemove 事件,这可能会有所帮助。例如 lodash throttle 版本:
function handleMouseMove(event) {
xMovement += event.movementX;
yMovement += event.movementY;
console.log(event.movementX)
}
var throttledHandleMouseMove = _.throttle(handleMouseMove, 75);
document.addEventListener("mousemove", throttledHandleMouseMove, false);
使用这种方法 handleMouseMove
不会每 75 毫秒执行超过 1 次。
我有同样的问题,但对我来说,错误的价值观总是与运动方向相同。我发现如果我用最后一个值替换任何超过 50 的值,我会得到非常好的准确性。唯一的问题是当错误值在 30-49 范围内时,但我不想取消这些值,以防用户实际移动鼠标的速度如此之快,或者他们的鼠标轮询率很差。一些趋势线比较可以平滑那些,但如果你不需要太精确,这很好:
const movement = {X: 0, Y: 0};
const lastMovement = {X: 0, Y: 0};
function onMouseMove(evt) {
if (checkPointerLock()) {
['X', 'Y'].forEach(axis => {
const checkValue = evt['movement' + axis] || evt['mozMovement' + axis]|| 0;
//ignore >=50. probably erroneous. smooth to last value
if (Math.abs(checkValue) < 50) {
lastMovement[axis] = checkValue;
}
movement[axis] = lastMovement[axis];
});
yaw += movement.X * -0.001 * data.sensitivityX;
pitch += movement.Y * (data.invertY ? .001 : -.001) * data.sensitivityY;
pitch = Math.max(-Math.PI/2, Math.min(Math.PI/2, pitch));
}
}
我知道我来晚了,但我对 OP 中提到的第一个问题有一个解释,并且对@KiranKota 提出的第二个问题有解决方法。
第一个问题实际上是 64 之前的 Chromium 版本中的一个错误。它一直处于休眠状态,直到 Windows 10 Fall Creator 的更新中发生了一些事情,最终暴露了它。即使您处于指针锁定状态,您的“光标”虽然不可见,但基本上会环绕到 window 的另一侧,从而导致相反方向的运动尖峰。
解决这个问题的方法是简单地忽略第一个向相反方向移动的鼠标移动事件;那就是如果您仍然关心支持 Chromium < 67。
第二个问题,尖峰向同一个方向移动,完全无关,并且仍然是 Chromium 94 的问题。这个问题与轮询率高的鼠标有关,许多游戏都是这种情况老鼠。通过我的实验,我发现 1000 的轮询率非常糟糕,500 更少,250 似乎可以使问题消失。我还发现尖峰与当前 window 的宽度一致。它们总是 window.innerWidth (or innerHeight) / ~2.3... ,再加上我只能假设是当前鼠标移动的“真实”距离。为什么是 2.3-ish...?我不知道。无论我是 运行 1000 还是 500 的比率,系数都是相同的。
我将对此进行更多试验,看看我能否可靠地过滤掉这些异常情况。与此同时,也许这些信息会有用。