retyui / react-quick-pinch-zoom

A react component that providing multi-touch gestures for zooming and dragging on any DOM element.
https://react-quick-pinch-zoom.netlify.app/
310 stars 47 forks source link

Calling scaleTo with outside control returns element to start position #39

Closed maestor closed 2 years ago

maestor commented 3 years ago

Hi! Thanks for great library! I have one issue which can't solve and don't understand why it happens, so write here.

Use case:

Own expectations:

Actually happens:

Codesandbox: https://codesandbox.io/s/sad-dijkstra-x98nd

So, am I doing something wrong here? How I get the position staying to where it have dragged? I can see scaleTo took first correct position and moves there, then start this onUpdate iterating back to initial position.

mimoro commented 3 years ago

Hi there! I am trying to implement + and - zoom buttons too and I'm running into the same issues as stated above. After scaleTo is triggered with the new scale by clicking on the zoom button, onUpdate is called multiple times: first with the original/previous scale and current correct coordinates and then it's called again with the new scale but different x and y values until they are 0.

I'd really appreciate your help! Thanks!

retyui commented 2 years ago

@maestor you can't reuse x,y cords from an onUpdate event, as it ONLY for css translation function!

to make zoom in \ zoom out you need to remember a poison of cursor\touches to continue scaling at that point

retyui commented 2 years ago

You can use internal methods to make this functionality:

import QuickPinchZoom from "react-quick-pinch-zoom";

class MyPinchZoom extends QuickPinchZoom {
  _lastScaleToCenter = { x: 0, y: 0 };

  // owerwrite private method
  _scaleTo = (zoomFactor: number, center: Point) => {
    this._lastScaleToCenter = center; // remember the last center
    this._scale(zoomFactor / this._zoomFactor, center);
  };

  zoomIn() {
    this._stopAnimation();
    this._scaleTo(this._zoomFactor * 1.2, this._lastScaleToCenter);
    this._update();
  }

  zoomOut() {
    this._stopAnimation();
    this._scaleTo(this._zoomFactor / 1.2, this._lastScaleToCenter);
    this._update();
  }
}

// ------------------
// Usage

<>
  <MyPinchZoom ref={ref} />;
  <button onClick={() => ref.current?.zoomIn()}>+</button>
  <button onClick={() => ref.current?.zoomOut()}>+</button>
</>;

Also if you want to implement this functionality out of box, PR your welcome!