Categories
React

Framer Motion — Animation Events

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 Events

We can listen to various animation events emitted from our motion components.

For example, we can write:

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

function onUpdate(latest) {
  console.log(latest.x, latest.opacity);
}

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

to pass in the onUpdate function into the onUpdate prop.

The latest parameter has the x coordinate value and the opacity which is logged when the animation is running.

onAnimationStart

The onAnimationStart prop takes a callback that’s run when the animation starts.

For example, we can write:

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

function onStart() {
  console.log("Animation statted");
}

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

We pass in the onStart function into the onAnimationStart prop to log some output when the animation starts.

onAnimationComplete

The onAnimationComplete prop takes a function that’s run when the animation is done.

For example, we can write:

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

function onComplete() {
  console.log("Animation completed");
}

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

to log something when the animation is done.

Hover Events

We can listen for hover events with Framer Motion.

onHoverStart(event, info)

The onHoverStart prop lets us listen for hover events when they start.

For example, we can write:

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

export default function App() {
  return (
    <motion.div
      onHoverStart={() => console.log("Hover starts")}
      style={{ backgroundColor: "red", width: 100, height: 100 }}
    ></motion.div>
  );
}

When we hover over the div, ‘Hover starts’ is logged.

onHoverEnd(event, info)

We can listen for hover end events with the onHoverEnd prop.

For instance, we can write:

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

export default function App() {
  return (
    <motion.div
      onHoverEnd={() => console.log("Hover ends")}
      style={{ backgroundColor: "red", width: 100, height: 100 }}
    ></motion.div>
  );
}

Now when we move the mouse from the div to outside of the div, we see ‘Hover ends’ logged.

onTap(event, info)

The onTap prop lets us listen for taps.

For instance, we can write:

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

function onTap(event, info) {
  console.log(info.point.x, info.point.y);
}

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

Then we log the coordinate of the tap with the info.point property.

Conclusion

We can listen for various events with Framer Motion.

Categories
React

Framer Motion — Drag and Drop and Gesture Handling

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.

dragElastic

We can set the dragElastic prop to set the degree of movement allowed outside constraints.

Possible values range from 0, which means no movement, to 1, which means full movement.

The default value is 0.5.

For example, we can write:

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

export default function App() {
  return (
    <motion.div
      drag
      dragConstraints={{ left: 0, right: 300 }}
      dragElastic={0.2}
      style={{ background: "red", width: 100, height: 100 }}
    />
  );
}

We set the dragElastic prop to 0.2 to slow down movement.

dragMomentum

The dragMomentum prop lets us apply momentum from the pan gesture to the component while dragging finishes.

For example, we can write:

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

export default function App() {
  return (
    <motion.div
      drag
      dragConstraints={{ left: 0, right: 300 }}
      dragMomentum={false}
      style={{ background: "red", width: 100, height: 100 }}
    />
  );
}

We set dragMomentum to false so that we remove momentum from the pan gesture to the component after dragging ends.

dragTransition

The dragTransition prop lets us change dragging inertia.

For example, we can write:

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

export default function App() {
  return (
    <motion.div
      drag
      dragConstraints={{ left: 0, right: 300 }}
      dragTransition={{ bounceStiffness: 600, bounceDamping: 10 }}
      style={{ background: "red", width: 100, height: 100 }}
    />
  );
}

We set the bounceStiffnes and bounceDamping to set how the div acts without dragging.

Damping slows the div down. And stiffness removes the bounciness of the div.

dragPropagation

We can allow drag gesture propagation to child components.

For instance, we can write:

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

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

Then the drag gestures propagate from the child div to the parent.

whileHover

The whileHover prop lets us apply styles when we hover over an element.

For example, we can write:

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

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

to set the div to increase in size when we hover over it.

whileTap

The whileTap prop lets us apply styles to an element when the component is pressed.

For instance, we can write:

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

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

We set the whileTap prop so that the div shrinks when we tap on it.

Conclusion

We can add drag and drop and gesture handling with Framer Motion.

Categories
React

Framer Motion — Variants and Drag and Drop

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.

variants

We can organize styles with variants.

They let us control animations throughout a component tree by switching to a single animate prop.

For example, we can write:

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

const variants = {
  active: {
    backgroundColor: "#f00"
  },
  inactive: {
    backgroundColor: "#fff",
    transition: { duration: 2 }
  }
};

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

We create the variants object with some styles we want to apply at various stages of animation.

Then we apply them by passing the variants object as the value of the variants prop.

Then we set animate to 'active' to set the styles when the animation ends to the ones in the active property.

style

The style prop is like the style prop in React, but it’s enhanced to support motion values and transform values.

For example, we can write:

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

