In this lesson we'll build a "tap to show love" animation. This technique is commonly used on many streaming sites to show the streamer they appreciate the content. When the screen is pressed an
Animated.Value will be created. We will measure the screen dimensions with
Dimensions so we can place our heart in a random location. Then we'll use
Animated.timing to animate the heart upwards. Finally a series of
interpolate will allow the heart to explode from nothing to full sized heart, wobble side to side, move upwards, and then fade out.
Let's take a look at the current state of our app. We have a constructor where we set up this.state which is hearts, with just an array. We have a handleAddHeart function, we have a touchableWithoutFeedback that will call that function.
We have a view where we can use the stylesheetAbsoluteFill, which will do an absolute position of left, top, right, and bottom of 0, so it covers the entire screen. Then we have a heart, this heart consists of a wrapping view with two heart shapes.
The heart is going to be 50 by 50, and the heart shape will be 30 by 45, and the left heart is just a piece that is rotated -45, and another piece that is rotated 45 degrees. We're going to need the current dimensions of the screen, and we can get that by saying const widthAndHeight which we'll destructure from the dimensions.getWindow() call.
Now down in our handleAddHeart, we'll say const animation = new Animated.Value which we'll set to 0, this will create a new animation every time we want to add a new heart.
Next, we'll call this.setState and because we'll be referencing state and we want to make sure that all of the setStates have flushed through, we'll pass a function into our setState which will receive the state at the time that we need it.
We'll then return an new object of hearts with our state.hearts in it, as well as the animation that we just created, and start, which will be a starting position along the bottom, and we'll just say getRandomInt(100) to width-100.
Finally, we need to start our animation, so we'll pass in a second function here, which will act as a componentDidUpdate, then we'll get our animated.timing and say animation, which is the animation for this particular heart that we just created.
Say toValue of our height, and then we'll say duration of 3000. Then we'll call start on our animation. What this will do is take our animation which starts at 0, which is an offset, and then animate it to a value of the height of the screen, so it will animate from the bottom to the very top.
Now that we have our animations being added to an array when we press stuff and start it, we now need to render them on the screen. We'll create a this.state.map.hearts.map which will take a function, and we will destructure our animation, and our starting position, and we'll also get the index.
From here, we'll return a heart, just add the key of our index. The heart's loading will consist of a series of animations. The first one is a position animation, so let's say const positionIntepolate = animation, and we'll interpolate on it, and say the input range is starting at 0 and going to the height, and we'll flip that around and say height-50.
It will start 50 pixels from the bottom up, because our heart is 50 pixels high, and it will go to 0. We'll then go set up our style, so get const heartStyle = transform, and here we'll say translateY, and put in our positionInterpolate.
Our second animation will be opacity, so we'll say const opacityInterpolate = animation.interpolate() and our input range will be 0 to our height-200, and our output range will be 1 to 0. This will allow our opacity to start at 1, and as it goes up it will fade out to 0.
We'll go ahead and add that tour style, so opacity, and we'll set our opacityInterpolate. The third will be the scale. The scale will cause our bubble, or our heart to bubble up very quickly and start from 0, and look like it emerged on the scene.
We'll do const scaleInterpolate = animation.interpolate() and the input range will be very quick, so it will be 0, 15, and 30. Our output range will be 0, 1.2, and 1, and we'll need to set extrapolate:'clamp'. What this will do is within 30 movements, we'll go from 0, the heart will grow to 1.2 times its size, and then back to 1.
If we did not have this extrapolate:'clamp', it would just continue on scaling the heart, so we'll then add that to our transform. We'll say scale:scaleInterpolate. The fourth and final will be a little wobble.
First, we'll divide, we want six wobble, so we'll say const dividedHeight = Height/6, then say const wobbleInterpolate = animation.interpolate(), and our input range will start at 0 and go to our dividedHeight1, dividedHeight2, dividedHeight3, dividedHeight4, dividedHeigh5, and our dividedHeight6.
That means we need an output range, so our output range needs to match the same amount as our input range, so we'll say 0, and we'll go 15 to -15, and it'll just wobble back and forth between 15 and -15.
We have 7 here including the 0, we have 1, 2, 3, 4, 5, 6, 7, and then here we will also add an extrapolate:'clamp'. With this wobbleInterpolate, we'll apply that to the translateX, translateX, finally we want a random start position. I'll say left and add in our start which is a random number that we created in the beginning, and now we can apply our style to our heart.
Now if we go and refresh our emulator and we tap on the screen, you can see it explodes from 0 and scales up, and the float and wobbles side to side. We can create a whole bunch of heats by just tapping on the screen.