Categories
React

Add Animation with the react-motion Library

With the react-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 react-motion.

Getting Started

We can install the package by running:

npm install --save react-motion

Motion

The Motion component lets us create the animation with the easing function of our choice.

For example, we can write:

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

export default function App() {
  const [click, setClick] = useState(false);
  return (
    <>
      <button onClick={() => setClick(!click)}>toggle</button>
      <Motion defaultStyle={{ x: 0 }} style={{ x: spring(click ? 30 : 0) }}>
        {({ x }) => (
          <div
            style={{
              transform: `translateX(${x}px)`
            }}
          >
            hello world
          </div>
        )}
      </Motion>
    </>
  );
}

to move the div when we click on the toggle button.

The Motion component wraps around the items that we want to animate.

The defaultStyle prop has the default styles.

And the Motion component’s style prop has the style that’s applied when animation.

Then we can get the x value in the render prop and then use it in our content.

The spring function renders the x value that’s applied when we run the animation.

We can animate more than one style.

For example, we can write:

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

export default function App() {
  return (
    <>
      <Motion
        defaultStyle={{ x: 0, y: 0 }}
        style={{ x: spring(10), y: spring(20) }}
      >
        {({ x, y }) => (
          <div
            style={{
              transform: `translateX(${x}px) translateY(${y}px)`
            }}
          >
            hello world
          </div>
        )}
      </Motion>
    </>
  );
}

to animate the x and y values and use them with the div.

StaggeredMotion

The StaggeredMotion component animates a collection of fixed lengths whose values depend on each other.

To use it, we can write:

import React from "react";
import { spring, StaggeredMotion } from "react-motion";

export default function App() {
  return (
    <>
      <StaggeredMotion
        defaultStyles={[{ h: 0 }, { h: 0 }, { h: 0 }]}
        styles={(prevInterpolatedStyles) =>
          prevInterpolatedStyles.map((_, i) => {
            return i === 0
              ? { h: spring(100) }
              : { h: spring(prevInterpolatedStyles[i - 1].h) };
          })
        }
      >
        {(interpolatingStyles) => (
          <div>
            {interpolatingStyles.map((style, i) => (
              <div key={i} style={{ border: "1px solid", height: style.h }} />
            ))}
          </div>
        )}
      </StaggeredMotion>
    </>
  );
}

to create 3 divs that are stacked on top of each other.

The height of each is animated so that their height increases up to 100px each.

We pass in an array to the defaultStyles prop to set the initial styles for each div,

Then in the styles prop, we create a function to get the previously interpolated styles from the parameter.

Then we return the object with the height style to animate with depending on the index of the element that’s animated.

In the render prop, we get the interpolatingStyles and apply them to the div.

Conclusion

We can create simple animations with the react-motion library.

Categories
React

Animation with the react-motion Library — Transitions

With the react-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 react-motion.

TransitionMotion

We can add component mounting and unmounting animation with the TransitionMotion component.

For instance, we can write:

import React, { useEffect, useState } from "react";
import { spring, TransitionMotion } from "react-motion";

export default function App() {
  const [items, setItems] = useState([
    { key: "a", size: 10 },
    { key: "b", size: 20 },
    { key: "c", size: 30 }
  ]);

  const willLeave = () => {
    return { width: spring(0), height: spring(0) };
  };

  useEffect(() => {
    setItems([
      { key: "a", size: 10 },
      { key: "b", size: 20 }
    ]);
  }, []);

  return (
    <>
      <TransitionMotion
        willLeave={willLeave}
        styles={items.map((item) => ({
          key: item.key,
          style: { width: item.size, height: item.size }
        }))}
      >
        {(interpolatedStyles) => (
          <div>
            {interpolatedStyles.map((config) => {
              return (
                <div
                  key={config.key}
                  style={{ ...config.style, border: "1px solid" }}
                />
              );
            })}
          </div>
        )}
      </TransitionMotion>
    </>
  );
}

We use the TransitionMotion component to render a transition effect that’s shown when we remove the bottom div.

We create the willLeave function to return the effect that we want to show.

And we pass that into the willLeave prop.

The styles prop has the styles for each item.

The key property is required to identify the correct item when animating.

We animate their width and height .

The render prop has the divs that we want to render.

We get their styles from the interpolatingStyles parameter.

And we apply the styles form them by passing that into he style prop.

We can change how the spring animation works by passing in a 2nd argument.

For instance, we can write:

import React, { useEffect, useState } from "react";
import { spring, TransitionMotion } from "react-motion";

