Jakke.fi logo
jakke.fi/blog

Blogging mostly about my free-time projects.

HomeBloganimating-with-framer-motion-appearing-text

Animating with Framer Motion (Appearing Text)

@Type: Report

@Published:November 10, 2024 at 11:20

@Last Updated:November 12, 2024 at 17:16

@Author: Jakke Korpelainen

Intro

Wanted to create appearing text as if it were written or how a language model replies. Framer Motion (framer.com/motion) has been an interesting tool for various animation purposes.

Source & Demo

Source - N/A (in report)

Demo - smartdatahub.io/about

Animated Appearing Text

Study

AnimatedText.tsx

1'use client';
2
3import { motion } from 'framer-motion';
4import React from 'react';
5
6interface AnimatedTextProps {
7  text: string;
8}
9
10export const AnimatedText = ({ text }: AnimatedTextProps) => {
11  // split text into words
12  const words = Array.from(text.split(' '));
13
14  // Variants for Container
15  const container = {
16    hidden: { opacity: 0 },
17    visible: (i = 1) => ({
18      opacity: 1,
19      transition: { staggerChildren: 0.01, delayChildren: 0.02 * i },
20    }),
21  };
22
23  // variants for each letter
24  const child = {
25    visible: {
26      opacity: 1,
27      x: 0,
28      y: 0,
29      transition: {
30        type: 'spring',
31        damping: 12,
32        stiffness: 100,
33      },
34    },
35    hidden: {
36      opacity: 0,
37      x: -20,
38      y: 10,
39      transition: {
40        type: 'spring',
41        damping: 12,
42        stiffness: 100,
43      },
44    },
45  };
46
47  const animatedText = words.map((word) => (
48    <div key={crypto.randomUUID()} className="whitespace-nowrap">
49      {Array.from(word).map((letter) => (
50        <motion.span key={crypto.randomUUID()} variants={child}>
51          {letter === ' ' ? '\u00A0' : letter}
52        </motion.span>
53      ))}
54    </div>
55  ));
56
57  return (
58    <motion.div
59      className="overflow-hidden flex-wrap flex text-base md:text-lg gap-2"
60      variants={container}
61      initial="hidden"
62      animate="visible"
63    >
64      {animatedText}
65    </motion.div>
66  );
67};
68