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

trackpads - how to have pinch do zoom and two finger movement pan the viewport? #143

Open
dontwork opened this issue Jun 22, 2019 · 25 comments

Comments

@dontwork
Copy link

No description provided.

@davidfig
Copy link
Owner

Is this for Mac or PC trackpads? Have you tried viewport.wheel() for the zoom? (I expect it won't work but worth a try.)

@dontwork
Copy link
Author

this makes it so that 2 finger dragging zooms, overriding the previous behaviour of 2 finger dragging moving the camera

is it possible for 2 finger drag to move the camera and pinching do the zoom

@davidfig
Copy link
Owner

It is possible. I don’t think it’s currently supported. I’ll see if I can get it working.

@dontwork
Copy link
Author

@davidfig any thoughts on this one?

@davidfig
Copy link
Owner

Still working on this. I've had limited success using https://medium.com/@auchenberg/detecting-multi-touch-trackpad-gestures-in-javascript-a2505babb10e

To give you an idea where I am: it sort of works on PC trackpads but the 'wheel' event (on my device) locks the direction--i.e., if you start a horizontal two-finger drag (without press), then it will not return a event.deltaY and vice versa. If you start a two-finger drag with a diagonal move then it works correctly.

Sigh. Still working through this last blocking PC issue. I also need to implement gestureevents to support Safari.

@davidfig
Copy link
Owner

davidfig commented Jul 1, 2019

This may not be possible. Here's the stackoverflow conversation: https://stackoverflow.com/questions/56825793/javascript-wheel-event-locks-to-horizontal-or-vertical-movement-and-does-not-all

I'll see if there are any other suggestions, but on Chrome/PC, the trackpad will not properly register the movement events. Firefox is generally okay support (although the scaling for the movement is weird). Safari would require a different API (GestureEvents).

@davidfig
Copy link
Owner

davidfig commented Jul 7, 2019

And here's the chrome bug report: https://bugs.chromium.org/p/chromium/issues/detail?id=980479

Feel free to star the report if you're interested in having this feature.

@davidfig
Copy link
Owner

davidfig commented Jul 9, 2019

Looks like chrome is not going to support this behavior. I'm going to close this issue since it's not worth implementing if it doesn't work in chrome.

@davidfig davidfig closed this as completed Jul 9, 2019
@dontwork
Copy link
Author

I am not sure i understand the relevance of the chrome issues you cite to the original intention behind this ticket.

To be clear, does the behaviour in chrome prevent pinch zooming altogether?

@davidfig
Copy link
Owner

Correct. On chrome you cannot use two-finger movement on a trackpad. Once you start a two-finger movement, chrome locks you in the horizontal or vertical direction. You do not get event data about the other axis. Zoom may work but you can't perform the same two-finger move and zoom that currently works on touchscreens.

I see no way around this limitation and chromium doesn't want to change the behavior. I'm open to alternative suggestions.

@dontwork
Copy link
Author

I'm not sure but i know figma (also uses webgl) have pinch to zoom, as mentioned here:
https://medium.com/@auchenberg/detecting-multi-touch-trackpad-gestures-in-javascript-a2505babb10e

@ygorlf
Copy link

ygorlf commented Mar 5, 2020

Hi @davidfig , I'm also need a 'pinch to zoom' and 'two-fingers drag' the workaround posted by @dontwork could be used in pixi-viewport?

@davidfig
Copy link
Owner

davidfig commented Mar 6, 2020

Yes, I've been working on a patch to support both PC and Mac trackpads for wheel scroll, and pinch and zoom. It's currently in the gesture branch of this repository. I think the PC code is working, but I still need to add the code for mac (it uses a proprietary gesture library).

It's on my list, but I probably won't get a chance to finish it for a few weeks.

@ygorlf
Copy link

ygorlf commented Mar 6, 2020

Ok, I'll test the gesture branch and track the status of the feature. Thank you so much, your library is helping me a lot, thanks for put the time to create this.
:)

@davidfig
Copy link
Owner

davidfig commented Mar 6, 2020

Cool. let me know how the branch works and if you find any bugs. i've tested it somewhat and it seems to work. i do need to get the mac gesture stuff working for my current project, so it's a high priority on my list.

@crutch12
Copy link

Hi
Any progress on this?

@npgauth
Copy link

npgauth commented May 11, 2020

We're also in need of this feature.

@davidfig were you able to get the Mac code added? Happy to test the gesture branch if so.

(This library is great btw!) Thanks!

@davidfig davidfig reopened this May 12, 2020
@davidfig
Copy link
Owner

I have not, but I really need to get that done. I don't have my mac with me today, but I'll put it in my bag for tomorrow and get this sorted out. I'd love to take it off my list as well. Stay tuned.

@jkar32
Copy link

jkar32 commented May 28, 2020

Curious how this is going.

I made a poor mans version which works on chrome but not properly safari.

Here is the code for the plugin