export default function App() {
  const [items, setItems] = useState([
    { key: "a", size: 10 },
    { key: "b", size: 20 },
    { key: "c", size: 30 }
  ]);

  const willLeave = () => {
    return {
      width: spring(0, { stiffness: 120, damping: 17 }),
      height: spring(0, { stiffness: 120, damping: 17 })
    };
  };

  useEffect(() => {
    setItems([
      { key: "a", size: 10 },
      { key: "b", size: 20 }
    ]);
  }, []);

  return (
    <>
      <TransitionMotion
        willLeave={willLeave}
        styles={items.map((item) => ({
          key: item.key,
          style: { width: item.size, height: item.size }
        }))}
      >
        {(interpolatedStyles) => (
          <div>
            {interpolatedStyles.map((config) => {
              return (
                <div
                  key={config.key}
                  style={{ ...config.style, border: "1px solid" }}
                />
              );
            })}
          </div>
        )}
      </TransitionMotion>
    </>
  );
}

We set the stiffness and damping to change how the animation is rendered.

We can also add the precision property to specify both the rounding of the interpolated value and the speed.

Conclusion

We can use the TransitionComponent to render transition effects in our React component.

Categories
React

Add Animation with the react-awesome-reveal Library

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

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

Installation

We can install the library by running:

npm install react-awesome-reveal --save

with NPM or we can run:

yarn add react-awesome-reveal

with Yarn.

Quick Start

We can add a simple fade effect to our content with the Fade component.

For example, we can write:

import React from "react";
import { Fade } from "react-awesome-reveal";

export default function App() {
  return (
    <div className="App">
      <Fade>
        <p>hello world</p>
      </Fade>
    </div>
  );
}

to display ‘hello world’ with a fade effect as it enters.

Other supported effects include Bounce, Fade, Flip, Hinge, JackInTheBox, Roll, Rotate, Slide and Zoom .

We can add the triggerOnce prop to animate only the first time an element enters the viewport:

import React from "react";
import { Fade } from "react-awesome-reveal";

export default function App() {
  return (
    <div className="App">
      <Fade triggerOnce>
        <p>hello world</p>
      </Fade>
    </div>
  );
}

Chaining Multiple Animations

We can chain multiple animations with the cascade prop:

import React from "react";
import { Fade } from "react-awesome-reveal";

export default function App() {
  return (
    <div className="App">
      <Fade cascade>
        <p>foo</p>
        <p>bar</p>
        <p>baz</p>
      </Fade>
    </div>
  );
}

Then each of the p elements will be animated one after the other.

This is similar to:

import React from "react";
import { Fade } from "react-awesome-reveal";

export default function App() {
  return (
    <div className="App">
      <Fade>
        <p>foo</p>
      </Fade>
      <Fade delay={1000}>
        <p>bar</p>
      </Fade>
      <Fade delay={2000}>
        <p>baz</p>
      </Fade>
    </div>
  );
}

except that cascade shows the 2nd item only after the first enter the viewport.

Custom Animations

We can create custom animations with the keyframes tag.

For example, we can write:

import React from "react";
import Reveal from "react-awesome-reveal";
import { keyframes } from "[@emotion/core](https://medium.com/r/?url=http%3A%2F%2Ftwitter.com%2Femotion%2Fcore "Twitter profile for @emotion/core")";

const customAnimation = keyframes`
  from {
    opacity: 0;
    transform: translate3d(200px, 100px, 0);
  }

to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
`;

function AnimatedComponent({ children }) {
  return <Reveal keyframes={customAnimation}>{children}</Reveal>;
}

export default function App() {
  return (
    <div className="App">
      <AnimatedComponent>
        <p>hello world</p>
      </AnimatedComponent>
    </div>
  );
}

to create the customAnimation object with the keyframes tag.

We specify the from styles that are rendered at the start of the animation.

The to styles are rendered at the end of the animation.

The styles in between are interpolated.

Then we can use that with the Reveal component’s keyframes prop.

And we use our AnimatedComponent in the App component.

If no keyframes prop is passed in, the default rendered animation is fade entrance from the left.

Other props we can pass to Reveal include:

  • cascade
  • damping
  • delay
  • duration
  • fraction
  • triggerOnce
  • className and childClassName
  • style and childStyle

Conclusion

We can add simple animation with the react-awesome-real library.

Categories
Vue 3

Vue 3 — Props Data Flow

Vue 3 is the up and coming version of Vue front end framework.

It builds on the popularity and ease of use of Vue 2.

In this article, we’ll look at how to use props with Vue 3.

One-Way Data Flow

Props have a one way downward binding between the parent and child component.

When the parent property updates, then the updates are passed into the child via props.

This prevents child components from accidentally mutating the parent’s state.

And this makes our app easier to understand.

We should never mutate props.

If we need to change their value, then we should assign them to a new property first.

For instance, if we need to change the value of an initial value that’s set with the prop’s value, then we should assign that to a state first.

