DevGang
Авторизоваться

Как создать анимированное гамбургер-меню в React

Если вы хотите добавить несколько отточенных анимаций в свои приложения React, Framer Motion - это инструмент для этой работы.

В этом руководстве я покажу вам, как создать полностью анимированное мобильное меню, используя движение кадров в Reaction.

Что мы собираемся создать?

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

Вы также можете ознакомиться с этим подробным видео-уроком, который я создал на основе этой статьи.

Адаптивная навигационная панель с полностью анимированным мобильным меню.
Адаптивная навигационная панель с полностью анимированным мобильным меню.

Предпосылки

Хотя для начала работы с этим руководством не требуется предварительного знакомства с Framer Motion, важно иметь базовые знания в React, поскольку здесь я не буду подробно описывать основные концепции React.

На протяжении всего этого урока вы будете использовать следующие инструменты:

  • React 18.2.0: React - это библиотека JavaScript, используемая для создания пользовательских интерфейсов. Она позволяет разработчикам создавать повторно используемые компоненты пользовательского интерфейса и эффективно обновлять пользовательский интерфейс на основе изменений данных.
  • Framer Motion: Framer Motion - популярная библиотека анимации для React. Он предоставляет простой в использовании интерфейс для создания плавных интерактивных анимаций и переходов в веб-приложениях.
  • Vite: Vite - это сервер быстрой разработки и инструмент сборки для современных веб-приложений.
  • Tailwind: В этом руководстве вы будете использовать Tailwind для применения стилей к вашим компонентам React.

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

Чтобы начать работу с этим руководством, я подготовил для вас стандартный проект, который содержит все необходимые зависимости, так что вам не нужно настраивать свой проект с нуля.

Просто клонируйте исходный шаблон из репозитория GitHub, а затем следуйте инструкциям.

Исходный шаблон: Посмотреть на GitHub

Окончательная версия: Посмотреть на GitHub

Как создать простую навигационную панель в React

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

Я уже настроил для вас каталог routes, содержащий массив со всеми необходимыми маршрутами для вашего приложения. Вы можете легко отобразить эти маршруты, импортировав массив и сопоставляя его по мере необходимости.

//📂./src/routes.ts
//📂./src/routes.ts

import { BiHomeAlt2 } from "react-icons/bi";
import { FiSearch } from "react-icons/fi";
import { PiChatCircleBold } from "react-icons/pi";
import { IoPricetagsOutline } from "react-icons/io5";

export const routes = [
  {
    title: "Home",
    href: "#",
    Icon: BiHomeAlt2,
  },
  {
    title: "Explore",
    href: "#",
    Icon: FiSearch,
  },
  {
    title: "Pricing",
    href: "#",
    Icon: IoPricetagsOutline,
  },
  {
    title: "About",
    href: "#",
    Icon: PiChatCircleBold,
  },
];

Каждый объект в массиве routes включает значок, импортированный из библиотеки React Icons, понятный заголовок и ссылку href, обозначающую путь к маршруту.

Давайте отобразим массив маршрутов на панели навигации. Откройте ./src/comComponents/nav-desktop и добавьте следующий код:

//📂./src/components/nav-desktop.tsx
//📂./src/components/nav-desktop.tsx

import { routes } from "../routes";

export const NavDesktop = () => {
  return (
    <ul className="hidden lg:flex lg:items-center gap-5 text-sm">
      {routes.map((route) => {
        const { Icon, href, title } = route;
        return (
          <li>
            <a
              href={href}
              className="flex items-center gap-1 hover:text-neutral-400 transition-all"
            >
              <Icon />
              {title}
            </a>
          </li>
        );
      })}
    </ul>
  );
};

Компонент NavDesktop отображает неупорядоченный список (ul), содержащий маршруты. Он использует массив routes, импортированный из файла ../routes, для динамического создания элементов списка (li) со ссылками (a) и значками.

Навигация по рабочему столу
Навигация по рабочему столу

Вы только что создали красивую панель навигации на рабочем столе.

Теперь, когда у вас есть навигационная панель на рабочем столе, пришло время создать анимированное мобильное меню.

Как создать анимированный гамбургер-значок в React

Сначала давайте создадим кнопку с гамбургер-значком. Эта кнопка позволит пользователям переключать видимость вашего мобильного меню.

