DEV Community

Cover image for Help Rocky Animate with Framer Motion
B3kay
B3kay

Posted on • Originally published at github.com

Help Rocky Animate with Framer Motion

Animation with Framer-Moton

Tutorial

In this tutorial, I've prepared a project in true 80's synthwave feeling. Now during Covid-19 times it feels like are working mostly remotely and from home to many of us skip training and we are becoming slaves under the control of Netflix and other streaming services.

But thanks to Rocky🥊 and a bunch of other ripped 80's action heroes we are going to repair an old workout generator that's gonna make us as buff as the heroes of that time!🦸‍♂️🦸‍♀️(<3 Stalone, Arnold, Dolph!) 💪

The problem with Rocky's workout-generator is that's it's not animating, and like your thinking right now, were gonna fix it with Framer-Motion

Let's do this

Framer Motion:

Framer-Motion API because that's where I started.

Framer motion is the magic component that we are going to use today. Its name is motion and it extends all the native HTML tags like div, a and ul etc.

We can give the motion just a few "props" to magically make the Framer-Motion API do all the animation in the background. It's also 3d optimized to use the graphics card on your computer to make it really smooth.

In this tutorial, we are going to use a specific prop variants to orchestrate the rendering and animation av elements in a list. An example from the API: https://www.framer.com/api/motion/examples/#variants

The repo

The documentation for this Tutorial can be found in Tutorial English
To get going with the Tutorial I've prepared this repo, just change the branch to Demo-ready and you can just follow along. Or find the repo here Animate-with-Framer-Motion.

The project is Bootstrapped with a simple CRA (Create React App) app that renders a Header, a slider to select the number of exercises and a switch to activate the training program. The app also has a few states and functions that we don't need to put any focus on for this tutorial.

App.js:

  • Header - Name of the app
  • Slider - Choose amount of exercises
  • Switch - Starts the workout
  • List - The list of exercises we need to repair(Animate).

Components we need to fix:

  • StaggeredList - The list rendering the listItems
  • ListItem - Each item in the list.

These components are already styled but you are free to do any changes you want. 😎

You can also take a look at this codesandbox:

1. Create a list

Let's begin with creating a list, for sake of convenience, we could create a list component and render 4 elements wrapped in a div.

import React from "react";
import { motion } from "framer-motion";
import { ListItem } from "./ListItem";

export const StaggeredList = () => {
  return (
    <div>
      {[1, 2, 3, 4].map((item, index) => (
        <ListItem exercice={item} index={index} key={item.xercice} />
      ))}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

2. Add motion

The magic of Framer-Motion comes in when we use the motion components. Change the div to a motion.div. ListItem is a styled component that we want to render in our list. It will show our services. Ithe ListItem takes 3 props, exercise, index, and key. Key is needed for React and framer-motion to give the elements a stable identity. Good when there is a change in one or more elements in the list.

Magin med Framer-motion kommer in när vi använder motion componenterna. Så vi kan göra om div till en motion.div.
ListItem är en för stylad komponent som vi vill rendera i listan och visa upp våra övningar i. Den tar 2 props, exercice, index och key. Key behövs för React men även framer-motion för att kunna komma ihåg element och correkt animera dem.

2. Animate list

The next step is to tell motion how we want it to handle its children. We want to tell the children we got two states, open and closed. Motion helps us with the transition if we just tell it the two points to transition between.

We do this by adding a variants prop to the motion components.
This tells the list of how to control its children. When the state changes to open we want it to wait for 0.5s before it's starts rendering its children. Then we want it to wait for 0.3s between the render of each child. The same when we close it. Though we want to do it a little bit faster, I think it looks better that way. Direction is which way to start removing children.

const variants = {
  open: {
    transition: { staggerChildren: 0.3, delayChildren: 0.5 },
  },
  closed: {
    transition: {
      staggerChildren: 0.05,
      staggerDirection: -1,
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

The list takes a prop telling when the switch was pressed, to know if to render the items or not in the Workout generator. In the animate prop to motion, we tell it if isOpen animate to open otherwise animate to closed. We also set the initial state to closed.

export const StaggeredList = ({ list, isOpen = false }) => (
  <motion.div
    variants={variants}
    animate={isOpen ? "open" : "closed"}
    initial="closed"
  >
    {[1, 2, 3, 4].map((item, index) => (
      <ListItem exercice={item} index={index} key={item.exercice} />
    ))}
  </motion.div>
);
Enter fullscreen mode Exit fullscreen mode

Now we're done with the list head over to the ListItem component!

3. Make listItem animate

List item looks like this, it is an item but we need to give it a few props to make it animate.

StyledMotion är endast en motion.div som jag stylat med Styled-Components.

export const ListItem = ({ exercice, index }) => {
  return 
    (<StyledMotion 
      index={index}
    >
      {exercice.exercise}
    </StyledMotion>);
};
Enter fullscreen mode Exit fullscreen mode

ListItem know the variants we added to the list component. What we need to do to animate this is to tell what the two states mean. What are variants of open and closed

To fix this we use the variants prop. Motion animate automatically between the most kind of values, opacity, scale, x, y, z, height, width, top left... More can be found here Supported Values

When the animation start I want the items to fade in and swoop in from the right. We do that by adding an opacity of 0 and moving the item a few pixels to the right with the x. When it's open we put it back to its default x position and opacity.

const variants = {
  open: {
    opacity: 1,
    x: 0,
  },
  closed: {
    opacity: 0,
    x: 150,
  },
};

export const ListItem = ({ exercice, index }) => {
  return (
    <StyledMotion
      variants={variants}

      index={index}
    >
      {exercice.exercise}
    </StyledMotion>
  );
};
Enter fullscreen mode Exit fullscreen mode

Finishing touches

If we test now it should animate 4 boring list items. So we need to go back to the List and tell it to render the workout-list instead.

We should now be able to see the exercises and change the number of exercises we want!

  • Let's get BUFF! 🥊🏆

If it doesn't work properly feel free to write an issue here in GitHub. 😘
You can also change the branch to demo-1 to see the finished result. The main branch has some extra goodies and just a WIP. Or head of to this live demo at netlify

Som extras! ☺

We can add some extra props to the items.
For example, we could change the scale onHover or tap by just adding a while over or whileTap prop.

  whileHover={{ scale: 1.1 }}
  whileTap={{ scale: 0.9 }}
Enter fullscreen mode Exit fullscreen mode

To add some extra sprinkles on the cake let's add an index prop. This has nothing to do with framer-motion, but we can also animate between style changes with styled-components.

index={index}
Enter fullscreen mode Exit fullscreen mode

All list items should now have an Epic 🌈 gradient!

HAPPY CODING! :)

Top comments (2)

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
b3kay profile image
B3kay

I'm so happy! Gradients just looks so gorgeous! :D 🌈