So we should write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <counter :initial-count="5"></counter>
    </div>
    <script>
      const app = Vue.createApp({}); app.component("counter", {
        props: ["initialCount"],
        data() {
          return {
            count: this.initialCount
          };
        },
        template: `
          <div>
            <button @click='count++'>increment</button>
            <p>{{count}}</p>
          </div>
        `
      }); app.mount("#app");
    </script>
  </body>
</html>

We have the initialCount prop that we use to set the initial value of count state in the counter component.

Then we can do whatever we like with it.

If the value needs to be transformed, then we can put it in as a computed property.

For instance, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <counter :initial-count="5"></counter>
    </div>
    <script>
      const app = Vue.createApp({}); 
      app.component("counter", {
        props: ["initialCount"],
        data() {
          return {
            count: this.initialCount
          };
        },
        computed: {
          doubleCount() {
            return this.count * 2;
          }
        },
        template: `
          <div>
            <button @click='count++'>increment</button>
            <p>{{doubleCount}}</p>
          </div>
        `
      }); app.mount("#app");
    </script>
  </body>
</html>

We have the initial-count prop which is transformed to doubleCount by returning this.count * 2 .

Now we don’t have to do anything with the prop value itself.

And we just change the state to what we want within the data method and the computed property in the counter component.

Prop Validation

We can validate props by check its data type and more.

We set the the props property’s value to a constructor.

Or we can validate it with a function.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <blog-post v-for="post of posts"></blog-post>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            posts: [{ author: "james", likes: 100 }]
          };
        }
      });
      app.component("blog-post", {
        props: {
          title: {
            type: String,
            default: "default title"
          }
        },
        template: `<p>{{title}}</p>`
      });
      app.mount("#app");
    </script>
  </body>
</html>

Then we get the ‘default title’ text displayed since we never passed in value to the title prop.

default has the default value.

validator has the validator function for props.

For example, we can write:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <blog-post v-for="post of posts" type="news"></blog-post>
    </div>
    <script>
      const app = Vue.createApp({
        data() {
          return {
            posts: [{ author: "james", likes: 100 }]
          };
        }
      });
      app.component("blog-post", {
        props: {
          type: {
            validator(value) {
              return ["news", "announcement"].indexOf(value) !== -1;
            }
          }
        },
        template: `<p>{{type}}</p>`
      });
      app.mount("#app");
    </script>
  </body>
</html>

to add a validator for the type prop.

The validator method is run when we pass in the prop with the given name.

The value is the value that we pass in.

So if we pass in something other than 'new' or 'announcement' like:

<blog-post v-for="post of posts" type="foo"></blog-post>

then we’ll get a warning.

We can also add the required property and set it to true to make a prop required like:

prop: {
  type: String,
  required: true
}

Conclusion

We can validate props with constructors and validation functions.

Also, we can add the default property to set the default value of a prop.

Categories
React

Animation with the react-tweenful Library — SVG Animation

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

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

SVG Animation

We can add animations to SVGs with the SVG object.

For example, we can write:

import React from "react";
import { SVG, percentage, elastic } from "react-tweenful";

const circles = new Array(5).fill(0).map((_e, i) => ({
  loop: true,
  fill: `hsl(${(i + 1) * 20 - 20}, 70%, 70%)`,
  delay: ((i + 1) * 1500) / -10,
  duration: 1500,
  easing: elastic(2, 0.9),
  transform: {
    translate: "0 100px"
  },
  style: {
    transformOrigin: `${-200 + 120 * (i + 1)}px 250px`
  },
  animate: percentage({
    "0%": { translate: "0px 100px", scale: 1 },
    "50%": { translate: "0px -100px", scale: 0.3 },
    "100%": { translate: "0px 100px", scale: 1 }
  }),
  r: 35,
  cx: 100 * i + 50,
  cy: 250
}));

export default function App() {
  return (
    <div className="bouncing-balls">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        x="0px"
        y="0px"
        viewBox="0 0 1000 500"
      >
        {circles.map((circle, i) => (
          <SVG.circle key={i} {...circle}></SVG.circle>
        ))}
      </svg>
    </div>
  );
}

to add a bouncing ball effect.

The circles array has objects which are created with styles that we apply to create the bouncing ball effect.

fill has the fill color.

loop set to true means we repeat the animation forever.

delay has the animation delay.

duration has the duration of the animation.

easing has the easing of the animation.

transform is the CSS transform property.

style has more styles we apply.

animate lets us add styles applied at the given progress for the animation.

r , cx , and cy have the radius, and the x and y coordinates of the center of the circle respectively.

In the JSX, we create the svg component with the SVG.circle components inside it.

We apply all the animation styles by spreading the circle properties that we created earlier.

Now we should see the bouncing ball effect displayed.

Conclusion

We can animate SVGs easily with the react-tweenful library.