JavaScript: на Firefox перемещение мыши запускается при изменении размера окна - PullRequest
0 голосов
/ 26 августа 2018

Когда я нахожусь в Firefox, canvas вызывает 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, чтобысобытие перемещения мыши не запускается?

1 Ответ

0 голосов
/ 26 августа 2018

Нашли решение для смягчения проблемы.К сожалению, нет жизнеспособного решения, которое действительно могло бы решить проблему, потому что всякий раз, когда 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>

Делая это, вы легко можете решить эту проблему.К сожалению, это не чистое решение, которое я бы предпочел, но, учитывая обстоятельства, это лучший способ справиться с проблемой, с которой я мог бы столкнуться.

Что касается вашего другого вопроса, я думаю, вы хотелиопубликовать пример здесь на SO?Если да, я думаю, что вы столкнулись с некоторыми ограничениями, наложенными на код.Поскольку все происходит в iframe, я предполагаю, что некоторые действия запрещены.Присоединение определенных обработчиков событий очевидно затронуто.

...