29

React at 60fps — Building a Medium-Inspired Zoom with React-Pose

 4 years ago
source link: https://www.tuicool.com/articles/aAbu2qR
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

What I will be building

You might have noticed that Medium has a pretty great image preview UI and this is what I will be implementing today:

77vY3e7.jpgbU36rmY.gif

And if you would like to see my final implementation of if, this is it:

aUBfYzr.jpg73m2Av3.gif

Tip: Use Bit ( Github ) to easily share and reuse your React components between your apps, and build faster as a team with a shared component hub.

Picking React & React-Pose

I decided to go with react for this one. The algorithm could be easily ported to Angular, Vue or even pure web components but I think React is the main web standard at the moment.

J3mMbuU.png!webbeIV3yi.png!web

In terms of the transitions, I don’t think this type can be easily done with CSS, so I needed to pick between JS animation solutions for React and decided to go with react-pose as I already used it before and it’s a pretty great library which is also available for other libraries and pure JS.

A3YZ7ny.png!webqAVVr2y.png!web

Implementation

Now, let’s get started. Firstly, I created a simple image component that just allows you to toggle zoom on press, but doesn’t cause any visual changes.

FvYneqa.png!webJjeM73A.png!web
Just a simple image component

Then I can simply switch the <img> tag with a posed.img . When the image is in it’s normal state, it should have a static position, width matching the parent and the height adjusted to its aspect ratio. The difference between that and the zoomed state is that when zoomed, the position should be fixed.

VrQjei2.png!webvER3ee6.png!web
AfQZ3mV.png!webq6BBNnQ.png!web

React-pose allows you to pass the current “pose” state to tell it which state should be rendered on the screen.

YJFBjyM.png!webVRRz2eM.png!web

I also added some styles so that the cursor suggests that you can zoom in/out.

JvAbq2F.png!webzUfmEzY.png!web

And this simple implementation shows very promising results:

VreUJbF.jpgJnY7NnA.gif

However there are still things that need to be fixed. Firstly, if the image has an odd aspect ratio the zoomed image is stretched. To fix this, I need to make sure that the original aspect ratio is kept. Before doing that however, I will just add an utility hook that allows me to create event listeners.

eQnEbeM.png!webyM3yU3n.png!web

I also decided to make the transition key frames closer to the medium transition. The important change however is to the width and height of the zoom state, where it will allow to specify whether the image has a full width or full height.

YBfqaab.png!webVbmUZvJ.png!web

Now, the most important change. Firstly, I added a ref element to the image and another boolean state variable called fullWidth . This is used in the updateSizing function in order to check the size of the image and tell us whether the image has to be stretched vertically or horizontally. This updates when the image loads or the user changes the size of the browser (e.g. changes phone rotation, goes fullscreen, etc). I also implemented a feature allowing the user to scroll to unzoom the image.

Y3iMNn7.png!webuEfQ3mm.png!web

And here is what this looks like:

M3M3QrA.jpgRjiYraq.gif

As you can see, the issue with the odd scaling has been resolved, but we still see the content below the image shifting up. The solution to this, is doing exactly what the developers at Medium did, which is blank out the background.

yiEnUvq.png!webJrUBfqV.png!web
iAfiAvu.png!webAvIfIfi.png!web
uMjAnaR.png!webBZVjiyB.png!web

And it’s all done, we did it You can find a live demo right here:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK