前言
個人一直比較喜歡網(wǎng)易云音樂,所以就想使用react native 仿寫一個,當然開篇就是登錄頁面,我這邊是以IOS的UI為準的,看到網(wǎng)易的登錄頁面后,被驚艷到了,想到底該怎么實現(xiàn)這種縹緲的波紋,有同學感興趣的話,可以退出網(wǎng)易的賬號,仔細觀察下,還是有很多細節(jié)處理的很好的......本篇基于ReactNative實現(xiàn)點贊飄心動畫實現(xiàn)
第一步
在構造函數(shù)中聲明多個用來驅(qū)動動畫的Animate變量,我這里創(chuàng)建了10個,當然你也可以創(chuàng)建更多,但是不建議,十個及以下最好,因為同時在頁面上顯示的圓圈不會那么多,并且因為這個動畫是改變視圖的寬高屬性,無法調(diào)用原生的UI線程,純粹的JS執(zhí)行來執(zhí)行動畫,太多的話,非常容易掉幀.以及一個用來做視圖于動畫匹配的變量,可能有同學會好奇為什么要初始化這么多變量,我理解的是在React Native中任何可顯示的內(nèi)容都不可能憑空出現(xiàn),如果頁面上有十個view,那就一定有十個實例,即便他們都一樣
constructor(props) {
super(props);
this.animViewIndex = 0;
this.viewArr = Array(10).fill()
this.viewArr.map((_, index) => this[`animView${index}`] = new Animated.Value(0))
}
第二步
在render函數(shù)中使用循環(huán)聲明多個View,因為這個動畫的本質(zhì)其實就是圓圈的半徑變大,然后透明度逐漸增大,所以需要控制的變量很少,我這里初始化圓圈的大小為74,這個跟中間的LOGO大小保持一致.
這里有個關于動畫的細節(jié)需要說一下,在做圖片的大小變形的時候,最好使用transform的scaleX,scaleY或者scale,因為在IOS中每次調(diào)整組件的寬高,都需要重新剪裁和縮放原始圖片,這會帶來很大的性能開銷,圖像大小跟內(nèi)存消耗成正比,不過在我們這個示例中卻無法使用,因為我們變動的是視圖的大小,而非圖片,如果使用scale的話,會造成視圖的失真,比如邊框變寬等問題,希望同學們注意
<View style={LoginIndexSty.common.outer}>
<TouchableOpacity onPress={() => this.startAnimate()}>
<Logo/>
</TouchableOpacity>
{
this.viewArr.map((_, index) => {
let s = 74;
let size = this[`animView${index}`].interpolate({
inputRange: [0, 1],
outputRange: [1, WIDTH * 1.4]
})
let border = this[`animView${index}`].interpolate({
inputRange: [0, 1],
outputRange: [s / 2, WIDTH * 0.7]
})
let opacity = this[`animView${index}`].interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0, 1, 0]
})
return <Animated.View
key={index}
style={[LoginIndexSty.common.animateContainer, {
width: size,
height: size,
// transform: [{scale: size}],
borderRadius: border,
opacity,
}]}/>
})
}
</View>
第三步
使用構造函數(shù)中定義的驅(qū)動動畫的變量來跟我們的視圖一一對應,然后根據(jù)動畫的當前值,判斷是否驅(qū)動下一個視圖,目前動畫的時間設置的是7秒鐘,這個是根據(jù)我個人觀察網(wǎng)易云音樂的時間得來的,具體的...可能得拿秒表計時一下...??
這里有一個細節(jié),在最后的一行,是為了做隨機時間執(zhí)行動畫,因為通過觀察發(fā)現(xiàn)網(wǎng)易云音樂的波紋不是固定時間做動畫的
startAnimate = () => {
this[`animView${this.animViewIndex}`].setValue(0)
let currentValue = this[`animView${this.animViewIndex}`].__getValue()
if (currentValue !== 0) {
this.animViewIndex++
}
Animated.timing(this[`animView${this.animViewIndex}`],
{
toValue: 1,
duration: 7000,
}
).start(() => {
this[`animView${this.animViewIndex}`].setValue(0)
})
if (this.animViewIndex > 8) {
this.animViewIndex = 0
}
this.animViewIndex++
setTimeout(() => this.startAnimate(), Math.floor(Math.random() * (1000)) + 500)
}
看成品(由于gif非高清的,我把波紋的顏色改成了白色??,方便大家看效果)


如果覺得這些內(nèi)容對你有用,那點個贊再走吧??,歡迎轉發(fā),還請注明出處,謝謝