Categories
React

Framer Motion — Exit Animation and Staggering Animations

With the Framer Motion library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with Framer Motion.

Exit Animations

We can add exit animation with Framer Motion.

For example, we can write:

import React from "react";
import { motion, AnimatePresence } from "framer-motion";

const image = {
  src:
    "https://i.picsum.photos/id/23/200/300.jpg?hmac=NFze_vylqSEkX21kuRKSe8pp6Em-4ETfOE-oyLVCvJo"
};

export const Slideshow = ({ image }) => (
  <AnimatePresence>
    <motion.img
      key={image.src}
      src={image.src}
      initial={{ opacity: 0, y: 200 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
    />
  </AnimatePresence>
);

export default function App() {
  return (
    <>
      <Slideshow image={image} />
    </>
  );
}

We use the AnimatePresence component to enclose the motion.img component to show animation on the image when it’s being unloaded.

We set the inital and animate props to set the starting and ending styles respectively.

And we have the exit prop to set the style to show after animating.

Mount Animations

We can add animations when the component mounts when we set initial to false and we the animate prop.

For instance, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <>
      <motion.div
        style={{ backgroundColor: "red", width: 100, height: 100 }}
        animate={{ x: 100 }}
        initial={false}
      />
    </>
  );
}

to move the div 100px to the right when we mount the App component.

Propagation

If motion components have children, then changes in variants will be flown down through the component hierarchy.

For example, if we have:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  const list = {
    visible: { opacity: 1 },
    hidden: { opacity: 0 }
  };

  const item = {
    visible: { opacity: 1, x: 0 },
    hidden: { opacity: 0, x: -100 }
  };

  return (
    <motion.ul initial="hidden" animate="visible" variants={list}>
      <motion.li variants={item}>foo</motion.li>
      <motion.li variants={item}>bar</motion.li>
      <motion.li variants={item}>baz</motion.li>
    </motion.ul>
  );
}

We animate the ul and li with the motion.ul components.

And we set the variants to set the styles for stages of the animation.

The initial prop has the initial style values of the animation.

And animate has the name of the style that’s applied at the end of the animation.

Orchestration

We can set delays in various parts of the animation.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  const list = {
    visible: {
      opacity: 1,
      transition: {
        when: "beforeChildren",
        staggerChildren: 0.3
      }
    },
    hidden: {
      opacity: 0,
      transition: {
        when: "afterChildren"
      }
    }
  };

  const item = {
    visible: { opacity: 1, x: 0 },
    hidden: { opacity: 0, x: -100 }
  };

  return (
    <motion.ul initial="hidden" animate="visible" variants={list}>
      <motion.li variants={item}>foo</motion.li>
      <motion.li variants={item}>bar</motion.li>
      <motion.li variants={item}>baz</motion.li>
    </motion.ul>
  );
}

We add the list object to stagger the animation of the li elements with the staggerChildren property in the visible stage.

Then when property sets the stage when the staggering is applied.

Conclusion

We can add animation when our component unmounts and tweak our animation in various ways with Framer Motion.

Categories
React

Framer Motion — Drag and Scroll Progress

With the Framer Motion library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with Framer Motion.

Drag

We can add drag and drop into our React app with Framer Motion.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <>
      <motion.div
        drag
        dragConstraints={{
          top: -50,
          left: -50,
          right: 50,
          bottom: 50
        }}
        style={{ backgroundColor: "red", width: 100, height: 100 }}
      />
    </>
  );
}

to make a draggable div.

We add the drag prop to make the div draggable in all directions.

And we add the dragConstraints prop to constrain the positions that the div can be dragged to.

MotionValues

We can use MotionValues to track the state and velocity of all animation values.

For example, we can write:

import React from "react";
import { motion, useMotionValue, useTransform } from "framer-motion";

export default function App() {
  const x = useMotionValue(0);
  const background = useTransform(
    x,
    [-100, 0, 100],
    ["#f4fc03", "#ced41c", "#d4bb1c"]
  );

  return (
    <motion.div style={{ background }}>
      <motion.div
        drag="x"
        dragConstraints={{ left: 0, right: 0 }}
        style={{ x }}
      >
        <div x={x}>foo</div>
      </motion.div>
    </motion.div>
  );
}

to show a different background when we drag the ‘foo’ text across the screen.

We do this by using the useTransform hook with the useMotionValue hook to create the value to track.

useTransform takes the value to track as the first argument.

The 2nd argument has the position to drag to.

The 3rd argument has the color for that’s displayed when we drag the ‘foo’ text.

The x MotionValue is applied by setting the x property of the style prop of the div .

We do the same with the div.

And we add the drag and dragConstraints to enable dragging and set the location that we can drag to.

We set left and right to 0, so we bounce the ‘foo’ text back to its original position.

We set the background property in the style prop of motion.div to set the background.

Viewport Scroll

