I have a When a fixed-size <Canvas> inside a centred container. When I resize the window horizontally,<Canvas /> moves on the screen for any reason other than the window being resized, pointer events no longer occur within the bounds of the canvas.
could you make a quick codesandbox to wire up all the css stuff to reproduce it? it's probably a change that needs to go into react-use-measure but we can profile it here.
Good call on the sandbox ... it wasn't as straightforward to reproduce as I thought. Here is the link https://codesandbox.io/s/r3f-pointer-events-bug-j5rfk
I've learned that the bug occurs:
This has nothing to do with the canvas being centred as I initially thought. I'll update the title of the issue and clarify the description.
not sure if this can be solved. i think there's nothing in the dom that can tell you that something moved. all we have is resizeobserver, which doesn't fire in this case. what i could do is expose the resize function so you can call it yourself when you know you're about to toggle alignment. it sucks i know.
Could this be linked to the use of clientX and clientY over offsetX and offsetY? If I'm not mistaken, with the latter, the coordinates of the pointer would always be relative to the top-left corner of the canvas.
offsetX|Y is experimental but I'm pretty confident it's supported everywhere three.js is supported.
yes i have the same issue using react-three-fiber inside react-transition-group, what i did is when the transition end i fire a windows resize event .
@axelboc didnt see your post, but could be, i have almost given up understanding dom events. if you make a PR and do a little testing before so that everything keeps going, i would approve if that fixes the issue.
adding to what @adelchamas96 said here, i updated the code sandbox with the following code:
...
const [alignEnd, setAlignEnd] = useState(false)
useEffect(() => {
window.dispatchEvent(new Event('resize'))
}, [alignEnd])
...
(https://codesandbox.io/s/r3f-pointer-events-bug-1qclj)
which triggers a resize event on state change - fixes the problem in the sandbox for those waiting on the merge of #406
@drcmda, can you please re-open this issue as per https://github.com/pmndrs/react-three-fiber/commit/42569b9dbd107195668d1f0314f9738155a008a7?
To summarise, replacing clientX/clientY with offsetX/offsetY in the default raycaster has introduced a regression in cases involving scrolling. In such cases, the raycaster receives events that originate from a scrolled element rather than from the canvas itself, which leads to offsetX and offsetY being relative to the scroll position of the element.
For a reproduction, see https://codesandbox.io/s/r3flex-forked-3czg6?file=/src/App.tsx. (Use R3F v5.1.3 to test the regression; it was reverted in v5.1.4).
Perhaps a solution would be to allow users to compute the offsetX and offsetY values used in the raycaster:
<Canvas
computeRaycasterOffsets={(event) => {
const { nativeEvent } = event;
return {
offsetX: nativeEvent.offsetX,
offsetY: nativeEvent.offsetY - state.top
};
}}
/>
The raycaster would then call this function, if provided:
const { offsetX, offsetY } = computeRaycasterOffsets ? computeRaycasterOffsets(event) : event.nativeEvent;
makes sense, i would accept it. let's do it! :-D glad that at least now it's clear whats happening.
Most helpful comment
@axelboc didnt see your post, but could be, i have almost given up understanding dom events. if you make a PR and do a little testing before so that everything keeps going, i would approve if that fixes the issue.