Categories
React

Add Animation to Our React App with the react-spring Library

With the react-spring library, we can render animations in our React app easily.

In this article, we’ll take a look at how to get started with react-spring.

Installation

We can install the react-spring package by running:

npm install react-spring

Basic Animation

We can create basic animations with the useSpring hook.

For example, we can write:

import React from "react";
import { useSpring, animated } from "react-spring";

export default function App() {
  const props = useSpring({ opacity: 1, from: { opacity: 0 } });
  return <animated.div style={props}>hello world</animated.div>;
}

We call the useSpring hook to set the opacity that’s applied after the animation is done.

The from property has the styles before the animation.

The animated.div component lets us create a div that can be animated.

We pass in the props variable to the style prop to style it.

We can also animate text:

import React from "react";
import { useSpring, animated } from "react-spring";

export default function App() {
  const props = useSpring({ number: 1, from: { number: 0 } });
  return <animated.span>{props.number}</animated.span>;
}

We animate props.number when it changes from 0 to 1.

Also, we can scroll a div with the scroll property.

For example, we can write:

import React from "react";
import { useSpring, animated } from "react-spring";

export default function App() {
  const props = useSpring({ scroll: 300, from: { scroll: 0 } });
  return (
    <animated.div
      scrollTop={props.scroll}
      style={{ overflowY: "scroll", height: 200 }}
    >
      {Array(100)
        .fill()
        .map((_, i) => (
          <p key={i}>{i}</p>
        ))}
    </animated.div>
  );
}

We scroll 300px down from the top.

Also, we can combine multiple effects together:

import React from "react";
import { useSpring, animated, interpolate } from "react-spring";

export default function App() {
  const { o, xyz, color } = useSpring({
    from: { o: 0, xyz: [0, 0, 0], color: "red" },
    o: 1,
    xyz: [10, 20, 5],
    color: "green"
  });

  return (
    <animated.div
      style={{
        color,
        background: o.interpolate((o) => `rgba(210, 57, 77, ${o})`),
        transform: xyz.interpolate(
          (x, y, z) => `translate3d(${x}px, ${y}px, ${z}px)`
        ),
        border: interpolate([o, color], (o, c) => `${o * 10}px solid ${c}`),
        padding: o
          .interpolate({ range: [0, 0.5, 1], output: [0, 0, 10] })
          .interpolate((o) => `${o}%`),
        borderColor: o.interpolate({
          range: [0, 1],
          output: ["red", "#ffaabb"]
        }),
        opacity: o.interpolate([0.1, 0.2, 0.6, 1], [1, 0.1, 0.5, 1])
      }}
    >
      {o.interpolate((n) => n.toFixed(2))}
    </animated.div>
  );
}

We call the useSpring hook to generate some values that are passed into the style prop.

We interpolate o , x , y , and z into various values to change the style of the div as it is animating.

We can pass in values that are created from the react-spring hooks into components directly.

For instance, we can write:

import React, { useState } from "react";
import { useSpring, animated } from "react-spring";

export default function App() {
  const [state, setState] = useState(1);
  const props = useSpring({ x: state ? 1 : 0 });
  return (
    <>
      <button onClick={() => setState((state) => (state === 1 ? 0 : 1))}>
        toggle
      </button>
      <animated.div
        style={{
          transform: props.x
            .interpolate({
              range: [0, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1],
              output: [1, 0.97, 0.9, 1.1, 0.9, 1.1, 1.03, 1]
            })
            .interpolate((x) => `scale(${x})`),
          backgroundColor: "red",
          height: 100,
          width: 100
        }}
      />
    </>
  );
}

We add the div and then we can change the scale as we click the toggle button by setting the transform prop.

We map the value from the range to the output .

And x is the value of output that corresponds to the one in range .

Conclusion

We can add basic animation to our React app with react-spring.

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.