Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pointer capture does not work in react-native #3315

Open
krzys-h opened this issue Jul 31, 2024 · 1 comment
Open

Pointer capture does not work in react-native #3315

krzys-h opened this issue Jul 31, 2024 · 1 comment
Labels
bug Something isn't working react-native to do with react-native

Comments

@krzys-h
Copy link

krzys-h commented Jul 31, 2024

I'm trying to implement a drag-and-drop like feature using R3F event system. It works perfectly on the web, but in react-native builds, trying to call setPointerCapture / releasePointerCapture as described in the docs (https://docs.pmnd.rs/react-three-fiber/api/events#pointer-capture) fails. Without it, onMouseMove / onMouseUp don't get properly delivered if you move the pointer too fast and it leaves the object.

Specifically, the code fails here:
https://github.com/pmndrs/react-three-fiber/blob/v8.16.8/packages/fiber/src/core/events.ts#L297
https://github.com/pmndrs/react-three-fiber/blob/v8.16.8/packages/fiber/src/core/events.ts#L150

on react-native, the event.target field seems to be an integer handle of the target view, not an object, so event.target.setPointerCapture does not exist.

For testing, I patched it out like this:

diff --git a/node_modules/@react-three/fiber/dist/index-99983b2d.esm.js b/node_modules/@react-three/fiber/dist/index-99983b2d.esm.js
index d3aa0a8..606b519 100644
--- a/node_modules/@react-three/fiber/dist/index-99983b2d.esm.js
+++ b/node_modules/@react-three/fiber/dist/index-99983b2d.esm.js
@@ -835,7 +835,7 @@ function releaseInternalPointerCapture(capturedMap, obj, captures, pointerId) {
     // If this was the last capturing object for this pointer
     if (captures.size === 0) {
       capturedMap.delete(pointerId);
-      captureData.target.releasePointerCapture(pointerId);
+      if(captureData.target.releasePointerCapture) captureData.target.releasePointerCapture(pointerId);
     }
   }
 }
@@ -991,7 +991,7 @@ function createEvents(store) {
             // faster access.
             internal.capturedMap.set(id, new Map([[hit.eventObject, captureData]]));
           }
-          event.target.setPointerCapture(id);
+          if(event.target.setPointerCapture) event.target.setPointerCapture(id);
         };
         const releasePointerCapture = id => {
           const captures = internal.capturedMap.get(id);

With that change, pointer capture still didn't work, because on react-native e.pointerId is called e.identifier. This caused it to silently fail here:
https://github.com/pmndrs/react-three-fiber/blob/v8.16.8/packages/fiber/src/core/events.ts#L257-L258

so as an additional hack I did this:

if (typeof event.pointerId === 'undefined')
    event.pointerId = event.identifier;

and now the pointer capture seems to work.

I would have expected this to work only partially, and break if you move the pointer out of the canvas while holding the object, but it seems that at least in my setup, react-native defaults to capturing the pointer to the view you initially clicked on. This could be some side-effect of using r3f-native-orbitcontrols though, I didn't fully test it. The "proper" way to implement it in react-native is probably to use PanResponder, which I can see is already partially done in #3252.

@CodyJasonBennett
Copy link
Member

With #3252, it seems we only need the last patch with event.identifier. Can you confirm that on your end? Would happily accept a PR also if that's enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working react-native to do with react-native
Projects
None yet
Development

No branches or pull requests

2 participants