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/
308 stars 46 forks source link

How to manually trigger zoom? #66

Closed leandrocrs closed 1 year ago

leandrocrs commented 1 year ago

I need to trigger zoom by one click only. I'm able to capture the click and position X and Y related to the inner element where the user has clicked, and I'm using quickRef.scaleTo({ scale: 2, x: innerEl.clientX, y: innerEl.clientY }) to make QuickPinch to the hard work.

However, the offset is wrong, and looking to the code I was not able to completely understand the logic to calculate proper X and Y positions.

I did also try to use alignCenter, but with no success either.

Any clue how can I achieve 1 click zoom?

Demo:

retyui commented 1 year ago

you can solve trying to find a combination for the next props:

  tapZoomFactor={1}
  zoomOutFactor={1.3}
  maxZoom={5}
  minZoom={0.5}

see docs: https://github.com/retyui/react-quick-pinch-zoom/blob/master/docs/api/README.md

leandrocrs commented 1 year ago

@retyui thanks for fast response!

My problem is to focus on point that user clicked. You can see in this video above that the zoom is applied next to click, but not in exact point. I'm passing clientX and clientY, but I'm not sure if I have to care about offset, and if so, what should I pass to make sure the exact point will be zoomed.

leandrocrs commented 1 year ago

For reference:

I did managed how to it. The mistake was not taking in account the parent offset, so I have created a function to make the calculation:

const getZoomCoordinates = (ev: ReactMouseEvent<HTMLElement, MouseEvent>, innerEl: HTMLElement) => {
  const parentOffset = innerEl.offsetParent

  const parentClientRects = parentOffset?.getClientRects().item(0)

  return {
    x: ev.clientX - (parentClientRects?.left || 0),
    y: ev.clientY - (parentClientRects?.top || 0)
  }
}

// and when I call scaleTo, I call this helper function to give me the coordinates
const { x, y } = getZoomCoordinates(ev, innerRef.current)

quickPinchRef.current.scaleTo({
  x,
  y,
  scale,
  animated: true
})

Result: