react-native——動畫

一鱼的、LayoutAnimation
主要用于視圖位置、透明度等state改變之前調(diào)用痘煤,讓其變化過程帶上動畫效果凑阶,不那么生硬。適用于全局變化衷快。常規(guī)用法就不說了宙橱,主要看下細節(jié)點。如下是一個典型的LayoutAnimation動畫

    LayoutAnimation.configureNext({
            duration:800,
            create:{
                type:LayoutAnimation.Types.spring,
                property:LayoutAnimation.Properties.opacity,
            },
            update:{
                type:LayoutAnimation.Types.linear,
            },
           delete: {
              type:LayoutAnimation.Types.linear,
              property:LayoutAnimation.Properties.opacity,
          },
  });

參數(shù)意義:
@type::決定動畫進度蘸拔,例如彈簧spring师郑,線性linear,easeInEaseOut,easeIn,easeOut,keyboard等
@property:opacity或scaleXY调窍,只在create和delete之下時生效宝冕,決定視圖出現(xiàn)\消失的樣式,opacity為改變透明度出現(xiàn)\消失邓萨,scaleXY則為正中心一個點地梨,然后放大至原型出現(xiàn)菊卷。在create和delete中此屬性為必需,update中無效湿刽,不必寫的烁。
@create: 適用于給從無到有剛剛創(chuàng)建出來視圖添加動畫褐耳,例如點擊按鈕诈闺,在列表后添加一張圖片,當property為opacity時铃芦,圖片呈現(xiàn)完全透明在逐漸出現(xiàn)動畫效果雅镊。
@delete:適用于視圖消失時的動畫效果,例如點擊按鈕刃滓,刪除列表最后一張圖片仁烹,當property為scaleXY時,圖片呈現(xiàn)中點不變逐漸等比例縮小至消失動畫效果咧虎。
一般情況下LayoutAnimation不必使用上面的自定義動畫過程卓缰,直接使用系統(tǒng)已經(jīng)寫好的那幾個動畫就可以了,如LayoutAnimation.easeInEaseOut()砰诵、LayoutAnimation.spring()

在iOS中征唬,源碼動畫最終調(diào)用的是UIView的animateWithDuration方法產(chǎn)生動畫效果。
該API適用時需添加

 if (Platform.OS == 'android') {//android平臺需要開啟允許LayoutAnimation ios默認開啟
     UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
 }

二茁彭、Animated
相比LayoutAnimation总寒,適用于更細微的變化過程動畫,可適配性更高理肺。如下簡單使用

export default class Test extends Component {
    state = {
        bounceValue: new Animated.Value(0),
    };
    render() {
        return (
            <Animated.Image source={require('./1.png')} style={{
                transform: [{scale: this.state.bounceValue}]}}/>)
    }
    componentDidMount() {
        Animated.timing(this.state.bounceValue,{
            toValue:3,
            duration:3000,
            //  useNativeDriver: true    這里先注釋掉摄闸,標記為注釋@1
        }).start()
    }
}

所有Animated的js源碼都在AnimatedImplementation.js中,本文RN版本為0.43妹萨,以下所有源碼都只提取了關鍵部分
先從動畫的入口函數(shù)Animated.timing說起年枕,該函數(shù)定義在第2060行

var timing = function (value: AnimatedValue | AnimatedValueXY,config: TimingAnimationConfig,): CompositeAnimation {
     // 一些列轉化,最終執(zhí)行的是這個方法
     singleValue.animate(new TimingAnimation(singleConfig), callback);
};

這里的singleValue是傳入的this.state.bounceValue乎完,為AnimatedValue類型熏兄。singleConfig就是我們調(diào)用Animated.timing方法傳入的第二個參數(shù)對象。接下來去了AnimatedValue這個類的animate方法

animate(animation: Animation, callback: ?EndCallback): void {
        var handle = null;
        var previousAnimation = this._animation;
        this._animation && this._animation.stop();
        this._animation = animation;
        animation.start(
            this._value,
            (value) => {this._updateValue(value, true)},
            (result) => {
                callback && callback(result);
            },
            previousAnimation,this
        );
    }

這個方法也沒做啥實事囱怕,只是調(diào)用了傳入?yún)?shù)animation的start方法霍弹,這個參數(shù)就是上面?zhèn)鬟^來的new TimingAnimation(singleConfig)對象。這個對象的start方法如下

  start(fromValue: number,onUpdate: (value: number) => void,onEnd: ?EndCallback,previousAnimation: ?Animation,animatedValue: AnimatedValue): void {
     // 簡化后
      this._onUpdate = onUpdate;
      this._startTime = Date.now();
      if (this._useNativeDriver) {
          this.__startNativeAnimation(animatedValue); 
      } else {
         this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this));
      }
   }

