当我使用Firefox时,画布调用requestPointerLock
,然后按F11键进行全屏显示-我看到事件mousemove
被触发。这使一些必须移动的东西必须是静态的,因为鼠标没有移动。
我尝试创建一个演示,但出现错误Blocked pointer lock on an element because the element's frame is sandboxed and the 'allow-pointer-lock' permission is not set.
这是一个至少可以阅读的代码示例。
HTML部分:
<canvas id="canvas" width="800" height="600"></canvas>
JavaScript部分:
canvas = document.getElementById('canvas');
document.addEventListener("click", function(e) {
canvas.requestPointerLock = canvas.requestPointerLock ||
canvas.mozRequestPointerLock ||
canvas.webkitRequestPointerLock;
if (canvas.requestPointerLock)
canvas.requestPointerLock();
}, false);
document.addEventListener("pointerlockchange", plChange, false);
document.addEventListener("mozpointerlockchange", plChange, false);
function plChange(e) {
var controlEnabled = (document.mozPointerLockElement === canvas ||
document.webkitPointerLockElement === canvas ||
document.pointerLockElement === canvas);
if (!controlEnabled) {
window.removeEventListener("mousemove", mouseMove);
} else {
window.addEventListener("mousemove", mouseMove, false);
}
}
function mouseMove(e) {
// This is being executed on window resize
console.log(e.movementY);
}
结果是,当窗口进入全屏状态(Firefox完全将其打开)时-我在控制台中打印了 e.movementY ,并且值并非总是 0 。
问题是我该如何阻止Firefox的“功能”,以便不触发鼠标移动事件?
答案 0 :(得分:1)
找到了减轻该问题的解决方案。不幸的是,没有可行的解决方案可以真正解决问题,因为每当Firefox调整窗口大小时,鼠标都会以某种方式拖动,以使指针相对于左上角的位置保持不变。但是,由于它在屏幕上移动,因此触发了虚假的mousemove
事件。
减轻这种情况的一种方法是在窗口对象中添加resize
处理程序,以检查是否正在调整窗口大小-如果是,则设置一个标志并使用它来使鼠标移动处理程序摆脱困境。不幸的是,当鼠标移动时,您不能仅重置此标志,因为您仍然会偶尔收到虚假的mousemove
事件。相反,当您可以相对确定浏览器窗口的大小已完全调整时,必须设置一个超时,最终将重置该标志。
我设法通过如下所示的测试用例完成了该任务:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xml:lang="en">
<head>
<title>canvas Test Case</title>
<style type="text/css">
body {
background-color: silver;
}
canvas {
background-color: white;
}
</style>
<script type="application/javascript">
/* <![CDATA[ */
'use strict';
var canvas;
var this_timeout = null;
document.addEventListener('DOMContentLoaded', function (p_event) {
canvas = document.getElementById('canvas');
document.addEventListener("click", function (p_event) {
canvas.requestPointerLock = canvas.requestPointerLock ||
canvas.mozRequestPointerLock ||
canvas.webkitRequestPointerLock;
if (canvas.requestPointerLock)
canvas.requestPointerLock();
}, false);
document.addEventListener("pointerlockchange", plChange, false);
document.addEventListener("mozpointerlockchange", plChange, false);
window.addEventListener('resize', function (p_event) {
// Use this handler to set a flag that a resize event is taking place.
// Using the timeout ID actually hits two birds with one stone: It serves as a
// flag that a resize is actually taking place, plus it allows us to reset the
// timeout if it hasn't expired when another one fires.
if(this_timeout)
clearTimeout(this_timeout);
this_timeout = setTimeout(function () { this_timeout = null; }, 250);
console.log('Resizing...'); }, true);
}, false);
function stoppedResize() {
// If the timeout expires, reset the timeout id to show that we are done resizing.
this_timeout = null;
}
function plChange(p_event) {
var controlEnabled = (document.mozPointerLockElement === canvas ||
document.webkitPointerLockElement === canvas ||
document.pointerLockElement === canvas);
if (!controlEnabled) {
console.log('Disabling mouse tracker...');
window.removeEventListener("mousemove", mouseMove);
} else {
console.log('Enabling mouse tracker...');
window.addEventListener("mousemove", mouseMove, false);
}
}
function mouseMove(p_event) {
// Check whether there's a timeout running. If yes, just bail out...
if(this_timeout)
{
console.log('Skipping...');
return;
}
console.log('Mouse movement detected!');
}
/* ]]> */
</script>
</head>
<body>
<header><h1>canvas Test Case</h1></header>
<main>
<canvas id="canvas" width="800" height="600" />
</main>
</body>
</html>
通过这样做,您可以轻松缓解此问题。不幸的是,这不是我会首选的干净解决方案,但是鉴于种种情况,这是解决我可能想到的问题的最佳方法。
关于您的其他问题,我想您想在此处发布示例吗?如果是,我认为您已经对代码施加了一些限制。由于一切似乎都发生在iframe
中,因此我认为某些操作是不允许的。附加某些事件处理程序显然会受到影响。