controls end event broken for mousewheel
See original GitHub issueDescribe the bug
Currently mousewheel is treated like this in controls:
function onMouseWheel(event) {
if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return
event.preventDefault()
event.stopPropagation()
scope.dispatchEvent(startEvent)
handleMouseWheel(event)
scope.dispatchEvent(endEvent)
}
That means that start
and stop
for zoom cannot be relied upon as it behaves differently from all other gestures, pan and rotate for instance. This makes it hard to detect when the control has stopped on the parental level.
We started to notice this because we render on demand. Controls tell the state model that the scene is moving or not. Zoom caused issues when the canvas flips on-demand-rendering on and off.
To Reproduce
https://codesandbox.io/s/r3f-basic-demo-forked-omcxr
Open the dev console and pan, you will see 1 start, 1 stop. Zoom and it will spit out hundreds of start/stops.
Expected behavior
start
and stop
should not leak internals, they should tell the user when controls are active and when not. As long as controls are dollying, either because mousewheel is firing in sequence or because damping is enabled, stop
should not be called. In this case it has to anticipate browser behaviour and debounce the tail call. It could do the same to start
with a leading call but it’s not as important imo.
import debounce from "lodash-es/debounce"
const debouncedEnd = debounce(() => scope.dispatchEvent(endEvent), 100)
function onMouseWheel(event) {
if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return
event.preventDefault()
event.stopPropagation()
scope.dispatchEvent(startEvent)
handleMouseWheel(event)
debouncedEnd()
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:15 (14 by maintainers)
Top GitHub Comments
This is what happens when you scroll:
Three just removed Geometry, Face3, switched to WebGL2, etc …, … Imo this is a bug report, not a feature request. 😛
The debounce could be anything, just to help it connect frames. It could also be fixed by checking movement diff, perhaps better than a debounce? If it’s actively moving, something needs to tell it that it can’t call the stopped-event.
We can make the PR if you decide to give it a shot.
@pailhead actually, if we assume that event.deltaY is proportional to wheel rotation speed, we can model its rotation and estimate the time remaining until complete stop. This model would have to take into account sudden deltaY increases due to repeated spins, etc, but probably still doable? Maybe. Not sure if you get wheel events fast enough for this estimation to be accurate enough.