這里出現(xiàn)了分支娃弓,當注釋@1打開時典格,_useNativeDriver屬性會為YES,動畫的執(zhí)行方式將交由原生端台丛,不再走下面的js端耍缴。本文只討論js端Animated動畫實現(xiàn)砾肺。
記錄下動畫開始的時間,然后調(diào)用requestAnimationFrame執(zhí)行onUpdate方法防嗡,requestAnimationFrame是跟原生端的定時器通信变汪,讓原生端定時器觸發(fā)回調(diào)事件onUpdate

    onUpdate(): void {
        var now = Date.now();
        if (now >= this._startTime + this._duration) {. // 動畫時間結束調(diào)用
            if (this._duration === 0) {
                this._onUpdate(this._toValue);
            } else {
                this._onUpdate(
                    this._fromValue + this._easing(1) * (this._toValue - this._fromValue)
                );
            }
            this.__debouncedOnEnd({finished: true});
            return;
        }
        // 在這里更新傳入的this.state.bounceValue的值
        this._onUpdate(this._fromValue +this._easing((now - this._startTime) / this._duration) * (this._toValue - this._fromValue));
        if (this.__active) {
            // 不斷注冊原生端定時器事件,循環(huán)
            this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this));
        }
    }

這個方法內(nèi)部會不斷注冊原生端定時器事件蚁趁,回調(diào)自身循環(huán)更新this.state.bounceValue的值裙盾,直到動畫時間結束退出。這里要注意他嫡,每一幀都會調(diào)用this._onUpdate方法番官。_onUpdate是start方法的第二個參數(shù),由上一個方法傳遞過來的钢属,最終執(zhí)行的是AnimatedValue的_updateValue方法

   _updateValue(value: number, flush: bool): void {
        this._value = value;
        if (flush) {
            _flush(this);
        }
        for (var key in this._listeners) { // AnimatedValue的值的變化過程是可監(jiān)控的徘熔,類似于KVO
            this._listeners[key]({value: this.__getValue()});
        }
    }

方法傳遞到_flush,再到AnimatedProps的update方法,最終回調(diào)到AnimatedComponent的_attachProps方法中注冊的回調(diào)callback淆党。

       var callback = () => {
                if (this._component.setNativeProps) {
                    if (!this._propsAnimated.__isNative) {
                        this._component.setNativeProps(this._propsAnimated.__getAnimatedValue());
                    } else {
                        throw new Error('Attempting to run JS driven animation on animated '
                            + 'node that has been moved to "native" earlier by starting an '
                            + 'animation with `useNativeDriver: true`');
                    }
                } else {
                    this.forceUpdate();
                }
            };

AnimatedComponent就是我們使用的Animated.Image酷师,this._component為Image。這里會判斷下我們使用的組件是否能夠設置setNativeProps染乌,只有那些能夠設置該屬性的組件山孔,如Image、Text慕匠、Image饱须、ScrollView才能使用Animated動畫,動畫的呈現(xiàn)原因是利用定時器不斷改變組件的setNativeProps值台谊,可避免觸發(fā)全局的render事件蓉媳,性能很高。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锅铅,一起剝皮案震驚了整個濱河市酪呻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盐须,老刑警劉巖玩荠,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贼邓,居然都是意外死亡阶冈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門塑径,熙熙樓的掌柜王于貴愁眉苦臉地迎上來女坑,“玉大人,你說我怎么就攤上這事统舀〈移” “怎么了劳景?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碉就。 經(jīng)常有香客問我盟广,道長,這世上最難降的妖魔是什么瓮钥? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任筋量,我火速辦了婚禮,結果婚禮上骏庸,老公的妹妹穿的比我還像新娘毛甲。我一直安慰自己年叮,他們只是感情好具被,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著只损,像睡著了一般一姿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跃惫,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天叮叹,我揣著相機與錄音,去河邊找鬼爆存。 笑死蛉顽,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的先较。 我是一名探鬼主播携冤,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闲勺!你這毒婦竟也來了曾棕?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤菜循,失蹤者是張志新(化名)和其女友劉穎翘地,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體癌幕,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡衙耕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了勺远。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橙喘。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖谚中,靈堂內(nèi)的尸體忽然破棺而出渴杆,到底是詐尸還是另有隱情寥枝,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布磁奖,位于F島的核電站囊拜,受9級特大地震影響,放射性物質發(fā)生泄漏比搭。R本人自食惡果不足惜冠跷,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望身诺。 院中可真熱鬧蜜托,春花似錦、人聲如沸霉赡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽穴亏。三九已至蜂挪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嗓化,已是汗流浹背棠涮。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留刺覆,地道東北人严肪。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像谦屑,于是被迫代替她去往敵國和親驳糯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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

  • 在上篇文章中介紹了 LayoutAnimation 的用法伦仍,本篇文章就來詳細介紹一下 Animated 的用法结窘。 ...
    IAMCJ閱讀 31,199評論 11 86
  • 實現(xiàn)動畫的幾種方式: requestAnimationFrame setNativeProps LayoutAni...
    zhuhf閱讀 13,582評論 10 38
  • 動畫 準備工作 本文基于react-native 0.47版本,提供兩個動畫系統(tǒng): Animated : 細粒度的...
    liuyanhongwl閱讀 4,484評論 2 9
  • 平時進行 Native 開發(fā)的時候充蓝,為了更好的用戶體驗隧枫,我們會做一些動畫效果,而在 React Native 中也...
    IAMCJ閱讀 6,471評論 3 34
  • 在我看來谓苟,無論是用 OC還是 RN 動畫無疑都是我的痛點官脓。但是在開發(fā)3.13.0版本的時候,有一個界面必須要使用動...
    Jeavil_Tang閱讀 8,466評論 0 6