Я уже некоторое время использую один и тот же шаблон анимации в своих проектах для анимации элементов на экране. В простейшей форме у вас будет элемент с нулевой непрозрачностью, а затем измените стиль на непрозрачность, равную единице, с CSS-переходом, равным секунде.
Мы можем опираться на это, добавляя другие свойства, которые меняют переход, изменяя продолжительность, добавляя задержку или устанавливая пользовательское замедление.
<AnimateIn/> — это компонент React многократного использования, который я добавил, когда хочу быстро добавить в свои проекты некоторые анимационные эффекты. Простой служебный компонент, сочетающий CSS Animation с классами Tailwind для создания плавной, привлекательной анимации с минимальными усилиями.
Давайте посмотрим, как он используется. После импорта компонента определите состояния from
и to
с помощью классов Tailwind. Оберните целевой элемент в <AnimateIn/> , чтобы увидеть, как анимация оживает.
import AnimateIn from '../animation/AnimateIn'; <AnimateIn from="opacity-0 scale-90" to="opacity-100 scale-100" duration={500} > <YourComponent /> </AnimateIn>
Вот немного более сложный пример, в котором используется больше свойств для анимации заголовка и подзаголовка.
import AnimateIn from '../animation/AnimateIn'; <header> <AnimateIn as="h1" from="opacity-0 translate-y-32" to="opacity-100 translate-y-0" delay={500} duration={300} className="text-4xl" style={{transitionTimingFunction:"cubic-bezier(0.25, 0.4, 0.55, 1.4)"}} > My Big Headline </AnimateIn> <AnimateIn as="h2" from="opacity-0 scale-0" to="opacity-100 scale-100" delay={800} duration={500} className="text-lg" > This is a subtitle below the headline </AnimateIn> </header>
В примере с заголовком <AnimateIn/> используется для создания эффекта скольжения в сочетании с плавным появлением. Вот как каждое свойство влияет на анимацию:
as
свойство: Установив as="h1"
, мы сообщаем AnimateIn отображать анимацию как элемент <h1>
.
from
и to
: свойство from
делает заголовок заэкранным ( translate-y-32
, перемещая его на 32 единицы вниз) и невидимым ( opacity-0
). Свойство to
затем переводит заголовок в конечное положение (обратно к translate-y-0
) и делает его полностью видимым ( opacity-100
).
duration
: анимация начинается немедленно, без задержки и длится 300 мс.
className
: className="text-4xl"
применяет служебный класс Tailwind для установки размера шрифта, благодаря чему заголовок заметно выделяется.
style
: Пользовательский transitionTimingFunction
( cubic-bezier(0.25, 0.4, 0.55, 1.4)
) добавляет анимацию уникальной легкости, придавая ей эффект отскока.
В подзаголовке используется другой набор анимаций, дополняющих заголовок, создавая целостный визуальный поток.
as
свойство: Здесь as="h2"
отображает компонент как элемент <h2>
, подходящий для субтитров.
from
и to
свойств: субтитр сначала уменьшается до нуля ( scale-0
) и становится невидимым ( opacity-0
), затем масштабируется до своего естественного размера ( scale-100
) и становится полностью видимым ( opacity-100
). Этот эффект масштабирования в сочетании с плавным появлением добавляет анимации глубину.
delay
и duration
: субтитры также начинаются после задержки в 800 мс, то есть после полной анимации заголовка. Такой поэтапный подход гарантирует, что каждый элемент получит свое внимание.
className
: className="text-lg"
задает размер шрифта субтитров, делая его меньше заголовка, но все равно значимым.
Чтобы лучше понять, что происходит, давайте посмотрим исходный код <AnimateIn/> на Github :
<AnimateIn/> использует перехватчик useState
для инициализации состояния анимации с помощью свойства from
, которое должно быть одним или несколькими служебными классами Tailwind, устанавливая основу для начальной точки анимации до того, как начнется какая-либо анимация.
Первый хук useEffect
в компоненте предназначен для соблюдения предпочтений пользователя по уменьшению движения. При прослушивании медиа-запроса (prefers-reduced-motion: reduce)
поведение анимации зависит от системных настроек пользователя. Если предпочтение отдается ограниченному движению, анимация полностью пропускается, а состояние анимации напрямую устанавливается в свойство to
, что обеспечивает доступность интерфейса.
Второй хук useEffect
— это место, где находится логика анимации. Если пользователь не указал предпочтение уменьшенному движению, компонент устанавливает таймер, который меняет состояние анимации from
начального значения на конечное to
после указанной задержки. Этот переход создает визуальный эффект анимации.
Функция очистки этого перехватчика (оператор return) очищает таймер, предотвращая возможные утечки памяти, например, если компонент размонтируется до завершения анимации.
Вызов функции React.createElement
— это механизм рендеринга компонента. Он динамически создает элемент HTML на основе as
, что позволяет использовать компонент в различных элементах HTML. className
создается с использованием функции cn
, популяризированной shadcn , которая объединяет служебные классы Tailwind, пользовательское className
передаваемое в качестве реквизита, и текущее состояние анимации. Это динамическое назначение класса — это то, что применяет к элементу нужные стили и переходы.
Кроме того, существует атрибут style
, который можно передать для непосредственного задания свойств стиля в контейнере анимации. transitionDuration
устанавливается на основе свойства duration
, но оно автоматически переключается на 0ms
, если пользователь предпочитает уменьшенное движение, эффективно отключая анимацию, сохраняя при этом функциональность компонента.
Если вы хотите использовать <AnimateIn/> в своем проекте и он уже использует shadcn , то все необходимое у вас уже есть, просто скачайте AnimateIn.tsx и добавьте его в свои компоненты.
В противном случае вам понадобится установить Tailwind , а также mxcn
— полезную утилиту для объединения классов попутного ветра.
Как и shadcn, <AnimateIn/> представляет собой компонент многократного использования, который вы можете копировать и вставлять в свои приложения и настраивать в соответствии со своими потребностями. Код ваш.
Кроме того, я собрал красивую демонстрационную страницу для экспериментов с созданием различных анимаций с помощью <AnimateIn/> на animate-in.vercel.app .
Также опубликовано здесь