export default function App() {
  const x = useMotionValue(0);

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

We pass the x motion value into the style prop so we can set the horizontal position of the div.

Layout Animation

We can create layout animations with Frame rMotion.

The layout prop lets us animate an element to its new position when its layout changes.

For example, we can write:

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

const items = [
  { name: "foo", isSelected: true, id: 1 },
  { name: "bar", isSelected: false, id: 2 },
  { name: "baz", isSelected: true, id: 3 }
];
export default function App() {
  return (
    <AnimateSharedLayout>
      {items.map((item) => (
        <motion.li layout key={item.id}>
          {item.name}
          {item.isSelected && <motion.hr layoutId="underline" />}
        </motion.li>
      ))}
    </AnimateSharedLayout>
  );
}

to let us animate the changes in the layout with the AnimateSharedLayout component.

We have the motion.li to animate the li elements when the li layout change.

Drag

We can add drag and drop capabilities to our elements with Framer Motion.

For instance, we can write:

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

export default function App() {
  const constraintsRef = useRef(null);

  return (
    <motion.div
      ref={constraintsRef}
      style={{ background: "green", width: 200, height: 200 }}
    >
      <motion.div
        drag
        dragConstraints={constraintsRef}
        style={{ background: "red", width: 100, height: 100 }}
      />
    </motion.div>
  );
}

We allow the red div to be dragged around within the green div.

We do this by assigning a ref to the green div.

Then we pass the ref as the value of the dragConstraints prop.

The drag prop lets us enable dragging on the red div.

Conclusion

We can create variants to organize styles.

Also, we can add drag and drop capabilities to elements with Framer Motion.

Categories
React

Framer Motion — Applying Animation Styles

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.

initial Prop and Multiple Variants

We can set the initial prop to an array of variant names.

For instance, we can write:

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

const variants = {
  visible: {
    opacity: 1,
    transition: { duration: 2 }
  },
  active: {
    backgroundColor: "green"
  }
};

export default function App() {
  return (
    <>
      <motion.div
        initial={["visible", "active"]}
        variants={variants}
        style={{
          backgroundColor: "red",
          width: 100,
          height: 100
        }}
        animate={{ opacity: 0 }}
      />
    </>
  );
}

We apply the styles from both the visible and active variant to apply styles from both when our component mounts.

Also, we can pass in false as the value of initial to disable mount animation.

For example, we can write:

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

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

Then the opacity of the div will be set to 1 when we mount the div.

animate Prop

The animate prop lets us set the values to animate to.

For example, we can write:

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

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

We set the animate prop to an object with opacity set to 1 to set the opacity of the div to 1 at the end of the animation.

Also, we can set the animate style to variant.

For instance, we can write:

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

const variants = {
  visible: {
    opacity: 1,
    transition: { duration: 2 }
  }
};

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

to set animate to the 'visible' variant to show the div.

For example, we can write:

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

const variants = {
  visible: {
    opacity: 1,
    transition: { duration: 2 }
  },
  active: {
    backgroundColor: "green"
  }
};

export default function App() {
  return (
    <>
      <motion.div
        initial={{ opacity: 0 }}
        style={{
          backgroundColor: "red",
          width: 100,
          height: 100
        }}
        variants={variants}
        animate={["visible", "active"]}
      />
    </>
  );
}

to set the animate to an array of variant names to apply all the styles at the end of the animation.

exit

We can set the exit prop to set the style to animate when the component is removed from the tree.

For example, we can write:

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

export const MyComponent = ({ isVisible }) => {
  return (
    <AnimatePresence>
      {isVisible && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          style={{
            backgroundColor: "red",
            width: 100,
            height: 100
          }}
        />
      )}
    </AnimatePresence>
  );
};

export default function App() {
  const [isVisible, setIsVislble] = useState(true);
  return (
    <>
      <button onClick={() => setIsVislble(!isVisible)}>toggle</button>
      <MyComponent isVisible={isVisible} />
    </>
  );
}

We create the MyComponent component to get which has the exit prop to apply some styles to the div when it’s being removed from the tree.

Conclusion

We can apply styles at various stages of animation with Framer Motion.

Categories
React

Framer Motion — Animation Styles

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.

CSS Variables

Motion components can accept CSS variables

For example, we can write:

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

export default function App() {
  return (
    <>
      <motion.ul
        initial={{ "--rotate": "0deg" }}
        animate={{ "--rotate": "360deg" }}
        transition={{ duration: 2, repeat: Infinity }}
      >
        <li style={{ transform: "rotate(var(--rotate))" }}>foo</li>
        <li style={{ transform: "rotate(var(--rotate))" }}>bar</li>
        <li style={{ transform: "rotate(var(--rotate))" }}>baz</li>
      </motion.ul>
    </>
  );
}

We set the rotate CSS variable to a value.

We set the value for it before the animation with the initial prop.

And we set the value for it after the animation with the animate prop.

Then we use them in the li to rotate the li elements.

The transition prop has duration to 2 to rotate for 2 seconds.

And we have repeat set to Infinity to repeat infinite times.

Performance

Framer Motion animates values outside the React render cycle to increase performance.

For example, we can write:

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

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

to get GPU accelerated animation by using the motion.div with motion value x .

If we specify CSS properties in the style and animate props, then we get CPU acceleration.

So if we have:

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

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

Then the left property will be animated by the CPU, which is slower than animating the x motion value with the GPU.

motion components are fully compatible with server-side rendering, except for the scale , rotate , pathLength , pathOffset , and pathSpacing properties.

Props

Motion components haves a few props.

initial

The initial prop lets us set the styles that are applied to the motion component when the animation starts.

For example, we can write:

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

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

to set the opacity of the div to 1 when we start animating the div.

We can also pass in a variant name as the value of initial :

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

const variants = {
  visible: {
    opacity: 1,
    transition: { duration: 2 }
  }
};

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

We pass in the property name in the variants object to apply the styles within the property.

Conclusion

We can add animations with better performance with GPU acceleration.

Also, we can set styles to apply when the animation starts.