React Native填坑之旅--動畫

React Native填坑之旅--Button篇
React Native填坑之旅--動畫
React Native填坑之旅--HTTP請求篇

動畫是提高用戶體驗(yàn)不可缺少的一個(gè)元素淌友。恰如其分的動畫可以讓用戶更明確的感知當(dāng)前的操作是什么。

無疑在使用React Native開發(fā)應(yīng)用的時(shí)候也需要?jiǎng)赢嬐驴_@就需要知道RN都給我們提供了那些動畫,和每個(gè)動畫可以處理的功能有哪些播聪。

填坑材料Animated

動畫API提供了一些現(xiàn)成的組件:Animated.View癣猾,Animated.TextAnimated.Image默認(rèn)支持動畫慕蔚。動畫API會調(diào)用iOS或者Android的本地代碼來完成這些組件的位移、大小等動畫巍佑。這樣各種動畫在視覺上可以非常的流暢倒源。

一個(gè)繞著屏幕轉(zhuǎn)的動畫

繞著屏幕轉(zhuǎn)的動畫:

<--< 
|  | 
V--^ 

基本代碼

export default class AnimatedSquare extends React.Component {
    constructor(props) {
        super(props);
        // 1
        this.state = {
            pan: new Animated.ValueXY
        }
    }

    getStyle() {
        return [
            styles.square,
            {
                transform: this.state.pan.getTranslateTransform()
            }
        ];
    }

    render() {
        return (
            <View style={styles.container}>
                <Animated.View style={this.getStyle()} />
            </View>
        );
    }
}

解釋一下:

  1. this.state里用了Animated.ValueXY的實(shí)例。這樣Animated動畫就知道需要處理的是X和Y兩個(gè)方向的值句狼。
  2. getStyle()方法會返回一個(gè)數(shù)組笋熬,因?yàn)閯赢嬓枰?code>square和transform兩個(gè)樣式值。getTranslateTransform()方法會獲得一個(gè)數(shù)組:[{translateX: xValue}, {translateY: yValue}]腻菇。xValueyValue就是根據(jù)我們開始的時(shí)候設(shè)置的Animated.ValueXY解析出來的胳螟。
  3. 最后設(shè)置Animated.View。也就是動畫最終作用的元素(或者叫做視圖)筹吐。

依賴和樣式

依賴項(xiàng):

import React from 'react';
import {
    Dimensions,
    StyleSheet,
    View,
    Animated
} from 'react-native';

let {
    width,
    height
} = Dimensions.get('window');

const SQUARE_DIMENSIONS = 30;

樣式:

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    square: {
        width: SQUARE_DIMENSIONS,
        height: SQUARE_DIMENSIONS,
        backgroundColor: 'blue'
    }
});

動起來

我們準(zhǔn)備讓這個(gè)目標(biāo)物體糖耸,一個(gè)方框,從左上角:x = 0, y = 0到左下角: x = 0, y = (screenHeight - squreHeight)丘薛。

const SPRING_CONFIG = {tension: 2, friction: 3};

    componentDidMount() {
        Animated.spring(this.state.pan, {
            ...SPRING_CONFIG,
            toValue: {x: 0, y: height - SQUARE_DIMENSIONS}                        // return to start
        }).start();
    }

componentDidMount方法是RN組件的生命周期方法嘉竟,在組件完成html渲染的時(shí)候調(diào)用。在組件渲染完成后開始動畫洋侨。

我們指定了SPRING_CONFIG為彈簧動畫的彈力和摩擦力舍扰,值都不大。所以這個(gè)方框會在屏幕的每個(gè)角稍微彈幾下希坚。

依次的動動動边苹。。裁僧。

我們可以讓幾個(gè)動畫按照順序依次執(zhí)行个束。這些動畫會一個(gè)挨一個(gè)的執(zhí)行慕购。sequence方法是動畫API組織動畫的多種方式之一。也可以使用parallel來組織茬底,這樣幾個(gè)動畫會并行執(zhí)行沪悲。

    componentDidMount() {
        Animated.sequence([
            Animated.spring(this.state.pan, {
                ...SPRING_CONFIG,
                toValue: {x: 0, y: height - SQUARE_DIMENSIONS} //animate to bottom left
            }),
            Animated.spring(this.state.pan, {
              ...SPRING_CONFIG,
              toValue: {x: width - SQUARE_DIMENSIONS, y: height - SQUARE_DIMENSIONS} // animated to bottom right
            }),
            Animated.spring(this.state.pan, {
                ...SPRING_CONFIG,
                toValue: {x: width - SQUARE_DIMENSIONS, y: 0} //animate to top right
            }),
            Animated.spring(this.state.pan, {
              ...SPRING_CONFIG,
              toValue: {x: 0, y: 0} // return to start
            })
        ]).start(cb);
    }

我們定義了四個(gè)彈簧動畫。這個(gè)四個(gè)一組的動畫執(zhí)行的順序就是前文指定的順序阱表。

重復(fù)動畫

調(diào)用動畫的start方法的時(shí)候可以傳入一個(gè)回調(diào)方法作為參數(shù)殿如。這個(gè)回調(diào)方法會在這一組動畫執(zhí)行完成之后調(diào)用。在本例中捶枢,每次動畫執(zhí)行完之后會再次調(diào)用開始動畫的方法。

    componentDidMount() {
        this.startAndRepeat();
    }

    startAndRepeat() {
        this.triggerAnimation(this.startAndRepeat);
    }

    triggerAnimation(cb) {
        Animated.sequence([
            Animated.spring(this.state.pan, {
                ...SPRING_CONFIG,
                toValue: {x: 0, y: height - SQUARE_DIMENSIONS} //animate to bottom left
            }),
            Animated.spring(this.state.pan, {
              ...SPRING_CONFIG,
              toValue: {x: width - SQUARE_DIMENSIONS, y: height - SQUARE_DIMENSIONS} // animated to bottom right
            }),
            Animated.spring(this.state.pan, {
                ...SPRING_CONFIG,
                toValue: {x: width - SQUARE_DIMENSIONS, y: 0} //animate to top right
            }),
            Animated.spring(this.state.pan, {
              ...SPRING_CONFIG,
              toValue: {x: 0, y: 0} // return to start
            })
        ]).start(cb);
    }

