Создание удовлетворительной волнистой анимации текста с помощью Framer Motion

Здравствуйте! Давно не виделись. Хотя теперь, когда экзамены по информатике AP закончились, а лето почти наступило (осталось 30 дней учебы), у меня, надеюсь, будет больше времени, которое я смогу посвятить проектам и написанию статей.

В нашей сегодняшней статье в блоге мы рассмотрим, как можно создать удовлетворительную волнистую анимацию текста с помощью Framer Motion, React и TypeScript.

Вот демонстрация проекта в CodeSandbox 👇.

Начало работы

Я знаю, что вы жаждете действий, так что давайте начнем! Начните с инициализации проекта React и TypeScript с помощью create-react-app.

npx create-react-app wavy-text --template typescript
cd wavy-text
Войдите в полноэкранный режим Выйти из полноэкранного режима

Для этого нам нужно установить еще одну библиотеку под названием Framer Motion. Давайте установим ее!

yarn add framer-motion
# npm i framer-motion
Войти в полноэкранный режим Выйти из полноэкранного режима

Потрясающе! Наш проект правильно настроен. Давайте откроем наш App.tsx, чтобы начать работу. Давайте заменим содержимое по умолчанию, чтобы начать работу.

import "./styles.css";
import WavyText from "./WavyText";

export default function App() {
  return (
    <div className="App">
      <h1>Awesome Wavy Text!</h1>
    </div>
  );
}
Вход в полноэкранный режим Выход из полноэкранного режима

Круто. Теперь перейдем к файлу src/styles.css, чтобы настроить некоторые базовые стили для нашего приложения. Ничего особенного, но мы хотим, чтобы все выглядело красиво.

@import url("https://fonts.googleapis.com/css2?family=Lexend+Deca&display=swap");

body {
  background: linear-gradient(
    45deg,
    hsl(272deg 75% 65%) 0%,
    hsl(193deg 100% 50%) 50%,
    hsl(162deg 84% 88%) 100%
  );
}

.App {
  font-family: "Lexend Deca", sans-serif;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  justify-content: center;
  align-items: center;
}

h1 {
  color: white;
  font-size: 48px;
  user-select: none;
}
Вход в полноэкранный режим Выход из полноэкранного режима

Создание анимации

Потрясающе! Теперь, когда все эти скучные вещи настроены и работают, давайте перейдем к сути проекта.

Переключившись на React, давайте сначала импортируем то, что нам понадобится для этого проекта, и настроим реквизиты для компонента.

import { FC } from "react";
import { motion, Variants, HTMLMotionProps } from "framer-motion";

interface Props extends HTMLMotionProps<"div"> {
  text: string;
  delay?: number;
  duration?: number;
}
Вход в полноэкранный режим Выход из полноэкранного режима

Поскольку мы используем Motion, нам нужно использовать HTMLMotionProps для передачи реквизитов в наш HTML-компонент.

Давайте теперь начнем создавать наш компонент React function внутри нашего файла и передадим через него наши реквизиты.

const Letter: FC<Props> = ({
  text,
  delay = 0,
  duration = 0.05,
  ...props
}: Props) => {

}
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь внутри мы должны взять наш текстовый ввод и преобразовать каждую букву в строке в массив строк. Для этого мы можем использовать функцию Array.from() в JavaScript, чтобы добиться именно того, чего мы хотим.

const letters = Array.from(text);
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что если вы используете международный язык, вам может понадобиться Grapheme Splitter для разделения строк на отдельные символы, воспринимаемые пользователем, в отличие от символов, воспринимаемых компьютером. Поскольку наш текст на английском языке, это только добавит ненужные сложности и дополнительные шаги в наш проект, поэтому я не буду его добавлять 🙂

Отлично! Давайте теперь отобразим отдельные буквы в этом массиве под другой компонент.

return (
  <motion.h1
    style={{ display: "flex", overflow: "hidden" }}
    {...props}
  >
    {letters.map((letter, index) => (
      <motion.span key={index}>
        {letter === " " ? "u00A0" : letter}
      </motion.span>
    ))}
  </motion.h1>
);
Вход в полноэкранный режим Выход из полноэкранного режима

Наша функциональность анимации в основном работает… есть только небольшая проблема. Анимация выглядит ужасно. К счастью, мы можем использовать Variants в Framer Motion, чтобы решить нашу проблему.

Вне (или внутри — мы можем даже объявить их в новом файле и импортировать в него) нашего компонента WavyText, мы можем создать две разные анимации для контейнера и дочернего элемента.

const container: Variants = {
  hidden: {
    opacity: 0
  },
  visible: (i: number = 1) => ({
    opacity: 1,
    transition: { staggerChildren: duration, delayChildren: i * delay }
  })
};

const child: Variants = {
  visible: {
    opacity: 1,
    y: 0,
    transition: {
      type: "spring",
      damping: 12,
      stiffness: 200
    }
  },
  hidden: {
    opacity: 0,
    y: 20,
    transition: {
      type: "spring",
      damping: 12,
      stiffness: 200
    }
  }
};
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь, когда мы это сделали, мы можем установить variants в наших компонентах на соответствующую анимацию.

<motion.h1
  style={{ display: "flex", overflow: "hidden" }}
  variants={container}
  initial="hidden"
  animate="show"
  {...props}
>
Вход в полноэкранный режим Выход из полноэкранного режима

…и в нашем дочернем компоненте:

<motion.span key={index} variants={child}>
Войти в полноэкранный режим Выйти из полноэкранного режима

Ура — наша анимация теперь работает! Нам осталось импортировать ее в наш файл src/App.tsx и правильно настроить.

Откройте файл src/App.tsx. Начните с импорта вашего компонента, а затем удалите элемент <h1></h1> и замените его на:

// import WavyText from "./WavyText";
// ...

<WavyText text="Awesome Wavy Text!" />
Вход в полноэкранный режим Выйти из полноэкранного режима

Замечательно! Теперь наша анимация должна работать так, как мы ожидали. В моем примере я также реализовал функцию «воспроизведения», если вам интересно взглянуть на код, стоящий за этим, обязательно загляните на CodeSandbox.

Заключение

Вот и все, что у меня есть для вас! Надеюсь, вы узнали что-то новое, и в дальнейшем сможете использовать эту анимацию для оживления своих сайтов! Я также сейчас использую эту анимацию на своем сайте 🙂

Если вы хотите увидеть больше статей о дизайне, a11y и смежных областях в моем блоге — дайте мне знать! Я с нетерпением жду ваших отзывов.

Приятного остатка дня 👋

Оцените статью
Procodings.ru
Добавить комментарий