We can watch for viewport scroll progress and animate content accordingly.

For example, we can write:

import React, { useEffect, useState } from "react";
import {
  motion,
  useSpring,
  useTransform,
  useViewportScroll
} from "framer-motion";

export default function App() {
  const [isComplete, setIsComplete] = useState(false);
  const { scrollYProgress } = useViewportScroll();
  const yRange = useTransform(scrollYProgress, [0, 0.9], [0, 1]);
  const pathLength = useSpring(yRange, { stiffness: 400, damping: 90 });

  useEffect(() => yRange.onChange((v) => setIsComplete(v >= 1)), [yRange]);

  return (
    <>
      <svg
        className="progress-icon"
        viewBox="0 0 200 200"
        style={{ position: "fixed", top: 0, left: 50 }}
      >
        <motion.path
          fill="none"
          strokeWidth="5"
          stroke="green"
          strokeDasharray="0 1"
          d="M 0, 20 a 20, 20 0 1,0 40,0 a 20, 20 0 1,0 -40,0"
          style={{
            pathLength,
            rotate: 90,
            translateX: 5,
            translateY: 5,
            scaleX: -1
          }}
        />
        <motion.path
          fill="none"
          strokeWidth="5"
          stroke="green"
          d="M14,26 L 22,33 L 35,16"
          initial={false}
          strokeDasharray="0 1"
          animate={{ pathLength: isComplete ? 1 : 0 }}
        />
      </svg>
      <div>
        {Array(100)
          .fill()
          .map((_, i) => (
            <p key={i}>{i}</p>
          ))}
      </div>
    </>
  );
}

We add the svg with a circle and a checkmark.

The pathLength will increase as we scroll down.

This is because we used the useViewportScroll hook to watch the scrollYProgress .

Then we use the useTransform hook to watch that and create the yRange object.

We call setIsComplete when the yRange value changes so so that we only show the checkmark when we scroll to the bottom.

The first motion.path has the circle. We increase the pathLength as we scroll down to show more of the circle as we scroll down.

The 2nd motion.path has the checkmark, we only show this when isComplete is true .

We scroll all the way down to make isComplete true .

Conclusion

We can add drag and drop and track scroll progress with Framer Motion.

Categories
React

Framer Motion — Keyframes and Gestures

With the Framer Motion library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with Framer Motion.

Animation

We can use the animate prop to specify how to animate an element.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <motion.div
      style={{ backgroundColor: "red", width: 100, height: 100 }}
      animate={{ scale: 2 }}
      transition={{ duration: 0.5 }}
    />
  );
}

We set animate to { scale: 2 } to double the size of the div.

The transition component is set to { duration: 0.5 } to set the duration of the animation in seconds.

Keyframes

We can add keyframes to create more complex animations.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <motion.div
      style={{ backgroundColor: "red", width: 100, height: 100 }}
      animate={{
        scale: [1, 2, 2, 1, 1],
        rotate: [0, 0, 270, 270, 0],
        borderRadius: ["30%", "30%", "50%", "50%", "40%"]
      }}
    />
  );
}

We add the scale property to set the quality to scale the div by in each frame.

rotate sets the rotation of the div in degrees in each frame.

borderRadius sets the border radius of the div in each frame.

Each entry an array is a quantity in a frame.

Variants

We can set predefined visual states in which a component can be in.

For instance, we can write:

import React, { useState } from "react";
import { motion } from "framer-motion";

const variants = {
  open: { opacity: 1, x: 0 },
  closed: { opacity: 0, x: "-100%" }
};

export default function App() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsOpen(!isOpen)}>toggle</button>
      <motion.nav animate={isOpen ? "open" : "closed"} variants={variants}>
        <p>foo</p>
      </motion.nav>
    </>
  );
}

to add animation when we toggle click on the toggle button to toggle the nav on and off.

The variants object have the style that the motion.nav can be in in different animation stages.

If it’s open , then opacity is 1, and x is 0.

And if it’s closed , then opacity is 0 and x is '-100%' .

Now we should see the ‘foo’ text move when we click on toggle.

Gesture Animations

We can listen to various gestures and animate elements when various gestures are applied.

For instance, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <>
      <motion.div
        whileHover={{ scale: 1.1 }}
        whileTap={{ scale: 0.9 }}
        style={{ backgroundColor: "red", width: 100, height: 100 }}
      ></motion.div>
    </>
  );
}

to listen for hovers with the whileHover prop.

And we listen to taps with the whileTap prop.

Then we set the scale to change the size of the div when those gestures are applied.

Conclusion

We can add complex animations with keyframes, and animate when gestures are applied with Framer Motion.

Categories
React

Framer Motion — Animations and Gestures

With the Framer Motion library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with Framer Motion.

Motion Components

