Набор практических примеров с кодом: от простых появления и hover до scroll-triggered и layout-анимаций. Ориентировочное время — 60–90 минут на воспроизведение и эксперименты.
Что вы изучите
Установку Framer Motion 7.8 (2025) в проект React 18.2 (2022) и базовые анимации появления и hover.
Создание scroll-triggered анимаций с использованием Intersection Observer и Framer Motion.
Layout animations: анимация перестроения списка и переходов между состояниями с layoutId.
Жесты (drag, pan) и оркестровка анимаций через Variants и control API.
Практические рекомендации по производительности и список типичных ошибок с их исправлением.
Требования
Node 20 (2023) или новее, npm 10 / pnpm 8. Минимум 2 ядра CPU, 4 ГБ ОЗУ для локальной разработки.
React 18.2 (2022) или React 19 (2025) — примеры рассчитаны на React 18.2, но совместимы с React 19.
Framer Motion 7.8 (2025) — пакет framer-motion@7.8 использован в примерах.
TypeScript 5.6 (2025) при использовании типов; примеры даны в JavaScript, с указанием типов там, где нужно.
Порты: dev-сервер по умолчанию http://localhost:3000. Развертывание на VPS/CI не требуется для воспроизведения.
Почему Framer Motion?
и категории на сайте содержат дополнительные примеры оптимизаций и полноценных проектов с интеграцией Framer Motion в крупные приложения.
0
Статья была полезной?
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…
Framer Motion предлагает декларативный API для анимаций в React, объединяя простоту и производительность благодаря рендер-оптимизациям и использованию requestAnimationFrame. Для задач интерфейса — появления компонентов, анимации переходов layout и управления жестами — Framer Motion обеспечивает минимальную обвязку и точный контроль через Variants и API контроллеров.
В итоге вы получите набор готовых паттернов, которые можно использовать в продуктивных приложениях: карточки с hover-анимацией, list-reorder с layout-переходами, scroll-triggered секции и анимированные модальные окна. Примеры в статье рассчитаны на 60–90 минут практики и до 3 часов для полного погружения с доработкой и тестами.
Скриншот базовой анимации: карточки, появляющиеся с эффектом fade-in
Шаг 1: базовые анимации
Команда: установка пакета и минимальный компонент с эффектом появления и hover.
Пояснение: команда инициирует проект и устанавливает React 18.2 и Framer Motion 7.8 (релиз 2025). Размер пакета framer-motion ~1.2 МБ в виде npm-пакета; установочный процесс обычно занимает 20–40 секунд в зависимости от сети.
// src/components/Card.jsx
import React from 'react'
import { motion } from 'framer-motion'
export function Card({ title, children }) {
return (
{title}
{children}
)
}
Ожидаемый вывод: компонент плавно появляется и слегка масштабируется при наведении. На dev-сервере вы увидите плавную анимацию при монтировании компонента.
// Пример запуска dev-сервера
npm run dev
// Ожидаемый лог (сокращённо):
// Vite v4.5.0 dev server running at:
// > Local: http://localhost:3000
Типичная ошибка: "Module not found: Can't resolve 'framer-motion'". Исправление: проверьте, что пакет установлен, выполните npm install framer-motion@7.8 и перезапустите dev-сервер. Если ошибка про Peer Dependency, обновите React до версии, совместимой с пакетом.
Шаг 2: scroll-triggered
Команда: небольшая утилита с Intersection Observer + Framer Motion для запуска анимации при скролле.
npm install use-intersection-observer --save
// или используйте встроенный IntersectionObserver в браузере
Пояснение: Framer Motion не включает встроенный scroll-trigger; типичный паттерн — комбинация Intersection Observer и animation controls из framer-motion. Это позволяет запускать анимацию один раз при появлении элемента в viewport.
Успешный вывод: при скролле к элементу он плавно появляется. На 2026-цельных приложениях допустим запуск анимаций только при первом попадании в viewport для экономии ресурсов.
// Возможная ошибка:
// TypeError: (0 , react_intersection_observer__WEBPACK_IMPORTED_MODULE_1__.useInView) is not a function
// Исправление:
// Проверьте версию пакета react-intersection-observer; обновите до 9.x (2024-2026 релизы).
// Либо используйте нативный IntersectionObserver: new IntersectionObserver(...).
Скриншот scroll-triggered анимации: элементы появляются при прокрутке
Шаг 3: layout animations
Команда: пример анимации перестроения списка при добавлении/удалении элемента с использованием layout и layoutId.
npm install framer-motion@7.8
// код добавьте в существующий проект
Пояснение: layout animations используют вычисления геометрии DOM и анимируют изменения layout между рендерами. Важно — не использовать layout на слишком большом количестве элементов одновременно, чтобы не вызвать перерасчёт макета (reflow) и просадки FPS.
Ожидаемый вывод: при добавлении элемента список плавно перестраивается, предыдущие элементы перемещаются с анимированными переходами. Для CSS-heavy layout проверьте, что используются аппаратно-ускоряемые свойства (transform, opacity) и минимальное количество перепаковок.
// Типичная ошибка:
// Warning: Expected layoutId to be a string but got undefined
// Исправление:
// Убедитесь, что свойство layoutId задано и уникально для связанных элементов, или используйте просто layout вместо layoutId.
Шаг 4: жесты и drag
Команда: демонстрация перетаскивания карточек с ограничением по оси и snap-to-grid.
// Нет установки, используем framer-motion API
// Реализация в файле src/components/DragCard.jsx
import React from 'react'
import { motion } from 'framer-motion'
export function DragCard(){
return (
Перетащите меня по оси X
)
}
Пояснение: drag поддерживает ограничения через dragConstraints и управление упругостью через dragElastic. Для мобильных устройств проверяйте конфликт с нативной прокруткой; используйте onDragStart чтобы подавлять свайп или избегать pointer-events конфликтов.
// Ожидаемый результат:
// Элемент перетаскивается по оси X, возвращается в границы, при отпускании отрабатывается spring-анимация.
// Возможная ошибка:
// dragConstraints не работает
// Исправление:
// Если constraints переданы как DOM-реф, убедитесь, что ref прикреплён, или используйте числовые ограничения {left,right}.
Шаг 5: оркестровка анимаций и Variants
Команда: реализация перехода состояний с помощью Variants и управления порядком запуска через stagger.
Пояснение: Variants позволяют описать состояния для группы компонентов и централизованно управлять поведением через родительские переходы. Для синхронизации нескольких слоёв анимации используйте staggerChildren, delayChildren и when (beforeChildren/afterChildren).
// Возможная ошибка:
// Анимация не синхронизируется: элементы стартуют одновременно
// Исправление:
// Убедитесь, что родитель действительно имеет props initial/animate/variants и дочерние элементы используют variants (а не отдельные animate props).
Какие хорошие best practices?
Используйте декларативный подход: описывайте состояния через Variants и избегайте многочисленных inline-атрибутов animate в каждом компоненте, если требуется координация. Для крупных списков применяйте виртуализацию (react-window, 2022) и анимируйте только видимые элементы. Ограничивайте использование layout-анимаций — применяйте layout выборочно для элементов, которые действительно перемещаются в UI. Предпочитайте аппаратно-ускоряемые CSS-свойства (transform и opacity) для плавности. Для тестирования анимаций на CI используйте headless-браузеры и snapshot-тесты по визуальным ключам, а не по пикселям.
Для сборки укажите флажки оптимизации в bundler: tree-shaking, code-splitting и минимизацию CSS. Если приложение использует server-side rendering, проверяйте, что начальные состояния (initial) согласованы между сервером и клиентом, чтобы избежать layout shift и мерцания элементов при гидратации.
Используйте prefers-reduced-motion для уважения настроек пользователя.
Для сложных последовательностей применяйте Animation Controls (useAnimation).
Профилируйте FPS в реальных устройствах (iPhone SE/Android 8) для оценки производительности.
Как не убить производительность?
Производительность критична: неправильное использование layout-анимаций или анимация большого количества DOM-элементов одновременно приводит к dropped frames. Ограничьте количество одновременно анимируемых элементов до 20–30 на страницу для обеспечения стабильных 60 FPS на большинстве устройств. Для мобильных устройств целевой минимум — 30 FPS. Проверяйте время выполнения функций: расчёты layout (getBoundingClientRect) занимают десятки мс при больших деревьях, поэтому избегайте вызова таких вычислений в цикле.
Практические шаги: вместо анимации top/left используйте transform; минимизируйте reflow и repaint; используйте will-change аккуратно — только для кратких периодов. При необходимости перенесите тяжёлые операции в Web Worker (логика, не DOM) и оптимизируйте рендер списка через виртуализацию и memoization (React.memo, useMemo).
Ошибка: мерцание при гидратации SSR — фикс: синхронизируйте initial состояния и избегайте разных initial/animate при CSR/SSR.
Для CI и тестов ставьте порог производительности: например, максимальное время реакции на интерактивность — 200 мс на ключевые сценарии пользовательского пути. Мониторинг в проде: записывайте метрики рендеринга и FPS на первых секундах взаимодействия.
Как начать использовать Framer Motion с TypeScript?
Добавьте типы: установите TypeScript 5.6 (2025) и используйте официальные типы, встроенные в пакет framer-motion@7.8. Для компонентов объявляйте пропсы через интерфейс: interface Props { title: string }. При использовании motion() с кастомными компонентами применяйте motion.customComponent или generics: motion.MyComponent — при этом старайтесь минимизировать any и явно указывать HTML-элементы через motion.button для корректной типизации событий и атрибутов.
Что делать, если анимации дергаются на мобильных устройствах?
Проверьте: используются ли аппаратно-ускоряемые свойства (transform, opacity). Уберите тяжелые операции в рендерах, минимизируйте количество одновременно анимируемых элементов. Для iOS протестируйте на реальных устройствах — эмуляторы часто дают более стабильный результат. Если проблема в touch-gestures, проверьте конфликт с нативной прокруткой и используйте пассивные обработчики событий или подавляйте события в onDragStart.
Почему layout-анимации отображаются по-разному при гидратации?
Различия при SSR/CSR часто вызваны различиями в initial-статусах на сервере и клиенте. Убедитесь, что серверный HTML и стиль задают те же начальные размеры и не зависят от window или случайных чисел. Для критичных переходов используйте CSS-резервные состояния и синхронизируйте initial и animate пропсы, либо выполняйте некоторые переходы только на клиенте (например, проверкой typeof window !== 'undefined').
Сколько анимаций безопасно запускать одновременно?
Практическое правило: до 20–30 простых анимаций одновременно обычно безопасно для современных десктопов (60 FPS). Для мобильных устройств ориентируйтесь на 10–15 одновременно активных анимированных элементов. Если количество превышает эти значения, используйте виртуализацию, batch-анимации (stagger) и оптимизацию DOM-структуры.
Framer Motion для React: 10 полезных анимаций | KtoHto
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…