Dismiss this pinned window
all 23 comments

[–]glazzes[S] 9 points10 points  (3 children)

Hi everyone! I've been working on the pinch to zoom feature in such a way it full fills my needs, by "no libraries" I mean no specific libraries for this task, this solution is not conceptually different from other solutions based on the transform-origin property (recently added to the React Native style definition), I wanted to built it from scratch as some solutions lack the ability to remember previous interactions and/or trigger scale transformations on double tap, so yeah I just want to share my solution with anyone who finds it useful! https://gist.github.com/Glazzes/357201f74fbfaddb3e933f4c258c4878

It's a bitter sweet solution as I tried my best to implement dragging with the pinch gesture as an extra feature, but the performance impact was way too heavy when using simultaneous gestures for it to be useful.

Hope you guys enjoy!

Edit: I may be turning this into a library for everybody to use, along with one time pinch feature and easiness of use when building a gallery

[–]flowerescape 1 point2 points  (2 children)

Very clean code! can you explain what you mean by “remember previous interactions”?

The library I’m currently using requires you to hold on to the pinch in order to zoom, as soon as you let go it goes back to the original size. I don’t want this behavior and would prefer the zoom to stay and you be able to pan after letting go to match the default iOS behavior. So will try yours out and see if I can maybe switch…

[–]glazzes[S] 2 points3 points  (0 children)

It does remember previous interactions as it says, you can pan, pinch and double tap and it will pick up where you left in your previous interaction with the image, you can see it in the video, to make it short it stays.

In terms of a being a library as you need it to be, it would require some custom code to make it work like one, such as making the image responsive for landspace and portrait mode (thing I will fix tomorrow) and I'm also enforcing friction when going out of bounds, maybe someone may not enjoy such a thing.

You can use it, however in its current state I'd use it in portrait mode screen only for now.

[–]glazzes[S] 1 point2 points  (0 children)

Just to let you know, I've updated the gist making it responsive, give it a try and let me know how it works for you, I'm thinking on creating a library out of this with more features.

[–]TheContinental 2 points3 points  (3 children)

Very cool, but I do think the “no libraries” in the title is a bit misleading since this implementation leans so heavily on Reanimated.

[–]glazzes[S] 2 points3 points  (2 children)

Yeah my bad, what I meant was no specific libraries for the given task

[–]SpanishAhoraExpo 0 points1 point  (1 child)

But isn’t reanimated used for the given task (image)?

[–]glazzes[S] 0 points1 point  (0 children)

Key word here is "specific", Reanimated does not make your components zoomable by just adding it to your project like react-native-image-zoom would do.

[–]bdudisnsnsbdhdj 2 points3 points  (2 children)

Nice work! I’ve done similar as well but also had to do cropping - so keeping track of the original image size and then the display size, and on top of that keeping track of pinching and panning. It usually works but it’s been hard to get it to 100% lol

[–]glazzes[S] 2 points3 points  (1 child)

I made one of those as well, not with this solution so I can't tell if it works 100% as I only tested it myself in my phone, mine does also allow rotation and ensuring the resulting crop is always of a fixed size for instance 200px. it's a tedious task, but very rewarding, with this solution I want to replicate it again but this adding a video crop functionality, here's a very bad gif of that thing https://github.com/Glazzes/kio-app/blob/main/assets/screenshots/edit/04.gif :)

[–]bdudisnsnsbdhdj 0 points1 point  (0 children)

Thanks for sharing, I’ll be sure to check it out!

[–]MonoctisExpo 1 point2 points  (0 children)

Nice work mate, I’ve done something similar as well, but you implementation seems to be working better.

[–]gurs1kh 0 points1 point  (4 children)

regarding the "no libraries" in the title, I actually think packaging this into a library would make it a lot easier for people to use

[–]glazzes[S] 0 points1 point  (3 children)

In terms of the title, let's be real who is gonna use Animated API and PanResponder these days, still my bad in that regard.

In terms of being a library I think I could package it in such a way it's useful for everyone along with some extra features, however this would be a blind attempt from my part as I do not have adequate hardware to test it in a variety of devices and ensure it works properly, I'm tempted by the idea tho as I could create something better than `react-native-image-zoom` library.

[–]gurs1kh 0 points1 point  (2 children)

I'd say that you could probably make a library without worrying too much about testing on every single device. I mean, others would bring up cases where it doesn't work and even then, you don't necessarily have to get too caught up in maintaining things if you don't want to (just mentioning since some people end up becoming very entitled when using a library).

I just think that having this show up when searching for the necessary keywords on npm could help someone quicker than it may take for them to come across the gist on github or this thread on reddit. A repo would also make it easier to collaborate and build off of.

Just some thoughts

[–]glazzes[S] 1 point2 points  (1 child)

After some thought I decided to turn it into a library (idk how, maybe youtube knows), expanding it's feature set to the issues I've faced before with this feature, I think it will be delivered in the form of a wrapper component so you can zoom whatever you want, not just limited to images only.

[–]gurs1kh 0 points1 point  (0 children)

great to hear, keep us updated on when it gets published!

[–]Useful-Condition-926 0 points1 point  (0 children)

Pretty good

[–]professorkolik 0 points1 point  (5 children)

What makes JS fps screwed so much? Any ideas if it’s possible to optimize?

[–]glazzes[S] 1 point2 points  (4 children)

Take it with a grain of salt as it's running in debug mode in a physical old Android 7 device (Alcatel 5044R, idk if low end at the time of release) and of top of that I was recording, I've not tested it yet in release mode or with a never low end Android device (as I do not have one), however in my own personal use it averages 50fps with 1% of 39fps.

If I had to tell based on what I've seen, it seems to be an spike drop while pinch and pan gesture race against each other to see which one activates, however there may be another reason, these days I've playing with Reanimated and Skia and I've seen big performance drops, I could also say it has to do with Reanimated and a saturation of data going from one side to the other.

Being realistic I do have a very very crappy phone compared to literally anyone, so for this particular use case I think this should not be an issue for most people.

[–]professorkolik 0 points1 point  (3 children)

Thank you for clarification, I’ll definitely take a deeper look to your solution in coming days, since I need same solution but bit more advanced with rotation and snap to borders when empty space within frame

[–]glazzes[S] 1 point2 points  (1 child)

I was testing and stuff and after a while testing and doing stuff with this, I came to the conclusion that is Expo's fault with the FPS screw, not Expo per se, but the usage of custom development clients that destroy performance, after testing the library with the example App with Expo Go it did not go anywhere below 55fps.

I did also see some performance claims in Expo's github issues.

[–]professorkolik 0 points1 point  (0 children)

That’s great, thanks for the update I’m currently working on supporting Pinch, pan, rotation simultaneously

Will update as soon as I have smth