最近做專案時需要實現一個漸變色的背景,真正實現時才發現要比我想象中花費的時間要多。
求大佬們點個關注,會定期寫原創和翻譯國外最新文章,跟大佬們一起學習進步,有問題或者建議歡迎加微信ruiwendelll,拉大家進技術交流群,一起探討學習,謝謝了!
天真的嘗試
要在React Native中顯示漸變,人們使用react-native-linear-gradient專案。我想看看是否有人試過動態地改變顏色,我找到了Animated Gradient Transition這個專案。仔細檢視程式碼,我的反應是這張的:
我不明白為什麼它需要兩個類,為什麼有這麼多的程式碼。我不想花太多時間去理解它了。我覺得我自己的思路就能簡單地解決這個問題:
- 使用
Animate.createAnimatedComponent
建立一個AnimatedLinearGradient
元件 - 插入某些顏色並傳遞給
AnimatedLinearGradient
很簡單吧?這裡是原始碼(會崩潰)。我使用它做了一個demo,然後就得到了error:
JSON value
<null>
of type NSNull cannot be converted to a UIColor. Did you forget to call processColor() on the JS side?
我求助了twttier,動畫不能使用arrays。儘管我覺得我做了正確的事。動畫庫不會處理任何陣列型別的值,所以底層的native元件不會得到動態的顏色。
這就是之前的程式碼如此龐大的原因。
正確構建
知道了動態化的限制。我們修改一下思路讓程式更健壯吧。
- 我需要主控制元件
AnimatedGradient
像LinearGradient
那樣工作。它接收color型別的陣列 - 在改變colors陣列的時候。我們想要一個動畫效果。為了實現這個,
AnimatedGradient
需要保持對之前colors陣列的追蹤。 - 因為我們不能使用arrays來改變值,我們要建立一個
GradientHelper
來獨立地接收顏色陣列。然後在Animated.createAnimatedComponent
中呼叫它。GradientHelper
會通過react-native-linear-gradient
包把array中的值傳給LinearGradient
控制元件。
為了便於理解,我們假設兩種顏色。
AnimatedGradient component
首先,建立一個AnimatedGradientHelper
在AnimatedGradient的建構函式中,我們將以跟蹤以前的顏色初始化prevColors狀態欄位。我們還初始化了一個名為tweener的Animated.Value。
在getDerivedStateFromProps中,我們獲取state.colors值並保持在state.prevColors中。我們設定了新的state.colors,我們重置了tweener。
在componentWillUpdate(也就是當引數改變時),我們將使tweener從0移動到1。
在render方法中,我們使用tweener,prevColors和colors來建立兩個顏色插值,並將它們分別傳遞給AnimatedGradientHelper。
Gradient Helper
在GradientHelper中,我們所做的就是獲取color1和color2引數,將它們放入一個陣列中,並將其傳遞給LinearGradient。我們這樣做是因為我們需要繞過Animated的限制。
下面是demo;
現在我們知道為什麼原始的程式碼如此之大。它必須做所有這些,並處理超過2種顏色的漸變。
如何動態改變
我們可以增加額外一步為其他屬性新增動畫。LinearGradient元件允許您指定漸變開始和結束的座標。為什麼不插入那些呢?這是一個更新的渲染方法。您可以猜測元件的其餘部分發生了什麼。原始碼
我們只需要通過做一些道具來調整我們的GradientHelper。程式碼
我們就得到了一個更酷的demo:
所以我們知道了如何在RN中實現動態漸變,和一點點動畫效果。