React Spring - это "spring-physics based animation library", что можно перевести как "основанная на физике пружин (spring - пружина, рессора)" или, поскольку речь идет о пружинах, "на упругости (пружинистости?) библиотека для анимации". Разработчики данной библиотеки заявляют, что она способна удовлетворить большую часть потребностей, возникающих при разработке пользовательских интерфейсов.
В настоящее время react-spring предоставляет 5 хуков (примитивов для анимации):
useSpring - простая пружина, перемещающая данные из точки "а" в точку "б"
useSprings - несколько пружин, для списков, где каждая пружина перемещает данные...
useTrail - несколько пружин с общим набором данных, одна пружина следует за другой
useTransition - для реализации переходов при монтировании/размонтировании компонентов (например, для элементов списка, которые добавляются/удаляются/обновляются). Обратите внимание: частью разрабатываемого в настоящее время командой React конкуретного режима является хук useTransition, предназначенный для обработки переходов между состояниями компонента. Как будет решена эта коллизия, покажет время
useChain - для постановки в очередь или выстраивания в цепочку нескольких анимаций
animated - это специальная фабрика, библиотека для выполнения анимации за пределами React (по соображениям производительности). Что делает animated? Она расширяет нативные элементы, чтобы они могли принимать анимированные значения (как styled в стилизованных компонентах).
Пружина анимирует значение от одного состояния до другого. Обновления суммируются, пружина запоминает переданные значения. Полученные пропы не являются статическими, они автоматически обновляются.
animated способна анимировать не только HTML-элементы, как в приведенном выше примере, но также React-компоненты, нативные компоненты, стилизованные компоненты и т.д.
1 2 3 4 5 6 7 8 910
// компонент ReactconstMyAnimatedComponent=animated(MyComponent);// React NativeconstAnimatedView=animated(View);// styled-components, emotion и т.д.constAnimatedListItem=styled(animated.li)` ...`;
В случае, когда нам требуется зафиксировать или экстраполировать значения, можно воспользоваться функцией interpolate, которую содержит каждое анимированное значение. Данная функция принимает функцию или объект с диапазоном значений. Из интерполяций можно формировать цепочки, позволяющие подключать одни вычисления к другим или повторно использовать произведенные ранее вычисления.
Причина, по которой интерполяцию лучше выполнять в представлении, а не в пружине, заключается в том, что интерполяция представления работает немного быстрее и занимает меньше места
import{useSpring,animated,interpolate}from'react-spring'const{o,xyz,color}=useSpring({from:{o:0,xyz:[0,0,0],color:'red'}o:1,xyz:[10,20,5],color:'green'})return(<animated.divstyle={{// По-возможности, всегда используйте обычные анимированные значения,// когда они просто передаютсяcolor,// Пока не потребуется их интерполироватьbackground:o.interpolate(o=>`rgba(210, 57, 77, ${o})`),// Что также работает с массивамиtransform:xyz.interpolate((x,y,z)=>`translate3d(${x}px, ${y}px, ${z}px)`),// Для комбинации нескольких значений используется утилита `interpolate`border:interpolate([o,color],(o,c)=>`${o*10}px solid ${c}`),// Можно создавать диапазоны и даже цепочки из нескольких интерполяцийpadding:o.interpolate({range:[0,0.5,1],output:[0,0,10]}).interpolate(o=>`${o}%`),// Разрешена интерполяция строкborderColor:o.interpolate({range:[0,1],output:['red','#ffaabb']}),// Существует сокращенный синтаксис для диапазонов без настроекopacity:o.interpolate([0.1,0.2,0.6,1],[1,0.1,0.5,1])}}>{o.interpolate(n=>n.toFixed(2))}/* интерполяция текста */</animated.div>)
Одним из отличий хуков от пропов для рендеринга является то, что хуки "не знают" о представлении. Поэтому хуки не умеют работать со значением auto. Это может показаться недостатком, однако, вычисление размера элемента с помощью таких хуков как useResizeAware или useMeasure никогда не было таким простым, как сейчас.
Проп to также позволяет превращать анимацию в скрипт и объединять анимации. Поскольку такие анимации будут асинхронными, передача свойства from с начальными значениями является обязательной, иначе, пропы будут пустыми.
useSprings возвращает пружины (springs) в виде массива и две функции: для обновления анимации (set) и ее остановки (stop)
123456789
const[springs,set,stop]=useSprings(number,(index)=>({opacity:1}));// Обновляем пружины новыми пропамиset((index)=>({opacity:0}));// Останавливаем все пружиныstop();
springs - это массив, содержащий анимированные пропы
Анимированная TransitionGroup. useTransition принимает элементы, ключи (которые могут иметь значение null, если элементы являются атомарными) и жизненные циклы. Данный хук предназначен для анимирования добавления/удаления элементов.
Жизненные циклы initial/from/enter/update/leave могут быть объектами, массивами или функциями. Функция позволяет возвращать объект, массив или функцию для осуществления перехода через несколько состояний. При передаче массива можно реализовать базовый мультипереход без доступа к элементу
Устанавливает порядок выполнения определенных ранее хуков анимации. useChain принимает массив со ссылками (refs) на анимации, что блокирует самостоятельный запуск анимаций. Порядок элементов в массиве определяет порядок выполнения анимаций
1 2 3 4 5 6 7 8 910111213141516
// Создаем пружину и добавляем к ней ссылкуconstspringRef=useRef()constprops=useSpring({...,ref:springRef})// Создаем переход и добавляем к нему ссылкуconsttransitionRef=useRef()consttransitions=useTransition({...,ref:transitionRef})// Сначала запускает пружину, затем переходuseChain([springRef,transitionRef])// Используем анимированные пропы как обычноreturn(<animated.divstyle={props}>{transitions.map(({item,key,props})=>(<animated.divkey={key}style={props}/>))}</animated.div>)
В качестве второго аргумента useChain принимает опциональный объект с настройками: timeSteps и timeFrame (по умолчанию имеет значение 1000 мс). timeSteps - массив с отступами от 0 до 1, определяющими начало и конец timeFrame
Позволяет формировать цепочки, композиции из анимаций.
Keyframes - это фабрика для расширения spring и trail. Сначала определяются именованные слоты с анимируемыми свойствами. Все неизвестные свойства считаются свойствами to. Возвращается компонент со специальным свойством state с названием одного из слотов.
Слот принимает:
объект со свойствами
массив объектов, выстраиваемых в цепочку
функцию, позволяющую создавать анимации в виде скриптов или формировать циклы
1 2 3 4 5 6 7 8 910111213141516171819
// Допускается создание ключевых кадров для `Spring` и `Trail`constContainer=Keyframes.Spring({// Единичное значениеshow:{opacity:1},// Цепочка из анимаций (массив)showAndHide:[{opacity:1},{opacity:0}],// Функция с побочными эффектами с доступом к пропам компонентаwiggle:async(next,cancel,ownProps)=>{awaitnext({x:100,config:config.wobbly});awaitdelay(1000);awaitnext({x:0,config:config.gentle});},});return(<Containerstate="showAndHide">{(styles)=><divstyle={styles}>Hello</div>}</Container>);
Parallax создает "прокручиваемый" (scroll) контейнер. Ему передается любое количество ParallaxLayer, которые перемещаются согласно их отступам (offsets) и скоростям (speeds)