1

I want to prevent the mouse wheel from actually scrolling the document if the pointer is locked to a certain element.

Here is a minimal example:

<style>
    div {
        width: 200px;
        height: 2000px;
        background: red;
    }
</style>
<div></div>

<script>
    const div = document.querySelector('div');
    let locked = false;
    document.addEventListener('pointerlockchange', () => {
        locked = document.pointerLockElement !== null;
        console.log("setting locked:", locked)
    });
    div.addEventListener('click', () => {
        div.requestPointerLock()
    });
    document.addEventListener('wheel', event => {
        if (!locked) {
            console.log("break");
            return;
        }

        console.log("locked:", locked, " cancelable:", event.cancelable);
        event.stopImmediatePropagation();
        event.preventDefault();
    });
</script>

When I click the red div the pointer is locked to the div (this works) and the variable locked is set to true (works). When I press ESC the lock is released and I can move the mouse again (works).

I also listen for mouse wheel events and prevent them if the variable locked is set to true. On Firefox and even Edge this works fine but on Google Chrome the event.preventDefault() is ignored and the page scrolls down/up (not what I want).

A sample workflow might look like this:

  1. I move the cursor anywhere (over the div or not doesn't matter)
  2. I use the scroll wheel and the page scrolls accordingly (as it should)
  3. In the console I see break
  4. Now I click on the div and the pointer is locked
  5. The console says setting locked: true
  6. Now I scroll again, but the page still scrolls (wrong)
  7. Console: locked: true cancelable: false

Now comes the interesting part: If I remove the if (!locked) {} section from the wheel event listener, the event is actually prevented while the console prints locked: true cancelable: true.

So for some reason the if block makes the event non-cancelable?

Here comes my question: How can I conditionally prevent the mouse wheel from scrolling the page, with the condition being whether the pointer is locked to a certain element?

Some things I also tried:

  • Attaching the wheel event listener to the div.
  • Attaching an unconditionally preventing event listener when the pointer is locked and removing it when the lock is released.
  • Attaching the wheel event listener to "everything": window document div ...
  • event.stopPropagation();
  • event.stopImmediatePropagation(); (how many are there?)

All had the same outcome as the minimal example above.

Edit: I tried the minimal example on Google Chrome 71 on Windows 10 and on Chromium 65 on CentOS 7.4: It didn't work there.

Wombatz
  • 4,958
  • 1
  • 26
  • 35

0 Answers0