Can't interact with canvas when having < divs> on top of it

Hi there,

I have a html page with a < canvas> sitting in the background (position: fixed). Over this canvas I have several divs.

Unfortunately I can’t recreate a playground for it but this is what goes in the actual canvas itself:
https://www.babylonjs-playground.com/#VHWT1E#10
As you can see from the playground, the map rotates when you move the mouse around the canvas

Back to the HTML, on top of this < canvas> I have a series of divs with links, images and few other bits. Once the mouse goes over some of these divs (containers) I can’t interact with the canvas anymore which means the map doesn’t rotate

Is there any way to fix this?

Thank you

Well this is expected :slight_smile: This is how HTML works through layers.

It that works for you, you can set with css pointer-events: none on your divs but you will not be able to click them.

Try to ensure that your divs are not covering the canvas but just the content (like not 100% with centered content)

Removing the point events was my first call but I have seen it working on other sites so I was wondering how it was done.

Found an example:


I’m aware that this site is using Three JS but the premise is very close to what I’m trying to achieve. Canvas fixed in the background and containers (divs) on top of it. No matter where your mouse is (project names, experience paragraph, etc), the orange circle from the < canvas> element does that panning effect

As 3js and babylonjs are comparable in the way they work it could be useful to understand how they do it to reproduce it for sure

I think they are capturing the events on the HTML side and use them to pilot the 3D.

This is starting to sound like mandarin to me but I get you.

document.querySelector('#sample').addEventListener('mouseover', function(){}

Is this the sort of thing you are talking about? Would you be able to guide me a little as I’m out of my depth here??

Thanks

Totally.

You need to get the mouse event and then use that event (probably evt.offsetX or offsetY) to change the position of your camera maybe? Depending on what you want to do :slight_smile:

I got the position of the mouse based on the window

var clientX = 0;
var clientY = 0;
window.addEventListener('mousemove', function(e) {
  clientX = e.clientX;
  clientY = e.clientY;
});

And this is the current code that controls the rotation of the map

let inertialAlpha = 0;
let inertialBeta = 0;
let inertia = 0.95;
let angularSpeed = 0.0005;

scene.onPointerObservable.add(evt => {

    var offsetX = evt.event.movementX ||
                evt.event.mozMovementX ||
                evt.event.webkitMovementX ||
                evt.event.msMovementX ||
                0;
    var offsetY = evt.event.movementY ||
                    evt.event.mozMovementY ||
                    evt.event.webkitMovementY ||
                    evt.event.msMovementY ||
                    0;

    const eu = ground.rotationQuaternion.toEulerAngles();
    if  ((eu.y < 0.2 && offsetX < 0)) {
        inertialAlpha -= (offsetX * angularSpeed)/35;
    }
    if  ((eu.y > -0.2 && offsetX > 0)) {
        inertialAlpha -= (offsetX * angularSpeed)/35;
    }

    if  ((eu.x < 0.2 && offsetY > 0)) {
        inertialBeta -= (offsetY * angularSpeed)/45;
    }
    if  ((eu.x > -0.2 && offsetY < 0)) {
        inertialBeta -= (offsetY * angularSpeed)/45;
    }

    scene.registerBeforeRender(() => {
        ground.rotate(BABYLON.Vector3.UpReadOnly, inertialAlpha, BABYLON.Space.LOCAL);
        ground.rotate(BABYLON.Vector3.Left(), inertialBeta, BABYLON.Space.WORLD);
        inertialAlpha *= inertia;
        inertialBeta *= inertia;
    });

});

The values I get from clientX/Y are always much higher than eu.x/y and offsetX/Y. How can we make it work from here??

why not just use movementX instead of clientX?

I got rid of this function
scene.onPointerObservable.add(evt => {})

and used addEventListener instead and it seems to work:

window.addEventListener('mousemove', function(evt) {
    var offsetX = evt.movementX ||
                evt.mozMovementX ||
                evt.webkitMovementX ||
                evt.msMovementX ||
                0;
    var offsetY = evt.movementY ||
                    evt.mozMovementY ||
                    evt.webkitMovementY ||
                    evt.msMovementY ||
                    0;

    const eu = ground.rotationQuaternion.toEulerAngles();
    if  ((eu.y < 0.2 && offsetX < 0)) {
        inertialAlpha -= (offsetX * angularSpeed)/35;
    }
    if  ((eu.y > -0.2 && offsetX > 0)) {
        inertialAlpha -= (offsetX * angularSpeed)/35;
    }
});

Is this bad practice??

nope this is super fine :slight_smile:
congrats! See? you did it!

that is brilliant!! thanks a lot for guiding me @Deltakosh. I definitely couldn’t have done it without your help :wink:

1 Like