調(diào)用triggerAnimation方法開始動畫飞崖,并傳入再次開始動畫的方法startAndRepeat烂叔。

完整代碼

import React from 'react';
import {
    Dimensions,
    StyleSheet,
    View,
    Animated
} from 'react-native';

let {
    width,
    height
} = Dimensions.get('window');

const SQUARE_DIMENSIONS = 30;
const SPRING_CONFIG = {tension: 2, friction: 3};

export default class AnimatedSquare extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            pan: new Animated.ValueXY
        }

        // bind
        this.startAndRepeat = this.startAndRepeat.bind(this);
        this.getStyle = this.getStyle.bind(this);
        this.startAndRepeat = this.startAndRepeat.bind(this);
        this.triggerAnimation = this.triggerAnimation.bind(this);
    }

    componentDidMount() {
        this.startAndRepeat();
    }

    startAndRepeat() {
        this.triggerAnimation(this.startAndRepeat);
    }

    getStyle() {
        return [
            styles.square,
            {
                transform: this.state.pan.getTranslateTransform()
            }
        ];
    }

    triggerAnimation(cb) {
        Animated.sequence([
            Animated.spring(this.state.pan, {
                ...SPRING_CONFIG,
                toValue: {x: 0, y: height - SQUARE_DIMENSIONS} //animate to bottom left
            }),
            Animated.spring(this.state.pan, {
              ...SPRING_CONFIG,
              toValue: {x: width - SQUARE_DIMENSIONS, y: height - SQUARE_DIMENSIONS} // animated to bottom right
            }),
            Animated.spring(this.state.pan, {
                ...SPRING_CONFIG,
                toValue: {x: width - SQUARE_DIMENSIONS, y: 0} //animate to top right
            }),
            Animated.spring(this.state.pan, {
              ...SPRING_CONFIG,
              toValue: {x: 0, y: 0} // return to start
            })
        ]).start(cb);
    }

    render() {
        return (
            <View style={styles.container}>
                <Animated.View style={this.getStyle()} />
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    square: {
        width: SQUARE_DIMENSIONS,
        height: SQUARE_DIMENSIONS,
        backgroundColor: 'blue'
    }
});

更多相關(guān)代碼請移步:https://github.com/future-challenger/petshop/tree/master/client/petshop

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市固歪,隨后出現(xiàn)的幾起案子蒜鸡,更是在濱河造成了極大的恐慌,老刑警劉巖牢裳,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逢防,死亡現(xiàn)場離奇詭異,居然都是意外死亡蒲讯,警方通過查閱死者的電腦和手機(jī)忘朝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來判帮,“玉大人局嘁,你說我怎么就攤上這事』耷剑” “怎么了悦昵?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長晌畅。 經(jīng)常有香客問我但指,道長,這世上最難降的妖魔是什么抗楔? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任棋凳,我火速辦了婚禮,結(jié)果婚禮上连躏,老公的妹妹穿的比我還像新娘贫橙。我一直安慰自己,他們只是感情好反粥,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布卢肃。 她就那樣靜靜地躺著疲迂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪莫湘。 梳的紋絲不亂的頭發(fā)上尤蒿,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天,我揣著相機(jī)與錄音幅垮,去河邊找鬼腰池。 笑死,一個(gè)胖子當(dāng)著我的面吹牛忙芒,可吹牛的內(nèi)容都是我干的示弓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼呵萨,長吁一口氣:“原來是場噩夢啊……” “哼奏属!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起潮峦,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤囱皿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后忱嘹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嘱腥,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年拘悦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了齿兔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡础米,死狀恐怖愧驱,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情椭盏,我是刑警寧澤组砚,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站掏颊,受9級特大地震影響糟红,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乌叶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一盆偿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧准浴,春花似錦事扭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽今野。三九已至,卻和暖如春罐农,著一層夾襖步出監(jiān)牢的瞬間条霜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工涵亏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宰睡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓气筋,卻偏偏與公主長得像拆内,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子宠默,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,282評論 25 707
  • React Native學(xué)習(xí)<一> 認(rèn)識Recat Native 博客原文:http://www.jianshu....
    AFinalStone閱讀 2,674評論 0 12
  • 仿佛是那紫羅蘭那藍(lán)悠悠的眼晴麸恍, 所放出的奇光異彩, 透過那霧氣彌漫的天空光稼, 與那皎潔的月光或南, 相互交融孩等, 鋪天蓋地...
    水云怒閱讀 402評論 0 1
  • 總是大呼小叫的艾君,這是和你一起在那個(gè)小出租屋里住了520天后的認(rèn)知,將那個(gè)在課堂里安靜的小女孩再也無法安在你現(xiàn)...
    曉荍閱讀 532評論 1 7
  • 姬:我要到人間去生活肄方。 神:為什么要去污穢的人間冰垄?那里充滿了虛榮、偽善权她、貪欲虹茶、色欲、欺騙和怯懦隅要。 姬:你說得不全對...
    為之不為閱讀 505評論 0 1