React Native Animations Should Be Fun


Are you afraid of animations? Well, you shouldn't be, React Native Reanimated got you covered. Your mobile application can share a story through animations, can help users through micro-interactions and differentiate your app from the others.



Hey and welcome to this talk. I'm really nervous to be here in front of you. Not because I'll be giving a talk, but because I'll be talking about a subject which is really close to my heart and that's animations in react Native. And animations in general. You see I have applied with this talk because I see the struggle in this community, especially coming from newcomers that they would like to animate their static UI, but they don't know how to actually getting started with. But also from experienced developers that don't know how to level up their skills. So the goal with this talk and by the end of this talk, if you're a newcomer, you'll know how to animate your static UI, if you're an experienced developer, you'll look at things with different eyes or from different perspectives and I'll show you some tricks and tips that will definitely level up your skills. We're engineers or certain developers and we don't think that we understand something unless we can build it and this process I like to call it learning by doing. It's funny because a while ago I was doing a code application and I came by this amazing quote by my friend Aristotle and it's saying that for the things we have to learn before we can do them, we learn by doing them. I'm a self-taught developer and learning by doing is not a fun process. From time to time you'll struggle quite a lot, you'd like to give up and you feel that you know nothing about what you're doing, but it's okay, this itself is the learning process. There's a learning curve, but with incremental steps you reach the peak. Well that's because the best solution that you currently know is based on your existing knowledge and for you to expand that knowledge and learn new ways of doing it, you learn by doing it. The entire talk is going to be around reanimated or react Native reanimated and I believe that this library, react Native reanimated is going to empower you with amazing tools and capabilities so you can create delightful experiences really fast, easy and performant. I believe that reanimated opens the gates for creating amazing animations, it eliminates a lot of roadblocks and is solving 99% of performance issues and is going to let you focus more on things that matters the most and that's creating pleasant illusions through animations and increasing user experience. My name is Catalin Miron, I'm currently helping others to succeed, you can follow more about my work, you can follow me on Twitter using Miron Catalin as Twitter handler. So let's start by setting up the ground foundation of this entire talk and start talking about reanimated primitives which I believe are the most critical ones to master eventually. The first and by far the most important one is use shared value. Shared values can carry data and provide a way to react to changes and also drive the animation and it's also important that it's reactive. This data is stored on the UI thread but can be also accessed from the javascript side as well hence the name shared. It can be a number, it can be a boolean, a string, an object, an array. Use derived value is when you'd like to create a new value based on a shared value. In this example I'm just adding 100 to an existing shared value so whenever that value is going to change this derived value is going to change as well. Use animated style, it's used when a style attribute will need to update based on a shared value or this style attribute depends on a shared value. In other words it's a reactive style sheet. The counterpart of use animated style is use animated props but yeah for non-style attributes. In this example I'm animating a stroke width but I can also do it for a path. Interpolate is going to let you remap values based on an input range and output range. You can also have interpolate color is the same as interpolate but for colors as output ranges. In this example I'm morphing between red and blue. Of course you can animate those shared values by using timing, spring and decay. You can delay those animations, you can repeat those animations, you can sequence them or go crazy, you can repeat reverse a sequence of animations with an initial delay. If you're using gesture handler you can also listen to some events by using use animated gesture handler or if you're using scroll view or flat list or any scrolling components you can use animated scroll handler and listen to those events and if you're just interested in the on scroll event you can use the shorthand notation and just get directly the event that's coming from that on scroll event. Last but not least is use animated reaction. It's useful if you'd like to set state or call some APIs or do something else on the javascript side and how it's actually using it's receiving two different methods, one is for the preparation, it's informing the animated reaction what shared value it's interested in and the reaction of that is going to receive the result and the previous value and you can do whatever you'd like to do. Now that we have set up the ground foundation and what are the most important primitives in my opinion that reanimated exposed now let's talk what matters the most when coming from outside world or you'd like to animate something. In my perspective the most important one is interpolate. Interpolate is a function that will remap an animation value from an input range to an output range and yeah it's a method, it's going to accept a shared value, it's going to accept an input range, output range, extrapolate left and extrapolate right and in case those two extrapolations are equal you can use the shorthand notation and pass back to the extrapolation. This is optional and by default the extrapolation it's extend and you'll see in a minute what extend actually means. Let me give you an example. I have here a component, I'm initializing a use shared value starting from zero. I'm animating that shared value whenever this component is going to be mounted. The fancy animation and I'm applying some styles by using use animated style and interpolating that value I'm passing an input range zero and one and the output range zero and 100 and I'm applying it to a translate X. Finally the most important part is to add those styles to an animated view or animated component and this is how it's going to look like. X is going to move from zero to one and the interpolated value or the translate X in our example is going to move from zero to 100. You see when I'm dealing with interpolations I would like to represent them visually in my head as a graph. So let me give you a sense of how that graph may look like in my head. So for the input range I have a line with different values in our example zero and one and for the output range I'll have another line from zero to 100 and yeah in a nutshell whatever we have written in code in my head it's this graph here and interpolate is trying to estimate the numbers between those two ranges and as I mentioned previously the extrapolation by default it extend that means that interpolation can estimate the numbers outside of or beyond those ranges. So in case when the input range or the value itself is going to be two the estimated value is going to be 100. If you're not interested in outside world of this range you can clamp the animations or you can clamp it on the left or clamp it on the right. The next problem which a lot of us are confused about or don't get it right initially is the index minus one, index and index plus one problem which it's going to be applied when you'd like to animate some things inside the carousel or in a horizontal or vertical list. Let me give you an example. So I have here a flat list that's horizontal and it's going to have paging enabled and I'm rendering a carousel item. Nothing too fancy here. So this is how it's going to look like, right. Because I have paging enabled is going to snap on each individual carousel item because each item has the screen width size. And how we can actually animate those? Well the first thing that you need to do is to initialize the scroll X in our example because it's a horizontal list as a shared value. Create the on scroll using use animated scroll handler and modify the scroll X based on the event that's coming on that listener. And finally change the flat list to be an animated flat list, add the on scroll event and now pass the scroll X to the carousel item. And nothing should be visibly changed but now each carousel item has access to the scroll X position. And what we can actually do with that? Well we can interpolate the value and apply some style changes. In this example I'll apply a different opacity but the most important part to pay attention to is the interpolate. So because we have access to the index and the scroll X we have this formula kinda. So let's take a closer look to the interpolate method here. So we have an index minus one multiplied by the width, index multiplied by the width and index plus one multiplied by the width. Well index minus one is actually the next item or the item that's coming or moving to the right. The index plus one is the previous item or the item that's going or coming from the left and of course the index is the current value. So it's exactly the opposite way of thinking kinda. Now of course since we are in a reanimated world we can apply math and we can divide it by the carousel item width and just clean up the code. So we'll have an interpolate with an input range index minus one, index and index plus one. The value should be visible again because we will have the active carousel item index as a shared value. You're not limited to just a single style change. In this case I'm applying a different scale based on the scroll X position but you can of course use interpolate color and apply a different color for each individual item based on where it's going to go to. So if it's going to left I'll be applying magenta, if it's going to the right I'll apply gold and notice that everything is running at 60 FPS or 120 FPS depends on your device capabilities but everything is running on the UI thread which makes this, yeah really performant. Last is what I would like to call it an interpolation exam and when you know how to do sticky. What I mean by sticky is the following. So there are three types of sticky. It's a sticky after when the sticky element top edge is equal to the viewport top edge or sticky before when the top edge of the element is the top edge of the viewport and sticky bottom, it's sticky initially but when the bottom edge of the sticky element which is the bottom edge of the viewport is going to move along with the scroll. Just before moving further you need to understand two different things. The first one is the position of the item is always moving in relation to the scroll viewport that's because the item is relatively positioned not absolute positioned and the second one it's important to find when the sticky element is visible inside the screen or inside the viewport either using a top edge or a bottom edge. We have a scroll view here and I'm just rendering a sticky element randomly positioned inside the scroll view otherwise it's just a dummy element and for the first example I'm getting the Y value, basically the Y position inside that scroll for this sticky element and I'm interpolating the scroll Y and it's saying when the top edge of the element is reaching the top edge of the viewport I'm compensating the movement by one. You see by just passing the input range and the output range I'm basically specifying the range that I'm interested in and for shaping this movement and interpolate is going to do the rest of the estimations. Now let's see, let's take a look at the graph which I have also presented in the previous slides. So, as you can see I'm just specifying three different parts where I'm interested in and the rest is calculated by the interpolate method. Yeah, I'm just leaving everything in the hands of interpolate to do the estimation of the values. The next one it's basically the same but this time I'm moving the item by offsetting it with its minus Y position so it's always going to be visible right at the top but when the top edge of the element is going to reach the top edge of the viewport I'm going to move it with the scroll. I'm also adding a minus 1 and 0 just because on iOS for example you have bounces so you can move below minus 1 with the scroll Y value. So yeah again this is how the graph is going to look like. I'll just specify the range that I'm interested in and the rest is going to be calculated by interpolate method. Last it's sticky bottom. It's basically the same as sticky before the only trick here is that I'm calculating the initial position of the item. In this case I'm compensating with its minus Y so it's at the top then I'm adding the screen height. Now it's at the bottom and I'm subtracting its height so it's always visible at the bottom of the screen. And notice that there is a scroll Y value and the reason for that again is the item is positioned relative is not absolute so I need to always compensate the scroll Y position and it's just a matter of finding the sweet spot where this item is going to be visible or this interpolate method it's basically saying be sticky until the item is fully visible on the viewport. Next, it's fluidity or how we can actually create some animations using math or how to create this natural movement and for example purposes I'll be using arc tangent. It's a math formula that's going to give you an angle between two different coordinates. So I have this example, right, I have a ball that's randomly moving on the screen and I have some arrows that are pointing to that ball and let's see how this is actually going to look like in code. So each individual arrow is going to receive XY of the ball which are shared values and it's also going to integrate its own XY using the onLayout event and I'm applying a different style and I'm applying a rotation in degrees and this rotation in degrees or the angle is calculating using this formula. So let's take a deeper look at this formula. So again I'm taking the arrow Y minus ball Y, arrow X and ball X which is going to give me the angle in radians and I like to convert them in degrees and I'm also adding 90 degrees and the reason for 90 degrees is because the arrows are pointing down or vertically and I would like to start them from zero. Usually when doing trigonometry and yeah I would like to start everything from zero, in my case it's OX. So yeah this is how it's going to look like whenever the ball is going to change the arrow is going to point to that ball and just bear in mind that there are 220 different arrows pointing to this ball running at 60 FPS and doing the math there are roughly around 14,000 calculations per second and still everything is going to run at 60 FPS which is mind-blowing. A while ago I have created this pretty nice balloon slider animation and since then I have never seen anyone that has recreated it the way I was doing it. Usually they were just hard coding the angle but I'll show you how to apply the same formula and create a natural movement of this balloon. So we have a balloon indicator is going to take, is going to receive the X value of the knob as a shared value and is going to use the same formula but this time the arc tangent is calculated differently because the indicator height or the indicator position it's always going to be the same no matter the X position I will always hard code it and yeah this is how it's going to look like. You'll notice that nothing it's actually kind of working, right and the reason for that is the X value. X value it's instantaneous. So there should be a way to delay it but naturally and the way to do it we can springify that X value so we can apply a width spring of that value so we can recalculate the arc tangent using the springify value minus the current value so we can apply a yeah natural delay and of course apply to the translate X and a quick tip here if you'd like to reuse the same logic for different style attributes let's say in our example translate X and the rotation please move everything to a user a value otherwise from time to time I end up with sluggish animations yeah just a quick tip here and this is how it's going to look like just bear in mind everything it's calculated on the fly using math so no hard-coded angles the same principle it's applied here each letter it's aware of the knob position it's going to calculate everything using the same exact formula and it's also going to scroll inside the list next up it is layout animations with layout animations you can do mount and unmount animation using entering and exiting on an animated component there are 78 pre-built animations in reanimated to like fading or zoom in or bounce out you name it and each individual animation has some you can apply different modifiers like a duration duration with other modifiers like a delay you can randomly delay you can springify springify it mass and stiffness and just to give you an example here I'm toggling between two different elements using entering and exiting or based on a state and first time fade in with fade out I zoom in with zoom out I can slide in left to it's like outright I can also go crazy so as you can see it's really easy to use those pre-built they are really nice to create some delightful animations especially around mounting and unmounting and having those pre-built is really nice just to give you a quick real world example I have recreated the Beast by Dre application and I am just using layout animation here and mounting and unmounting of and position the headsets and the text and everything and reanimated was doing pretty much the entire heavy lifting here for me the second part of layout animations is the layout animation itself by providing the layout property it's it's mind-blowing how how nice things are animated or what you can actually create and I'm more besides the layout calculations like XY width and height you can also create this hero animation or shared element transition animation by specifying the same key for each individual animated view in this case I have the key my box applied two different views and I'm toggling based on mounting and unmounting and yeah reanimated by by just applying the layout animation reanimated was doing the heavy lifting here for me it was transitioning those two different views it was calculating how that view may look like if it's toggling or toggled or not so yeah it's it's mind-blowing how easy it is last I would like to discuss about multi this is a tiny a powerful library for react native animations it's powered by reanimated and it's going to help you animate style properties really really simple and by far is the best library for performing micro interactions how this is actually working you just need to pass a set of initial styles and a set of final styles and in case you'd like to mount and unmount you can pass the exit styles as well and yeah it's declarative and what is going to do all the heavy lifting for you in this case moving from past in 0 to opacity 1 or if you like to rely on upstate change and modify this or animate your view you can directly pass the animate and toggle the opacity in our example you can change or alter the transition passing the type spring or type timing you can specify a different duration a different delay you can repeat repeat reverse loop the animations also play around with colors by specifying background color and multi is going to is smart enough to figure it out that's going to be color animation is going to use interpolate color underneath or you can do multiple styles like we've translate why and background color and multi is smart enough again to match individual style and apply a different transition last it's about sequence in this case I'm translating from X 0 to 150 150 and 0 I'm a huge fan of multi I have built tons of animations UI animations micro interactions and I can totally tell you that it's fun to use and it's really really effective and it is going to create that wow factor which a lot of users are looking for especially inside the mobile application and by the way if you'd like to have access to all the examples which I have showcased during my talk but to also 100 different others is the example that are including math or animated api reanimated gesture handlers and lots lots of things and solutions to problems which I've encountered during my react native development time don't hesitate to become a patron by following the link from from the screen here and in closing don't forget that the best solution that you're currently aware of or know it's based on your existing knowledge and for you to expand that knowledge and do it in different ways you need to learn it by doing it peace
28 min
24 Oct, 2022

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic