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

Pinch gestures trigger onWheel #80

Closed
andreas-eberle opened this issue Aug 13, 2019 · 12 comments
Closed

Pinch gestures trigger onWheel #80

andreas-eberle opened this issue Aug 13, 2019 · 12 comments

Comments

@andreas-eberle
Copy link

I try to use your component to zoom an image in a canvas by scrolling as well as by pinching. Therefore I use useGesture to add onWheel and onPinch listeners. However, when I pinch, both callbacks are called.

So I tried to only use the onWheel callback. It is enough to zoom my canvas whenever the user scrolls or pinches. However, since pinching gives way less onWheel events as the actual scrolling, I end up with a way slower zooming when I use pinching.

So I have three questions:

  • Is there a way for me to tell if a onWheel event was acutally triggered by pinching? This way, I could use a different zoom factor for scrolling and pinching.
  • Is it a desired/intended behavior that onWheel is called when the user pinches?
  • If so, is it expected that scrolling causes way more events than pinching?

Many thanks in advance!

@dbismut
Copy link
Collaborator

dbismut commented Aug 13, 2019

Right, I think see where this comes from. Can you confirm you’re using a trackpad with Chrome or if using Safari, are your binding the component (ie not using domTarget)? Essentially when you pinch to zoom on a trackpad browsers might send the onWheel event with the ctrl modifier key flag set to true. I’ll write a fix asap.

A temp fix would be to check if the ctrlKey flag is set to true in your life onWheel handler.

@andreas-eberle
Copy link
Author

I'm using the touchpad of my Dell XPS 15 with Windows 10 in Firefox.
I'm not setting domTarget.
And yes, I can confirm, the ctrlKey flag is set for pinches. Thanks for the hint and thanks for fixing it!

dbismut added a commit that referenced this issue Aug 13, 2019
@dbismut
Copy link
Collaborator

dbismut commented Aug 13, 2019

@andreas-eberle I've released 6.0.0-beta.2 just now, which does the below regarding this issue:

  • Adds a warning when using trackpad zoom without a domTarget or event.passive set to true.
  • Doesn't trigger the onWheel handler when the ctrl key is pressed and onPinch is active
  • Adds a gesture key to the event passed to handlers indicating which gesture originated the event.

Regarding the first point, the pinch-zoom on a trackpad should be default prevented, to avoid the wheel event propagating to the window. If you attach the handlers directly in React, non-passive events aren't supported, therefore event.preventDefault() doesn't work as it should.

Note that there's a few breaking changes in 6.0.0 (mostly renames though) so you might prefer waiting until tomorrow so that I can also fix 5.2.x.

@andreas-eberle
Copy link
Author

@dbismut: I tried out version 6.0.0-beta.2. However, I still get the onWheel() callback when pinching.

My code looks like this:

export interface Props {
	zoomHandler(zoomOut: boolean, pinch: boolean): void
}

const ZoomContainer: FunctionComponent<Props> = (props) => {

	const onWheel: Handler<Coordinates> = (state) => {
		const direction = state.direction[1]

		console.log(`onWheel(direction: ${direction}, ctrlKey: ${state.ctrlKey})`)

		if (direction !== 0) {
			props.zoomHandler(direction < 0, false)
		}

		if (state.event) {
			state.event.preventDefault()
		}
	}

	const onPinch: Handler<DistanceAngle> = (state) => {
		const direction = state.direction[0]

		console.log(`onPinch(direction: ${direction}, ctrlKey: ${state.ctrlKey})`)

		if (direction !== 0) {
			props.zoomHandler(direction > 0, true)
		}

		if (state.event) {
			state.event.preventDefault()
		}
	}

	const ref = React.useRef(null)
	const bind = useGesture({onWheel, onPinch}, {event: {passive: false, capture: false}, domTarget: ref})
	React.useEffect(bind, [bind])

	return <div ref={ref}>
		{props.children}
	</div>
}

and when I pinch, I get the following output in the console:

onPinch(direction: 1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: -1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: 1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: -1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: 1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 0, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: 0, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: -1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: -1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: -1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: -1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: -1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 1, ctrlKey: true) ZoomContainer.tsx:19
onPinch(direction: -1, ctrlKey: true) ZoomContainer.tsx:33
onWheel(direction: 1, ctrlKey: true) ZoomContainer.tsx:19

Am I doing something wrong? Or is there still an issue in the library?

@dbismut
Copy link
Collaborator

dbismut commented Aug 14, 2019

That's really weird, here is the code in the WheelRecognizer:

if (event.ctrlKey && this.controller.actions.has('onPinch')) return

Would you be able to set a simple repro sandbox somewhere?

Here is a csb where the left square reacts to wheel, and the right square should react to pinch.
https://codesandbox.io/s/react-use-gesture-issue-wheel-fj4rc

Do both square update on pinch on your end?

@andreas-eberle
Copy link
Author

If you change the code of the callbacks in your sandbox to:

      onWheel: ({ offset: [, oy] }) => {
        console.log('onWheel')
        set({ wheel: oy, immediate: true })
      },
      onPinch: ({ offset: [d] }) => {
        console.log('onPinch')
        set({ pinch: d, immediate: true })
      }

You can see in the console that onWheel and onPinch are called, when you pinch (at least it is that way for me).

@dbismut
Copy link
Collaborator

dbismut commented Aug 14, 2019

Hm indeed my code is a bit dumb since I’m not showing the same offset index 😅 I’m on my phone and will only be able to check that back later tonight. Can you confirm this is also happening on Chrome? does this (both gesture logging in the console) also happen when you wheel while physically pressing the ctrl key?

@andreas-eberle
Copy link
Author

  • I can confirm that it behaves the same in Chrome.
  • Using ctrl+scrolling looks like using the pinch gesture (it logs onWheel and onPinch).

@dbismut
Copy link
Collaborator

dbismut commented Aug 14, 2019

There must have been an issue when I published on npm. Please try 6.0.0-beta.3, my sandbox has been updated and it works properly. Sorry about this.

@andreas-eberle
Copy link
Author

No worries! Thanks for the support and super fast help! It works now 👍

@dbismut dbismut mentioned this issue Sep 19, 2019
Merged
@tommedema
Copy link

  • gesture

@dbismut I have version 7.0.5 and this property is not available, also it says pinching: false even though I am definitely pinching (on an iPhone XS Max in Safari)

also how do you know if it is a zoom-in pinch or a zoom-out pinch?

Screen Shot 2020-03-27 at 7 20 10 PM

@dbismut
Copy link
Collaborator

dbismut commented Mar 28, 2020

@tommedema the capture shows that the gesture is no longer active so this is not surprising that pinching is false. Zoom in means that the movement displacement between your fingers has increased. So movement[0] which measures the distance delta of the whole gesture should be positive. Zoom out is movement[0] being negative.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants