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.

Categories
React

Framer Motion —Motion Components

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

Motion components are DOM elements optimized for 60fps animations and gestures.

For example, to create an animated div, we can use the motion.div component.

To do this, we write:

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

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

to add a div that animates by rotating 360 degrees.

And we set the transition prop to set the duration of the animation to 2 seconds.

Supported Values

We can add various types of values for our animation.

We can add:

  • numbers
  • strings
  • colors in hex, RGB, or HSL format
  • complex strings with multiple numbers or colors

Non-animatable values will be set instantly.

If we set these values within transitionEnd , then this value will be set at the end of the animation.

For instance, we can use it by writing;

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

export default function App() {
  return (
    <>
      <motion.div
        animate={{
          x: 0,
          backgroundColor: "#000",
          boxShadow: "10px 10px 0 rgba(0, 0, 0, 0.2)",
          position: "fixed",
          transitionEnd: {
            display: "none"
          }
        }}
        style={{ backgroundColor: "red", width: 100, height: 100 }}
      />
    </>
  );
}

We set the animate prop to an object with various values.

x is the x coordinate of the element’s position.

backgroundColor has a background color.

boxShadow has the box shadow.

position is set to 'fixed' .

transitionEnd has the value display set to 'none' .

We have all these values applied duration animation.

Value Type Conversion

Values can only be animated between 2 of the same type.

However, x , y , width , height , top , left , right , and bottom values can be animated between 2 different value types.

For instance, we can write:

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

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

We have the initial prop set to an object with x set to '100%' .

And in the animare prop, we set x to 'calc(100vw — 50%) .

They’re different types of values, but Framer Motion can convert between them.

Transform

Transform properties are accelerated by the GPU so they can animate smoothly.

Transform properties include:

  • Translate shortcuts: x, y, z
  • Translate: translateX, translateY, translateZ
  • Scale: scale, scaleX, scaleY
  • Rotate: rotate, rotateX, rotateY, rotateZ
  • Skew: skew, skewX, skewY
  • Perspective: transformPerspective

For example, we can write:

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

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

Then when we tap or hover on the div, we’ll see smooth size changes.

Conclusion

Motion components are elements that we can animate with Framer Motion.

Categories
React

Framer Motion — Animation Hooks

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.

useReducedMotion

We can use the useReducedMotion hook to animate our elements based on the current device’s reduced motion setting.

For example, we can write:

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

export default function App() {
  const shouldReduceMotion = useReducedMotion();
  const closedX = shouldReduceMotion ? 0 : "-100%";
  const [isOpen, setIsOpen] = useState(true);

  return (
    <>
      <button onClick={() => setIsOpen(!isOpen)}>toggle</button>
      <motion.div
        animate={{
          opacity: isOpen ? 1 : 0,
          x: isOpen ? 0 : closedX
        }}
        style={{ backgroundColor: "red", width: 100, height: 100 }}
      />
    </>
  );
}

We call the useReduceMotion hook to get the shouldReduceMotion variable.

We can use that to check if reduced motion setting is enabled.

Then we can use that to position the div based on the shouldReduceMotion value.

usePresence

The usePresence hook lets us access information about whether an element is still present in the React tree.

If isPresent is false , then a component has been remove from the tree, but AnimatePresence won’t remove it until safeToRemove has been called.

For example, we can write:

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

export const Component = () => {
  const [isPresent, safeToRemove] = usePresence();

  useEffect(() => {
    console.log(isPresent);
    !isPresent && setTimeout(safeToRemove, 1000);
  }, [isPresent]);

  return <div style={{ backgroundColor: "red", width: 100, height: 100 }} />;
};

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

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>toggle</button>
      {isOpen && <Component />}
    </div>
  );
}

to watch the isPresent value in the useEffect callback.

Then we call safeToRemove to remove the component when it’s unloaded.

useIsPresent

The useIsPresent hook is similar to usePresence except that it doesn’t return the safeToRemove function.

For example, we can write:

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

export const Component = () => {
  const isPresent = useIsPresent();

  useEffect(() => {
    isPresent && console.log("is present");
  }, [isPresent]);

  return <div style={{ backgroundColor: "red", width: 100, height: 100 }} />;
};

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

  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>toggle</button>
      {isOpen && <Component />}
    </div>
  );
}

to log the isPresent value.

useDragControls

We can use the useDragControls hook to create drag controls.

The drag controls can be passed into the draggable component’s dragControls prop.

It exposes a start method that can start dragging from pointer events or other components.

For instance, we can write:

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

