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.
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);
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.
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.
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, soevent.target.setPointerCapture
does not exist.For testing, I patched it out like this:
With that change, pointer capture still didn't work, because on react-native
e.pointerId
is callede.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-L258so as an additional hack I did this:
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 usePanResponder
, which I can see is already partially done in #3252.