React-motion is a creditable library that makes it easy to create realistic animations within components using laws of physics. An endless possibilities of realistic animations can be explored by simply specifying values for stiffness and dampness within one of the exported components.
At first, these terms might not make so much sense to a person who’s just learning about this library, but at the end of this article, we will have discussed the meaning of these terms and looked at several use-cases where this library will prove applicable.
To follow along with the flow of this article, it is necessary that you have these tools installed on your computer:
- Node and npm
- Create-react-app (npm install -g create-react-app)
We will be showing all the use cases using the create-react-app tool.
Since this article focuses on showing how to use the react-motion library in React projects, it is assumed that the reader has at least a basic knowledge of React and a general understanding of JavaScript.
By the end of this article, we will have created several simple animation projects including this animated jumbotron revealer:
Before we start writing code and exploring any use-cases, it is imperative that we first discuss some of the basic properties of the react-motion library, so we understand it to a significant extent.
React motion exports three main components: Motion, StaggeredMotion and TransitionMotion.
Throughout this article, we will be working with the Motion component and we will see how to import it into our development environment and design creative animations. The kind of animations we will be making are called spring animations because they start at a defined value and spring towards the destination value.
Besides the start and finish values we just discussed, there are two other values we will be setting when creating animations. These values (variables) are: stiffness and damping. When starting out with creating these animations, it might not be visible what impact changing these values bring about, but these variables control the overall feel and structure of each animation.
That being said, let’s briefly define them below:
Stiffness defines how forcefully the object in an animation is pulled towards its final value.
Damping is the simulated friction the object will be subject to as it approaches its target.
Tweaking these values can bring about an overwhelming or subtle change to the entire animation.
Now that we have defined these terms, we can proceed to building a few projects to demonstrate relatable use-cases.
The first project we will be integrating react-motion into is a hamburger menu. This project isn’t difficult to build at all and can be built without writing a single line of JavaScript code. However, this tutorial aims at demonstrating how components can easily be animated in React.
Let’s begin by creating a new project using the create-react-app tool:
https://gist.github.com/6b455339705402f3459544d7d0aaa057
Now let’s navigate into the newly created directory and pull in the dependencies we need:
https://gist.github.com/121067c13a070bded937068100ada967
We are installing react-motion
because we need it to animate the movement of the side section that swings into the screen when the drawer is clicked upon.
We need styled``-``components
to create styled components within our application. Another perk with creating a styled component is that we are able to easily use props values from that component while styling, this already creates an infinite possibilities in animation since we can dynamically use the values of props to update the style of that component.
Let’s update the App.js
file, we will import the styled components package and use it to create a Wrapper
component. Lastly, we will render the Wrapper component and a Hamburger component that we are yet to define:
https://gist.github.com/f75f86f0388358ea6d60f7a0707944d1
Neatly done! Now let’s create a Hamburger.js file in the src directory:
https://gist.github.com/c8675c8ae9643372beb105bc0448ad16
In the Hamburger.js
file, let’s start laying out the general structure, we will start by importing the styled-components
and react``-``motion
packages. We also want to create two components using the styled components package. These components are Drawer
and Links
, the former will be the drawer section that slides into the focal region of the screen when we click the hamburger icon, while the latter will hold the links on the Drawer:
https://gist.github.com/c374ff7236e09d2dd9611f9bbc96c972
You might have noticed that we wrote ${(props)
*=>*
props``*.*``left}vh
while writing the styles for the Drawer
component, we did this so that the value of the left
property can be dynamic and updated as it updates in the component.
Now we can move further to defining and exporting the Hamburger
component. Within the Hamburger component, we want to register a constructor and call the super()
function. We also register a single state toggleState
which we will use to keep track of the state of the hamburger menu at any time. We will also include a method to handle the clicks on the hamburger icon.
https://gist.github.com/40ad466f3753e4b8f325ef00b93e7075
Now in the render
function, we will write some JSX code to define the structure of the application on the DOM. For the best part, we will register a Motion
component from the react motion library. The Motion component adopts the render prop pattern so it accepts some props and a function as its children and we pass in our Drawer
component to that function:
https://gist.github.com/629b89a35c697fcdb65af53ea67085f4
It can be observed from the code above that in the Motion component, we set an optional defaultStyle
to *left*``: -40
and then we set the style
to this long expression: *left*``: spring(``*this.*``state``*.*``toggleState ? 0 : -40, {``*stiffness*``: 210,
*damping*``: 10} )
What these two expressions mean are:
By default, set the left property (that automatically updates within the styled component) of this component to -40vh.
If the toggleState variable is set, then animate the component from its current left value (-40vh) to one of 0vh while applying a stiffness of 210 and a damping of 10. However, when it isn’t set, let it continue being equals to -40 (hence no animation)
We can run this application now to see just what we’ve built but we might be startled by the hideousness of its look! Let’s ass some CSS
to the App.css
file to give it a nice look:
https://gist.github.com/6a277be137ca8794ea08d8322e153298
Awesome stuff! We can run the application now by typing this command in the root directory of the project:
https://gist.github.com/f55af48c293d65e050e98f31e9ae5561
We will point our browser to http://localhost:3000 and get this screen:
The source code for this project is available here on GitHub.
Under this section, we will simulate the spinning of a preloader when some other action is running and needs time to complete before the user can get output. However, this is just a simulation so we wouldn’t tie the spinner to any larger application or process. We begin.
We can create a new application with this command:
https://gist.github.com/374bb241a6d50f21668d0028519be7b0
Let’s navigate into the working directory and install dependencies using these commands:
https://gist.github.com/3d98e833f31ee6304c99e5d1032c4150
We will be using styled-components in all of our projects because it makes everything easier.
Now we want to update the App.js
file, we will import the styled components package and use it to create a Wrapper
component. Lastly, we will render the Wrapper component and a Preloader
component that we are yet to define:
https://gist.github.com/f3c079107aa470e81a50317fb30a776c
We also need to give our application some information on how to reference the bootstrap package that we just pulled in, so we open the index.js
file and include this line to the list of imports *import*
'``*../node_modules/bootstrap/dist/css/bootstrap.min.css*``'
so it looks like this:
https://gist.github.com/77cd8888d8df78ca1dc5d25838773a99
We will create the Preloader.js
file in the src directory:
https://gist.github.com/12799235d5416186afced181b5cfc959
In the Preloader.js
file, let’s start laying out the general structure, we will start by importing the styled-components
and react``-``motion
packages. We also want to create a component — Loader — using the styled components package. This components will be the actual loader/spinner:
https://gist.github.com/233f52e8cae14082f18a177c15c2ff02
We wrote ${(props)
*=>*
props``*.*``transform}deg
while writing the styles for the Loader
component, we did this so that the value of the transform
property can be dynamic and updated as it updates in the component itself.
Now we can move further to defining and exporting the Preloader
component. Within the Preloader
component, we want to register a constructor and call the super()
function. We also register a two state variables:
- startLoader
- numberOfSpins
The application will use the startLoader
in deciding when to start the Loader, while the numberOfSpins
determines how many full circles the spinner does, for this project, we will set it to 5 by multiplying 360 by 5. Lastly we will include a simple function to switch the value of startLoader
from 0 to 1 to indicate that it should start the spinner on the click of a button:
https://gist.github.com/cfc4792f318347210aa15ef947991aaa
Now in the render
function, we will write some JSX code to define the structure of the application on the DOM. We will register a Motion
component from the react``-``motion
library. The Motion accepts some props and a function as its children and we pass in the Loader
component to that function:
https://gist.github.com/89b89e06c2298b6052e08bdfd913a5b1
The magic of this application lies in the section where we set an optimal defaultStle
to *transform*``: 0
and then set style
to *transform*``: spring(``*this.*``state``*.*``startLoader ?
*this.*``state``*.*``numberOfSpins: 0, {``*stiffness*``: 10,
*damping*``: 10})
.
In very basic terms, what these mean are:
set the default property of the transform property (that is bound to the Loader component) to 0
Whenever the
startLoader
state variable is set, do a transform to the set number of spins.
Before we run this application, we need to include some styles in the App.css
file:
https://gist.github.com/00a28d6e36624bef521e58922dadeb6a
We can run the application now by typing this command in the root directory of the project:
https://gist.github.com/3522c52f70d7f231ab18e7dba937cfc6
We will point our browser to http://localhost:3000 and get this screen:
Note: The spinner spins this way because we have set the stiffness and dampness to 10, you can tweak the animation to your taste by understanding the behavior of the stiffness and dampness properties from the earlier discussion and updating them adequately.
The source code for this project is available here on GitHub.
There’s hardly a person who has been on a mobile smart-phone or computer that would say he/she hasn’t seen a progress bar before. Progress bars are very important because they can communicate the status of a process to a user by showing the current length of the progress against the full-length of the bar. Let’s build our own simple progress bar using react motion:
https://gist.github.com/45cf0df48f0fe15cf39d855d630ac1b3
Let’s navigate into the working directory and install dependencies using these commands:
https://gist.github.com/1c9da9c1973ea152a7a03d9dab2b4005
Now we want to update the App.js
file, we will import the styled components package and use it to create a Wrapper
component. Lastly, we will render the Wrapper component and a Progress
component that we are yet to define:
https://gist.github.com/d77239bafa0289fa14f14e4b1280e38f
We also need to give our application some information on how to reference the bootstrap package that we just pulled in, so we open the index.js
file and include this line to the list of imports *import*
'``*../node_modules/bootstrap/dist/css/bootstrap.min.css*``'
so it looks like this:
https://gist.github.com/b86f80eef8b8b857f4a1794e2d85cede
We will go further and create the Progress.js file in the src directory:
https://gist.github.com/1458c6560c934dc632fc25ea8488bf4c
In the Progress.js
file, we will start by importing the styled-components and react motion packages. We also want to create a component — ProgressBar
— using the styled components package. This component will be the actual ProgressBar
, we will start the progress bar based on the state of a startProgress
state variable. We’d also set the stiffness and damping of the Motion component to 10:
https://gist.github.com/3966618aa855acb18bec1044d68a9397
We used the Math.trunc
function here to return the springed
width as an integer by removing the fractional digits.
Before we run this application, let’s add these styles to the App.css
file:
https://gist.github.com/d3b128615e626b3740b8fc78e23cab3b
We can run the application now by typing this command in the root directory of the project:
https://gist.github.com/5912dc1398f85ce5ae302132db384e19
We will point our browser to http://localhost:3000 and get this screen:
The source code for this project is available here on GitHub.
What’s better than being notified about the last interaction between a user and an application? You guessed it right! Being notified with a sliding animated notification in realtime. We will build a small login system that takes in a username and password then notifies the user on the status of his validation when he clicks on the Sign in
button.
https://gist.github.com/aa9653cb6f81a9a09ff938cce6d67b84
Let’s navigate into the working directory and install dependencies using these commands:
https://gist.github.com/55ad12ff56f8ecfd57461065ef97341f
Now we want to update the App.js
file, we will import the styled components package and use it to create a Wrapper
component. Lastly, we will render the Wrapper component and a Form
component that we are yet to define:
https://gist.github.com/05b5f334c414eb9de86125c8f81d28f1
We also need to give our application some information on how to reference the bootstrap package that we just pulled in, so we open the index.js
file and include this line to the list of imports *import*
'``*../node_modules/bootstrap/dist/css/bootstrap.min.css*``'
so it looks like this:
https://gist.github.com/362dabae4f1bd47aa0ee0ed9ca9132f5
Now let’s create a Form.js file in the src directory:
https://gist.github.com/08df28b18f7f6cc41b1d2acad032b7cb
In the Form.js
file, we will start by importing the styled-components and react motion packages. We will define a single component using styled component, this component would be called NotificationBox
. We will register a state — startAnimation
— that will decide when the animation starts and we will register two functions:
handleClick
— This function will handle click events on the ‘sign up’ button and call the other function so it resets the state ofstartAnimation
to 1resetValue
— This function will reset the state of thestartAnimation
variable.
https://gist.github.com/17135efdf487a474a69f3e58df3b246d
Within the render
function, we write some JSX code that defines the structure of the form then we register a Motion
component to animate the NotificationBox
component:
https://gist.github.com/92c884d17617188695f96d68f57fc8b0
As before, we have bound top and opacity properties of the component with it’s style so we get nice animations when the submit button is clicked. Let’s add the styles to the App.css
file:
https://gist.github.com/db10dcee5fde24d8cf41cd233d575fc5
We can run the application now by typing this command in the root directory of the project:
https://gist.github.com/9c977d4cc2b076ceba7f0dabd29d50e7
We will point our browser to http://localhost:3000 and get this screen:
The source code for this project is available here on GitHub.
We’ve looked at some basic examples so far, but now we’d look at something more complex, we are going to create an animated “jumbotron revealer.” In simpler terms, this is an application that displays a black screen on initial load then gradually reveals the jumbotron using react motion. Let’s get started.
We will create a new project:
https://gist.github.com/1f0904ee6fce4fbbcdad5cff5b38820d
We can navigate into this directory and install the dependencies:
https://gist.github.com/a6d12e1b7ab560716f36466dc73bce6e
Let’s make a quick edit to the App.js
file, we want to import styled-components
and also import ImageBoxAnimation
(which is a component we’d create very soon):
https://gist.github.com/246be0aac0f5e5b2f4d2f4d4df107306
We need to create two separate files for two components so let’s navigate into the src directory and create them:
https://gist.github.com/6656772a38ceb53b611615f568cbb865
Awesome! Now let’s open up the ImageBoxAnimated.js
file in our favorite editor and begin writing some code, the first thing we want to do is import the dependencies and the BlackBoxAnimated
component (though the file is currently empty) then create a new component using the styled components. The ImageBox
component will basically be a div
that loads a picture as its background image from the internet:
https://gist.github.com/128d7455863f8b7d333c7a58b81ef7bf
The next thing we will do is create the ImageBoxAnimation
component and set a single state variable — animationNumber — we need this state variable to decide when the black boxes that will initially cover the jumbotron will start to slide away.
We will also define a function — startNextAnimation — which serves the purpose of augmenting the animationNumber
that decides which box slides.
We will use the setTimeout()
function to call the startNextAnimation
function that increments the animationNumber
. Whenever a timeout runs, a new black box will slide (there will be about 10 of them by the completion of this project) across the jumbotron’s image.
In the render function, we will start by initializing an object { animationNumber }
to our application’s current state so that we can refer to it directly within the render function without having to call this
.
Next, we will register 10 instances of the BlackBoxAnimated
component and pass down three props to each one of them, these props are:
heightPercentage — This props is responsible for setting the height of each black box relative to the total height of the jumbotron. We will set it to 10% so that we have space for exactly 10 boxes
reverseDirection — This props takes a boolean value to decide in which direction the box should slide, because if all the boxes slide in one direction, then it would be visually boring. We will alternate between truth and false to give it a zigzag feel.
startAnimation — This props is very important because it is responsible for the cascading behaviour of the animation. It makes sure that the black boxes leave one at a time (because the setTimeout function gives a space of half a second before calling the
setNextAnimation
function which is responsible for increasing the value ofanimationNumber
by 1) by comparing its value against a number and returning a boolean value to theBlackBoxAnimated
component. Afalse
does nothing while atrue
starts the animation.
Finally, we will export the application:
https://gist.github.com/3344d87f1dbca17fbc154447edd97f7b
Now that that’s done, let’s open the BlackBoxAnimated.js
file we created a while ago and prepare it for the data that is being passed down by ImageBox
. We will start by importing the dependencies we’ll need, but this time we will also import PropTypes
*from*
'``*prop-types*``'
and this would help us confirm that our props are what we want them to be when they are being received. We will also define a Blackbox
component using styled components and populate it with some styles:
https://gist.github.com/12ef6ca0703c26d596020968d8daf7e5
We are using ${(props)
*=>*
props``*.*``heightPercentage}%
and ${(props)
*=>*
props``*.*``xDirection} center
because we want to bind these props from the component with the style properties.
Next, we will create the BlackBoxAnimated
component (you can define a component as a function in React) and define the props it should expect. We will register the Motion
component and trigger the animation only when startAnimation
has the value if true. Lastly, we will check that the props we received in the component are of the type we expected:
https://gist.github.com/11bb8f9c1fc2fdf0ec9d216fbbd22bac
Great, we can run the application now by typing this command in the root directory of the project:
https://gist.github.com/1c43023590c6b4149a3d54be00aab35a
We will point our browser to http://localhost:3000 and get this screen:
The source code for this project is available here on GitHub.
In this article, we have seen how to use react motion to create easy to tweak animations with React components, we have also come to understand the ideas behind the stiffness
and damping
variables that are available to us when using the library. Though the examples we have looked at in this tutorial mainly covered the basic sides to the library, but it’s a good start for anyone who hopes to build really complex and nice looking web animations with components.