OrbitControls with clickable overlay

Hi, is there a way for a html overlay to pass through the pointer events to the engine (and to three’s OrbitControls which does its own thing by itself apparently) while the overlay element itself should still be clickable?

In my use case there are buttons overlayed. They should stay clickable but if a swipe gesture starts over them the swipe should also trigger the camera interaction.

Hi, which Engine version are you using? Can you provide a repro? I’ve just did a quick check on stackblitz which works as intended.

OrbitControls are subscribing to events on the renderer’s canvas element which uses normal browser event bubbling. Unless you override the targetElement on the OrbitControls component.

If you want to have events pass through you need to set pointer-events: none via CSS on whichever HTML events to want to allow to go through and not being blocked. Just keep in mind that then you have to enable pointer-events again for children (e.g. button, links or text elements inside the container)

Nah I think I described it a bit complicated.

Regarding your stackblitz: If the click starts on the “Child” button and then drags over to the 3D scene I want this to be recognized as a camera interaction instead of swallowing the click inside the button.

Here’s roughly what I want: Needle-engine - Vite Template (duplicated) - StackBlitz

I guess this is more of a browser-related issue and has nothing much to do with how Needle operates though.

Here’s what I came up with for now: Register click as usual. But also register pointerdown, save the event for later. Then track if the pointer leaves the button (using pointerleave) and if so, (re-)dispatch a copy of the saved pointerdown-event from this.context.renderer.domElement. Now the engine (or OrbitControls) picks it up the pointer even if it originated on the button.

Got it, i added another option where you override the targetElement to have OrbitControls directly listen to <needle-engine> events instead of the three.js canvas. That way elements inside <needle-engine><div>mychild</div></needle-engine> would also cause OrbitControls to react:

  const orbit = context.mainCamera.getComponent(OrbitControls);
  if (orbit) {
    orbit.controls!.disconnect();
    orbit.controls!.domElement = context.domElement;
    orbit.controls!.connect();
  }

In the upcoming version it’ll be even easier by just assigning a new target element (stackblitz)

orbit.targetElement = newTargetHtmlElement

This topic was automatically closed 13 days after the last reply. New replies are no longer allowed.