retyui/react-quick-pinch-zoom

Stricter position sanitization/Toggle zoom on double tap/Swipe to close

tf opened this issue · 3 comments

tf commented

Thank you very much for this great library!

We've been using it to build a zoomable fullscreen overlay for inline images. To tailor the experience to our use case, we made some changes/additions. Ideally, we would like to contribute those back upstream. I'm not 100% sure, though, if some of the features might be too specific to our use case. Therefore, I wanted to discuss our suggestions upfront, before putting more work into the API design details.

Stricter position sanitization

Currently it is possible to move the content out of bounds while dragging and zooming (in the code this is called an "insane offset"). Once the interaction stops, the content animates back to an allowed position. There already is a draggableUnZoomed prop, which prevents dragging the content when it is not zoomed. Once zoomed in a bit, the option no longer takes effect, though.

We would prefer if dragging and zooming was always confined to "sane" positions. In particular, when zooming into a landscape image on a portrait device such that the image still fits in the viewport vertically, we want to ensure that dragging is locked to the x-axis.

We have this working and could contribute a PR to add this to the available options. To be backwards compatible this could be another boolean option (name suggestion?), which would then take precedence over draggableUnZoomed. From an API design perspective, I'd prefer to combine draggableUnZoomed and this new option into a union type that describes different ways the offset is confined.

Toggle zoom on double tap

There already is an option doubleTapZoomOutOnMaxScale which allows zooming back out once max scale is reached. We would prefer, though, if double tapping a second time always zoomed out again even if it's still possible to zoom in further via pinch gesture. This is, for example, how the image viewer in the Android Twitter app works. Again, this could be a new boolean option or could be combined into something line doubleTapBehavior: 'zoomIn' | 'zoomOutOnMaxScale' | 'toggleZoom' etc. Happy to prepare a PR.

Swipe to close

The most specific thing we needed was an easy way to close our overlay on mobile. We decided that swiping up or down while the image is unzoomed would be a nice way to do this. Here's a video showing how this interaction works:

screen-20230510-103501_3.mp4

To enable the fade-out effect, we needed to pass an additional parameter to onUpdate which represents the amount of "overscroll". I really liked, how this interaction turned out, still it might not be universal enough to be a feature of the library?

One other option could be to allow passing a custom sanitizeOffset function. If we pass enough information (zoom factor, current interaction), this could be enough to implement behaviors like this. Instead of relying on an extended onUpdate payload, client component could store additional state in refs.

Let me know how you want to proceed.

retyui commented

Welcome to PR If your improvements don't break backward compatibility, I'll be happy to merge them.

retyui commented

Fixed in 4.7.0

diff: 4.6.0...4.7.0

tf commented

Thanks for being so fast! I've submitted one more PR now. The changes related to this issue can be found in #70, #71 and #72. I decided to implement the "swipe to close" functionality visible in the video above outside of this library.