We can add motion components to add elements that we can animate.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <div className="App">
      <motion.div
        animate={{ scale: 0.5 }}
        style={{ backgroundColor: "red", width: 100, height: 100 }}
      />
    </div>
  );
}

to create a div that shrinks to half of the size that is specified in the style prop.

scale set to 0.5 does the shrinking with animation.

Animation

The animate prop lets us animate an element.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  const variants = {
    hidden: { opacity: 0 },
    visible: { opacity: 1 }
  };

  return (
    <motion.div
      initial="hidden"
      animate="visible"
      variants={variants}
      style={{ backgroundColor: "red", width: 100, height: 100 }}
    />
  );
}

to create a div with the motion.div component.

And we animate from opacity 0 to opacity 1.

The initial prop has the name of the initial state of the div.

animate has the name of the style of the div after the animation.

The variants prop has the variants object, which specifies the animation style for each state.

Gestures

Framer Motion can direct hover, tap, pan and drag gestures automatically.

So we can do things to an element when these gestures are applied.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <motion.div
      drag="x"
      dragConstraints={{ left: -100, right: 100 }}
      whileHover={{ scale: 1.1 }}
      whileTap={{ scale: 0.9 }}
      style={{ backgroundColor: "red", width: 100, height: 100 }}
    />
  );
}

to let us drag the red div horizontally with the drag and dragConstraints props.

drag set to 'x' lets us drag horizontally. And dragConstraints lets us drag within the given bounds.

left sets the left limit and right sets the right limit.

whileHover has the style to change when we hover over the div.

whileTap lets us change the style when we tap on the div.

MotionValue

We can set motion values to set the style we want.

For example, we can write:

import React from "react";
import { motion, useMotionValue, useTransform } from "framer-motion";

export default function App() {
  const x = useMotionValue(0);
  const opacity = useTransform(x, [-200, 0, 200], [0, 1, 0]);

  return (
    <motion.div
      style={{ x, opacity, backgroundColor: "red", width: 100, height: 100 }}
      drag="x"
    />
  );
}

to let us animate the red div by changing the opacity when we drag it.

The useMotionValue prop creates a reactive property to watch form.

x is the horizontal position of the div.

The 2nd argument is the distance values.

And the 3rd argument is the opacity values that correspond to the distance values in the 2nd argument.

Conclusion

We can add basic animations with size and opacity changes and drag and drop effects with Framer Motion.

Categories
React

Add Animation to Our React App with the Framer Motion Library

With the Framer Motion library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with Framer Motion.

Installation

We can install Framer Motion by running:

npm install framer-motion

Getting Started

We can create a div that moves by writing”

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <div className="App">
      <motion.div
        animate={{ x: 100 }}
        style={{ width: 100, height: 100, backgroundColor: "red" }}
      />
    </div>
  );
}

We set the animate prop to an object with the x property to move it horizontally.

Draggable Element

We can make an element draggable by using the drag and dragConstraints props.

To use them, we write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  return (
    <div className="App">
      <motion.div
        drag="x"
        dragConstraints={{ left: -100, right: 100 }}
        style={{ width: 100, height: 100, backgroundColor: "red" }}
      />
    </div>
  );
}

We set drag to 'x' to let us drag and div horizontally.

And we add the dragConstraint prop to let us drag left 100px to right 100px.

We can animate lists by using the motion.ul and motion.li components.

For example, we can write:

import React from "react";
import { motion } from "framer-motion";

export default function App() {
  const list = { hidden: { opacity: 0 } };
  const item = { hidden: { x: -10, opacity: 0 } };

  return (
    <motion.ul animate="hidden" variants={list}>
      <motion.li variants={item}>foo</motion.li>
      <motion.li variants={item}>bar</motion.li>
      <motion.li variants={item}>baz</motion.li>
    </motion.ul>
  );
}

We set the variants prop to objects to let us hide the elements with various styles.

animate is set to hidden , which is the name of the animation.

We set the opacity to 0 to hide the items.

The x property is set to -10 to move the li elements 10px to the left.

We can combine drag and drop with animation by using various hooks that comes with Framer Motion.

For example, we can write:

import React from "react";
import { motion, useMotionValue, useTransform } from "framer-motion";

export default function App() {
  const x = useMotionValue(0);
  const opacity = useTransform(x, [-100, 0, 100], [0, 1, 0]);

  return (
    <motion.div
      drag="x"
      style={{ x, opacity, width: 100, height: 100, backgroundColor: "red" }}
    />
  );
}

to create a red div that animate when we drag it.

The useMotionValue prop lets us create a distance value that we pass into the style prop.

useTransform lets us change the opacity as the div is animated.

The first argument is the quantity to change.

The 2nd argument is the distance values.

And the 3rd argument is the opacity values that correspond to the distance values in the 2nd argument.

So when we drag left or right, the opacity of the div becomes 0.

Conclusion

We can add basic animations and drag and drop effects with Framer Motion.