Hamburger React - это невероятно легкая библиотека React, которая предоставляет широкий спектр анимированных значков гамбургеров для плавной интеграции в ваши приложения React.

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

Откройте файл ./src/components/nav-mobile.tsx и добавьте следующий код:

//📂./src/components/nav-mobile.tsx
//📂./src/components/nav-mobile.tsx

import { useClickAway } from "react-use";
import { useRef } from "react";
import { useState } from "react";
import { Squash as Hamburger } from "hamburger-react";
import { AnimatePresence, motion } from "framer-motion";
import { routes } from "../routes";

export const NavMobile = () => {
  const [isOpen, setOpen] = useState(false);

  return (
    <div className="lg:hidden ">
      <Hamburger toggled={isOpen} size={20} toggle={setOpen} />
    </div>
  );
};

Этот компонент React создает кнопку, которая открывает и закрывает меню. Кнопка запускается как закрытая (isOpen имеет значение false). При нажатии на него видимость меню переключается.

Кроме того, компонент NavMobile останется скрытым на больших экранах, поскольку вы уже внедрили компонент desktop navbar.

Интерактивный значок гамбургера. Переключение между открытым и закрытым состояниями с плавной анимацией.
Интерактивный значок гамбургера. Переключение между открытым и закрытым состояниями с плавной анимацией.

Как создать анимированное мобильное меню в React

Давайте расширим функциональность вашего мобильного меню и отобразим маршруты навигации, как только пользователь нажмет на кнопку "гамбургер".

Откройте файл ./src/components/nav-mobile.tsx и добавьте следующий код:

//📂./src/components/nav-mobile.tsx
//📂./src/components/nav-mobile.tsx

import { useClickAway } from "react-use";
import { useRef } from "react";
import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Squash as Hamburger } from "hamburger-react";
import { routes } from "../routes";

export const NavMobile = () => {
  const [isOpen, setOpen] = useState(false);
  const ref = useRef(null);

  useClickAway(ref, () => setOpen(false));

  return (
    <div ref={ref} className="lg:hidden ">
      <Hamburger toggled={isOpen} size={20} toggle={setOpen} />
      {isOpen && (
        <div className="fixed left-0 shadow-4xl right-0 top-[3.5rem] p-5 pt-0 bg-neutral-950 border-b border-b-white/20">
          <ul className="grid gap-2">
            {routes.map((route) => {
              const { Icon } = route;

              return (
                <li
                  key={route.title}
                  className="w-full p-[0.08rem] rounded-xl bg-gradient-to-tr from-neutral-800 via-neutral-950 to-neutral-700"
                >
                  <a
                    onClick={() => setOpen((prev) => !prev)}
                    className={
                      "flex items-center justify-between w-full p-5 rounded-xl bg-neutral-950"
                    }
                    href={route.href}
                  >
                    <span className="flex gap-1 text-lg">{route.title}</span>
                    <Icon className="text-xl" />
                  </a>
                </li>
              );
            })}
          </ul>
        </div>
      )}
    </div>
  );
};

Вот упрощенное объяснение компонента:

Настройка состояния и ссылок:

  • Компонент начинается с создания двух переменных: isOpen и ref.
  • isOpen отслеживает, открыто или закрыто меню.
  • ref похож на метку, которую мы прикрепляем к элементу HTML. В данном случае он используется для ссылки на контейнер меню.

Обработка щелчков за пределами меню:

  • Компонент использует хук useClickAway из библиотеки React-Use, чтобы обнаружить, когда пользователь щелкает за пределами меню. Когда это происходит, он запускает функцию, которая закрывает меню, устанавливая для isOpen значение false.

Рендеринг гамбургер-кнопки:

  • Компонент отображает кнопку, которая выглядит как гамбургер-значок. Эта кнопка служит тумблером для открытия и закрытия меню.
  • При нажатии на кнопку переключается значение isOpen, которое определяет, отображается меню или нет.

Отображение меню:

  • Если isOpen имеет значение true, это означает, что должно отображаться меню. В этом случае отображается список ссылок и значков.
  • Каждая ссылка представляет отдельную страницу или раздел. При нажатии на ссылку обновляется isOpen, чтобы закрыть меню.

Это основной поток работы этого компонента React! Он настраивает состояние для отслеживания статуса открытия/закрытия меню, обрабатывает щелчки вне меню, отображает кнопку для переключения меню и отображает содержимое меню, когда оно должно быть открыто.

