ReactNative實現(xiàn)網(wǎng)易云音樂登錄波紋動畫

前言

個人一直比較喜歡網(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非高清的,我把波紋的顏色改成了白色??,方便大家看效果)

網(wǎng)易云音樂登錄頁面動畫(白色).gif

原圖.png

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

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容