pmndrs / react-three-fiber

🇨🇭 A React renderer for Three.js
https://docs.pmnd.rs/react-three-fiber
MIT License
27.62k stars 1.6k forks source link

help: using the onPointerDown event of a` <group/>` and the event.handlers of `useThree()` together #3209

Closed dusunax closed 8 months ago

dusunax commented 8 months ago

I am having trouble using the onPointerDown event of a <group/> and the event.handlers of useThree() together.

What I want is

to execute the 1️⃣onModelClick handler of a group when in "object addition mode," and when not in "object addition mode," I want to execute the function set in the 2️⃣onPointerDown of the useThree state.

With my current knowledge of web frontend, it seems like I need to manage event propagation, but once I register a handler in event.handlers, the previously created onModelClick of the group does not get triggered.

In the console or react dev tool, the event target appears as the canvas. I have been working with 3D rendering for less than a year, so debugging is challenging for me🥲

What I did

useThree(({ events }) => {
   events.handlers.onPointerDown = onPointerDown;
   events.handlers.onPointerUp = onPointerUp;
   ...
}
return (
  <group
    name={model.name}
    key={model.name}
    onPointerDown={onModelClick} // does not work
  >
    <mesh ref={frontMesh} geometry={geoFront} material={matFront} />
    <mesh ref={backMesh} geometry={geoBack} material={matBack} />
  </group>
);

I added handlers to onPointerMove and onPointerDown of useThree's events.handlers later on. It's for implementing the arcball feature that rotates 3D model, not the existing orbitControl that rotates the camera.

👉 Since it needs to rotate even when clicking outside the model, I cannot combine onPointerDown with the .

Solution that I can think of

Solution A

Solution B

three.set({ events: { ...events, priority: 0 } })

I would really appreciate a hint from someone knowledgeable. Thank you in advance. If I solve it myself, I will share the result for beginners like me

currently reading https://docs.pmnd.rs/react-three-fiber/api/events#customizing-the-event-settings, checking out EventManageFactory

dusunax commented 8 months ago

[!NOTE] I've checked the documentation and resolved the issue myself. so self close Issue & sharing this troubleshooting for anyone who might be facing the same problem.

Category Content
Cause Lack of understanding of (1)3D event propagation, (2)the library in use (R3F)
Solution Thoroughly read the official documentation & source code (as always, the best solution). react-three-fiber: events, events.ts

Registering the onPointerDown event

In 3D, because one can occlude another (differently from DOM), it operates differently.

  • Bubbling starts from the object closest to the camera.
  • Propagates through all objects intersecting with the ray as intersections.
  • event.stopPropagation() not only prevents bubbling to ancestors but also to objects behind.
    • If a pointerover event is passed - a pointerout event is immediately triggered.

Problem no.2

return(
    <CanvasWrapper>
        <Canvas> // R3F canvas
            <LoadingSuspense>
                <CanvasContents> // Contains the onPointerDown logic
                <CanvasHTMLElements> // HTML elements not in 3D 
            </LoadingSuspense>
        </Canvase>
    </CanvasWrapper>
)

Conclusion: use onPointerUp instead.