Функция переключения гамбургер-меню
Функция переключения гамбургер-меню

Теперь давайте используем движение рамки для анимации мобильного меню. Откройте файл ./src/components/nav-mobile.tsx и добавьте следующий код:

//📂./src/components/nav-mobile.tsx
//📂./src/components/nav-mobile.tsx

import { useClickAway } from "react-use";
import { useRef } from "react";
import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Squash as Hamburger } from "hamburger-react";
import { routes } from "../routes";

export const NavMobile = () => {
  const [isOpen, setOpen] = useState(false);
  const ref = useRef(null);

  useClickAway(ref, () => setOpen(false));

  return (
    <div ref={ref} className="lg:hidden ">
      <Hamburger toggled={isOpen} size={20} toggle={setOpen} />
      <AnimatePresence>
        {isOpen && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.2 }}
            className="fixed left-0 shadow-4xl right-0 top-[3.5rem] p-5 pt-0 bg-neutral-950 border-b border-b-white/20"
          >
            <ul className="grid gap-2">
              {routes.map((route, idx) => {
                const { Icon } = route;

                return (
                  <motion.li
                    initial={{ scale: 0, opacity: 0 }}
                    animate={{ scale: 1, opacity: 1 }}
                    transition={{
                      type: "spring",
                      stiffness: 260,
                      damping: 20,
                      delay: 0.1 + idx / 10,
                    }}
                    key={route.title}
                    className="w-full p-[0.08rem] rounded-xl bg-gradient-to-tr from-neutral-800 via-neutral-950 to-neutral-700"
                  >
                    <a
                      onClick={() => setOpen((prev) => !prev)}
                      className={
                        "flex items-center justify-between w-full p-5 rounded-xl bg-neutral-950"
                      }
                      href={route.href}
                    >
                      <span className="flex gap-1 text-lg">{route.title}</span>
                      <Icon className="text-xl" />
                    </a>
                  </motion.li>
                );
              })}
            </ul>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

Давайте разберем части, связанные с движением:

AnimatePresence:

Компонент AnimatePresence — это специальный контейнер, предоставляемый библиотекой framer-motion. Он управляет жизненным циклом анимации для элементов, входящих и выходящих из DOM.

В этом коде он обтекает содержимое меню, указывая, что оно должно анимироваться при появлении или исчезновении.

Меню анимации контента:

Содержимому меню (той части, которая отображается при открытии меню) даются анимационные инструкции. Эти инструкции включают:

  • initial: Это определяет начальное состояние анимации. Здесь она запускается без непрозрачности (полностью невидимая).
  • animate: Это определяет, как продвигается анимация. Он указывает, что непрозрачность должна быть равна 1 (полностью видна), создавая эффект затухания.
  • exit: Это определяет, как ведет себя анимация, когда содержимое меню удаляется из DOM. Здесь он устанавливает непрозрачность равной 0, создавая эффект затухания.
  • transition:  Это управляет поведением анимации с течением времени. В этом случае его продолжительность установлена равной 0,2 секунды, что означает, что для завершения анимации требуется 0,2 секунды.

Анимация элемента ссылки:

Для каждого отдельного элемента ссылки в меню даны инструкции по анимации. Эти инструкции включают:

  • initial: Это задает начальное состояние анимации. Она начинается с элемента, который является маленьким (масштаб 0) и полностью невидимым (непрозрачность 0).
  • animate: Это определяет, как продвигается анимация. Он указывает, что элемент должен увеличиться до своего обычного размера (масштаб 1) и стать полностью видимым (непрозрачность 1).
  • transition: Это определяет поведение анимации. Установлена "пружинящая" анимация, которая создает эффект упругости. Значения жесткости и демпфирования контролируют упругость, в то время как задержка создает ступенчатый эффект, в результате чего анимация каждого элемента начинается немного позже предыдущего.

Эти анимации придают визуальный колорит меню и пунктам прейскуранта, обеспечивая плавный переход между ними при открытии и закрытии.

Анимированные пункты меню
Анимированные пункты меню

Поздравляем, теперь у вас есть полностью анимированное Hamburger Menu, отличная работа!

Вывод

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

Вы можете подписаться на меня в Twitter, где я делюсь другими полезными советами по веб-разработке. Счастливого кодирования!

Источник:

#JavaScript #React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу