Анимационни градиенти в React Native

Работя върху личен проект, наречен KaoCards, приложение за флаш карти за запомняне на имена и лица на хората. Когато проектирах продукта, реших, че е готино да имам анимиран градиент като фон, но когато се опитах да го внедря, се оказа, че е повече работа, отколкото си мислех.

Ето тук е историята как успях да го накарам да работи. Ако искате TL; DR, направих хранилище, което можете да следвате.

Наивен опит.

Ако искате да разберете това, важно е да знаете защо първият ми опит не даде резултат.

За да покажат градиент в React Native, хората използват проект, наречен react-native-linear-gradient. Исках да видя дали някой се е опитал да анимира цветовете и намерих примера за преход на анимационен градиент на това репо. Разглеждайки кода, имах тази реакция:

Не разбрах защо са му нужни два класа, защо имаше толкова много код. Не мислех, че ти трябва толкова много Реших, че няма да се занимавам да разбирам всичко това. Реших, че начинът да го направя трябва да е доста прост:

  1. Създайте компонент AnimatedLinearGradient с помощта на Animate.createAnimatedComponent
  2. Интерполирайте някои цветове и ги предайте на AnimatedLinearGradient

Просто, нали? Ето източника (той ще се срине). Направих експериментално приложение, пуснах го и след това, утроба на матката. Получаваме грешката:

Стойността JSON `` от тип NSNull не може да бъде преобразувана в UIColor. Забравихте ли да се обадите на processColor () от страна на JS?

Нещо някъде по линията не получаваше цветови стойности. Затова се обърнах към Twitter за помощ:

Джейсън Браун отговори с ключовото прозрение:

Аааах ок! Animated не работи с масиви. Въпреки че реших, че правя всичко правилно, библиотеката на анимираните изображения не обработва стойностите на реквизит от масив, така че основният основен компонент получава боклук вместо да получава анимирани цветове.

Стана ясно защо оригиналният пример е толкова голям.

Изграждане правилно.

Добре, разбирайки това ограничение за Animated, нека да променим нашия план за игри и да го направим малко по-стабилен.

  1. Искаме основният ни компонент, AnimatedGradient, да работи точно като LinearGradient. Тя трябва да вземе масив от цветове.
  2. Искаме преход да настъпи, когато сменим цветовете на опора. За да направите това, AnimatedGradient трябва да следи предишните цветове.
  3. Тъй като не можем да анимираме стойности в масиви, можем да изградим GradientHelper компонент, който приема цветовете поотделно, и да извикаме Animated.createAnimatedComponent за това. GradientHelper ще постави стойностите в масив и ще ги предаде на компонента LinearGradient от пакета за реакция-нативен-линеен градиент.

За да опростим нещата за този пример, ще предположим, че цветовият масив има само 2 стойности.

Анимиран компонент на радиация

Програмен код

Първо, ние ще създадем AnimatedGradientHelper от нашия GradientHelper, който ще направим малко.

В конструктора на AnimatedGradient ще инициализираме състояние на състояниеCoCors, за да следим предишните цветове. Ние също инициализираме Animated.Value, наречен туитър.

В getDerivedStateFromProps вземаме стойността state.colors и се придържаме в state.prevColors. Задаваме новите state.colors и нулираме пинсета.

В компонент компонент WillUpdate (известен също при промяна на реквизита), ще накараме пинсета да премине от 0 на 1.

В метода на изобразяване използваме пинсета, prevColors и цветове, за да създадем две цветни интерполации и ги предаваме поотделно на нашия AnimatedGradientHelper.

Градиент Помощник

Програмен код

В GradientHelper всичко, което правим, е да вземем реквизита color1 и color2, да ги поставим в масив и да ги предадем на LinearGradient. Правим това, защото трябва да заобиколим ограниченията на Animated.

И това е същността на това. Ето демонстрацията:

Сега знаем защо оригиналният пример е толкова голям. Трябваше да направи всичко това и да се справи с градиенти с повече от 2 цвята.

Но чакай, какво още можем да оживим?

Всъщност можем да преминем на допълнителната стъпка и да анимираме други свойства. Компонентът LinearGradient ви позволява да зададете координати за началото и края на градиента. Защо да не интерполирате и тях? Ето актуализиран метод за изобразяване. Вероятно можете да се досетите какво се е случило в останалата част от компонента. източник

Просто ще трябва да опънем малко GradientHelper, като направим нещо с реквизита. източник

И сега имаме по-готина демонстрация.

Успях да комбинирам този анимиран градиент с някои други анимации, за да създам страхотен фонов ефект за моя проект KaoCards:

И така, сега знаете как да анимирате градиентите в React Native и малко повече за това как работи Animated. Какви други свойства смятате, че можете да оживите?

Благодаря на Джейсън Браун за предоставената ключова представа. Всичко, което научих за анимацията на неща в React Native, научих от него. Уверете се, че го следвате в Twitter и проверете курса му React Native Animations.