import { Plugin, Viewport } from "pixi-viewport";
import { assign } from "lodash";

type Options = {
    moveSpeed: number;
    moveReverse: boolean;
    zoomSpeed: number;
    zoomReverse: boolean;
};

const defaults: Options = {
    moveSpeed: 1,
    moveReverse: false,
    zoomSpeed: 1,
    zoomReverse: false,
};

export class PinchToZoomAndMove extends Plugin {
    private parent: Viewport;
    private options: Options;
    private moveReverse: number;
    private zoomReverse: number;

    constructor(parent: Viewport, options: Partial<Options>) {
        super(parent);
        this.parent = parent;
        this.options = assign({}, options, defaults);

        this.moveReverse = options.moveReverse ? 1 : -1;
        this.zoomReverse = options.zoomReverse ? 1 : -1;
    }

    wheel(event: WheelEvent) {
        if (event.ctrlKey) {
            this.zoom(event);
        } else {
            this.pan(event);
        }
    }

    private pan(event: WheelEvent) {
        this.parent.x +=
            event.deltaX * this.options.moveSpeed * this.moveReverse;
        this.parent.y +=
            event.deltaY * this.options.moveSpeed * this.moveReverse;
    }

    private zoom(event: WheelEvent) {
        const delta =
            1 -
            (this.zoomReverse * event.deltaY * this.options.zoomSpeed) / 300;

        // hack as input is not typed on parent
        const point = (this.parent as any).input.getPointerPosition(event);
        const oldPoint = this.parent.toLocal(point);

        this.parent.scale.x *= delta;
        this.parent.scale.y *= delta;

        const newPoint = this.parent.toGlobal(oldPoint);
        this.parent.x += point.x - newPoint.x;
        this.parent.y += point.y - newPoint.y;
    }
}

Here is how to use it

viewport.plugins.add("wheel", new PinchToZoomAndMove(viewport, {}));

Also on mac (not sure on windows) if you pinch you zoom into the page, to prevent this I have used

window.addEventListener(
    "mousewheel",
    (e: Event) => {
        e.preventDefault();
    },
    { passive: false }
);

I will test on windows soon but hoping this patch in here will solve all these problems

@davidfig
Copy link
Owner

davidfig commented Jul 3, 2020

I got about halfway done with it, and then the project I was consulting on ended. I definitely want to finish this, but it may not be until my schedule opens up a bit.

@mjzzz1
Copy link

mjzzz1 commented Mar 29, 2022

Hi
Has this issue been fixed in the latest version? it doesn't seem to work on mac/chrome. or need some special configuration?

@fakob
Copy link

fakob commented Apr 2, 2022

This is my setup. With a trackpad it allows to do 2-finger pan and pinch for zoom. For mouse it allows to do middle, right click pan and ctrl+wheel to zoom.

// configure viewport
viewport.current
  .drag({
    clampWheel: false,
    mouseButtons: 'middle-right',
  })
  .pinch()
  .wheel({ smooth: 3, trackpadPinch: true, wheelZoom: false })
  .decelerate({
    friction: 0.8,
  })
  .clampZoom({
    minScale: 0.05,
    maxScale: 4,
  });

However I would like to have a similar behaviour as Miro's "Auto-switch". Somehow they detect if a trackpad or a mouse is used and switch to wheel(wheelZoom: true) when using a mouse. At least this is how I believe it works. Anyone know how to achieve that?

@fakob
Copy link

fakob commented Apr 2, 2022

For anyone interested, I did a "gesture map" where I looked at the behaviour of using mouse/trackpad in different applications.

Research - flow based frameworks - Gesture map

@fakob
Copy link

fakob commented Apr 3, 2022

Regarding Miro's auto-switch behaviour I found this snippet on stackoverflow which allows for differentiating between a device with a scroll-wheel and trackpad. I tested it with some trackpads and mouses on mac and pc and it seems to work fine.

function detectTrackPad(e) {
  var isTrackpad = false;
  if (e.wheelDeltaY) {
    if (e.wheelDeltaY === (e.deltaY * -3)) {
      isTrackpad = true;
    }
  }
  else if (e.deltaMode === 0) {
    isTrackpad = true;
  }
  console.log(isTrackpad ? "Trackpad detected" : "Mousewheel detected");
}

document.addEventListener("mousewheel", detectTrackPad, false);
document.addEventListener("DOMMouseScroll", detectTrackPad, false);

And based on this detection I am setting wheelZoom to true for scroll-wheels or false for trackpads.
See here: https://github.com/fakob/plug-and-play/pull/91/files

@davidfig, you have created an awesome library. Thanks for your work!

@fakob
Copy link

fakob commented Oct 27, 2023

I have a follow up question to this wheelZoom setup. When it is set to false I can zoom via Ctrl+Scroll.

Is there any way to also allow Cmd+Scroll to be used when on a Mac?

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

8 participants