export default function App() {
  const dragControls = useDragControls();

  function startDrag(event) {
    dragControls.start(event, { snapToCursor: true });
  }

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

We create the dragControls with the useDragControls hook.

Then we pass that into the dragControls prop.

The drag prop is set to 'x' so that we can drag horizontally.

We also created the startDrag function to call dragControls.start to start dragging.

We pass in the mouse event object into start and set snapToCursor to true to move the div towards our mouse cursor when we click on ‘click me’.

Conclusion

We can use various hooks that come with Framer Motion to control our animation.

Categories
React

Framer Motion — Animate and Map Motion Values

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.

animate

We can use the animate function to animate a single value or a motion value.

For example, we can write:

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

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

  useEffect(() => {
    const controls = animate(x, 100, {
      type: "spring",
      stiffness: 2000,
      onComplete: (v) => {}
    });

    return controls.stop;
  });

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

to create the x motion value with useMotionValue .

Then we can animate it with the animate function.

We set the type of the animation and the stiffness of it.

Then we return the control.stop method in the callback to stop using it.

Then finally we put the x value into the style prop so we can use it.

Transform

The transform function transforms a number into other values by paying them into an output range.

For example, we can write:

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

export default function App() {
  const x = useMotionValue(0);
  const inputRange = [0, 100];
  const outputRange = [1, 0.3];
  const [opacity, setOpacity] = useState();

  useEffect(() => {
    x.onChange((latest) => {
      const opacity = transform(latest, inputRange, outputRange);
      setOpacity(opacity);
    });
  }, []);

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

to call transform to map the x motion value into an opacity value.

We watch the x value with onChange .

Then in the callback, we call transform to map the inputRange , which has the x value range, to the outputRange , which has the opacity values.

It returns the opacity value that we use in the motion.div .

Therefore, we see that the div changes in capacity when we drag it.

Also, we can use the transform function with the inputRange and outputRange array.

Then we can call the convertRange function with the latest x value to create our opacity value:

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

export default function App() {
  const x = useMotionValue(0);
  const inputRange = [0, 100];
  const outputRange = [1, 0.3];
  const [opacity, setOpacity] = useState();

  useEffect(() => {
    x.onChange((latest) => {
      const convertRange = transform(inputRange, outputRange);
      const opacity = convertRange(x.get());
      setOpacity(opacity);
    });
  }, []);

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

We did all of that in the onChange callback to create the opacity value and pass that into the style prop.

Conclusion

We can use the animate function to animate motion values.

And we can map motion values to other values with Framer Motion.

Categories
Useful APIs

Useful Free APIs — Books and Religious Text

In the software development world, practice makes perfect. Therefore, we should find as many ways to practice programming as possible. With free public APIs, we can practice programming by creating apps that use those APIs.

In this article, we’ll look at some practice project ideas that can use some of those APIs.

Bhagavad Gita API

The Bhagavad Gita API lets us access the Bhagavad Gita text all in one place.

To access the API, we need to authenticate via OAuth.

Bhagavad Gita is one of the most important Hindu religious texts.

British National Bibliography

The British National Bibliography API lets us search for book information.

It has data for journals, periodicals, magazines, newspapers, etc.

Authentication isn’t required to access this API.

Goodreads

The Goodreads API lets us access the data stored on the Goodreads website.

We can get data for authors, books, events, comments, followers, series, topics, users, reviews, and more.

Goodreads is a website with book reviews and book information.

We can access the data with an API key.

Google Books

The Google Books API lets us access data from the Google Books website.

We can use it to search for books by category, name, and more.

Also, we can add books to our own bookshelf and retrieve it.

OAuth is required to access this API.

The Library Genesis API

The Library Genesis API lets us query books by various fields.

They include title, author, and more.

Other fields that are returned include the series a book is in, periodical, language, number of pages, ISSN, color, DPI, scanned, file name, cover URL, and more.

We can also search for a book by date.

Libraries for Node.js and Python are available.

Authentication isn’t required to access this API.

Open Library

The Open Library API lets us get user and reading list data from the library.

Authentication isn’t required for accessing data.

We can also create and edit reading lists.

Penguin Publishing

The Penguin Publishing API lets us access book data for books published by Penguin Publishing.

We can use it to search for works, authors, titles, and author events.

It returns data in XML or JSON.

Authentication isn’t required to access this API.

Rig Veda

The Rig Veda API lets us access the categories, verses from ancient Indian texts.

Authentication isn’t required to access this API.

Vedic Society

The Vedic Society API lets us access data about names, places, animals, and things from Vedic literature.

Authentication isn’t required to access this API.

Conclusion

There are useful APIs to access books data and texts.