What you'll learn:
delay
async
functionSee for yourself! Failed Unlock.
This animation happens in three stages.
Lock shakes
Lock shrinks
Text is revealed
In the App component, we have a <Padlock>
and Frames.
<Padlock animate={lockAnim} left={45} />
<Frame
color="white"
animate={textAnim}
background={null}
style={{ fontSize: 30 }}
overflow="hidden"
width={0}
>
<Frame background={null} width={400}>
Swipe up to unlock
</Frame>
</Frame>
Another <Frame>
holds our Swipe up to unlock
text.
Notice the overflow
of the first <Frame>
is set to "hidden"
and its width
is 0
.
<Frame
color="white"
animate={textAnim}
background={null}
style={{ fontSize: 30 }}
overflow="hidden"
width={0}
>
This combination of attributes is a nice trick to implement our reveal effect.
If we comment out <Padlock>
and change the Frame's width, we'll see more and more of the text.
width={200}
width={300}
width={400}
Therefore, if we animate the width, we’ll get a smooth reveal effect!
Let's uncomment <Padlock>
and reset the text's width
to 0
.
We’ve already created lockAnim
and textAnim
with useAnimation
with their corresponding animate
attributes.
function App() {
const lockAnim = useAnimation()
const textAnim = useAnimation()
return (
<Frame background={null} center>
<Padlock animate={lockAnim} left={45} />
<Frame
color="white"
animate={textAnim}
background={null}
style={{ fontSize: 30 }}
overflow="hidden"
width={300}
>
...
</Frame>
</Frame>
)
}
We simply need to start the animations at the proper times.
Right after our app launches, we want to start the animation.
function App() {
const lockAnim = useAnimation()
const textAnim = useAnimation()
lockAnim.start({x:-10})
return(
...
)
}
To add the shake, we don't have to animate the lock back and forth. Instead, we can customize the animation by defining a spring. By adding certain spring properties, the spring will provide the shake effect.
function App() {
const lockAnim = useAnimation()
const textAnim = useAnimation()
const spring = {
type: "spring",
stiffness: 500,
damping: 4,
restSpeed: 0.5
}
lockAnim.start({x:-10, transition: spring})
return(
...
)
}
After the lock shakes for a bit, we want to shrink it.
function App() {
...
lockAnim.start({x:-10, transition: spring})
lockAnim.start({scale:0.2})
return(
...
)
}
This scale animation happens a little too early. We can fix this by adding the delay
property.
function App() {
...
lockAnim.start({x:-10, transition: spring})
lockAnim.start({scale:0.2, transition: {delay: 0.5}})
return(
...
)
}
To make room for our text reveal, we'll set the origin of <Padlock>
to the left, using originX="left"
.
<Padlock animate={lockAnim} left={45} originX="left" />
Now, after the lock finishes shrinking, we want to reveal the text.
function App() {
...
lockAnim.start({x:-10, transition: spring})
lockAnim.start({scale:0.2, transition: {delay: 0.5}})
textAnim.start({width:400, transition: { duration: 1.5, ease: "easeOut" }})
return(
...
)
}
To play the text animation after the scale and to move our lock and text to the left, we have to utilize await
and async
!
We learned that to use await
we have to add async
before the function name.
async function App() {
const lockAnim = useAnimation()
const textAnim = useAnimation()
const spring = {
type: "spring",
stiffness: 500,
damping: 4,
restSpeed: 0.5
}
lockAnim.start({x:-10, transition: spring})
await lockAnim.start({scale:0.2, transition: {delay: 0.5}})
textAnim.start({width:400, transition: { duration: 1.5, ease: "easeOut" }})
return(
...
)
}
However, we get an error!
async
functions inside of componentsUnfortunately, we cannot make a React component become an async
function.
However, the fix is quite simple!
Let's create a function inside of App
and move our animation code inside it.
function App() {
const lockAnim = useAnimation()
const textAnim = useAnimation()
async function playAnimation(){
const spring = {
type: "spring",
stiffness: 500,
damping: 4,
restSpeed: 0.5
}
lockAnim.start({x:-10, transition: spring})
await lockAnim.start({scale:0.2, transition: {delay: 0.5}})
textAnim.start({width:400, transition: { duration: 1.5, ease: "easeOut" }})
}
playAnimation()
return(
...
)
}
Remember to call the function after defining it!
async function playAnimation(){
...
}
playAnimation()
return(
...
)
Everything seems to be working like before!
We can improve the animation by moving the lock and the text to the left a bit.
function App() {
const lockAnim = useAnimation()
const textAnim = useAnimation()
async function playAnimation(){
const spring = {
type: "spring",
stiffness: 500,
damping: 4,
restSpeed: 0.5
}
lockAnim.start({x:-10, transition: spring})
await lockAnim.start({scale:0.2, transition: {delay: 0.5}})
textAnim.start({width:400, transition: { duration: 1.5, ease: "easeOut" }})
lockAnim.start({ x: -50 })
textAnim.start({ x: -40 })
}
playAnimation()
return(
...
)
}
As a recap, to play an animation when our app launches, we write our animation code before the return
statement in the component function. If we want to use await
to sequence animations, we need to create an embedded function because the component function is not allowed to be async
.
Play around with the animation timing and add some new animations!
In the next post, we'll create the floating-action-button animation!