[React Native]動(dòng)畫-Animated

在上一篇文章中,我們學(xué)習(xí)了React Native實(shí)現(xiàn)動(dòng)畫的幾種方式,其中重點(diǎn)介紹了LayoutAnimation杰捂。文章的末尾也提到秸讹,如果你需要更強(qiáng)大的動(dòng)畫功能檀咙,就需要使用高級(jí)API—Animated

如果你還不了解LayoutAnimation璃诀,建議先閱讀下上一篇文章[React Native]動(dòng)畫-LayoutAnimation弧可,其中的一些概念能讓你更好的理解本篇文章的內(nèi)容。

本篇文章會(huì)一步步介紹Animated的用法劣欢,如果有誤之處棕诵,歡迎指正~


動(dòng)畫類型:

  • spring:基礎(chǔ)的單次彈跳物理模型
  • timing:從時(shí)間范圍映射到漸變的值
  • decay:以一個(gè)初始速度開始并且逐漸減慢停止

創(chuàng)建動(dòng)畫的參數(shù):

  • value:AnimatedValue | AnimatedValueXY(X軸Y軸 | X軸Y軸)
  • config:SpringAnimationConfig | TimingAnimationConfig | DecayAnimationConfig(動(dòng)畫的參數(shù)配置)

組件類型:

  • Animated.Text
  • Animated.Image
  • Animated.View:可以用來包裹任意視圖
  • Animated.createAnimatedComponent():其它組件(較少用,用Animated.View包裹可以達(dá)到同樣的效果

讓我們來看一個(gè)示例:圖片透明度2秒內(nèi)從不透明到全透明凿将,線性變化校套。

class Demo8 extends Component {
  // 構(gòu)造
  constructor(props) {
      super(props);
      // 初始狀態(tài)
      this.state = {
          fadeOutOpacity: new Animated.Value(0),
      };
  }
  render() {
      return ( 
        <Animated.View // 可選的基本組件類型: Image, Text, View(可以包裹任意子View)
            style = {{flex: 1,alignItems: 'center',justifyContent: 'center',
                    opacity: this.state.fadeOutOpacity,}}> 
            <Image source = {{uri: 'http://i.imgur.com/XMKOH81.jpg'}}
                style = {{width: 400,height: 400}}/>
        </Animated.View > 
      );
  }
  startAnimation() {
      this.state.fadeOutOpacity.setValue(1);
      Animated.timing(this.state.fadeOutOpacity, {
          toValue: 0,
          duration: 2000,
          easing: Easing.linear,// 線性的漸變函數(shù)
      }).start();
  }
  componentDidMount() {
      this.startAnimation();
  }
}
AppRegistry.registerComponent('Demo8', () = >Demo8);

效果圖如下:

opacity.gif

值類型:

  • AnimatedValue:?jiǎn)蝹€(gè)值
  • AnimatedValueXY:向量值

多數(shù)情況下,AnimatedValue可以滿足需求(上面的示例)牧抵,但有些情況下我們可能會(huì)需要AnimatedValueXY笛匙。

比如:我們需要圖片沿著X軸和Y軸交叉方向,向右下角移動(dòng)一小段距離犀变。

class Demo8 extends Component {
  // 構(gòu)造
  constructor(props) {
      super(props);
      // 初始狀態(tài)
      this.state = {
          translateValue: new Animated.ValueXY({x:0, y:0}), // 二維坐標(biāo)
      };
  }
  render() {
      return ( 
        <Animated.View // 可選的基本組件類型: Image, Text, View(可以包裹任意子View)
            style = {{flex: 1,alignItems: 'center',justifyContent: 'center',
                  transform: [  
                    {translateX: this.state.translateValue.x}, // x軸移動(dòng)
                    {translateY: this.state.translateValue.y}, // y軸移動(dòng)
                  ]
                  }}> 
            <Image source = {{uri: 'http://i.imgur.com/XMKOH81.jpg'}}
                style = {{width: 400,height: 400}}/>
        </Animated.View > 
      );
  }
  startAnimation() {
      this.state.translateValue.setValue({x:0, y:0});
      Animated.decay( // 以一個(gè)初始速度開始并且逐漸減慢停止妹孙。  S=vt-(at^2)/2   v=v - at
          this.state.translateValue,
          {
              velocity: 10, // 起始速度,必填參數(shù)获枝。
              deceleration: 0.8, // 速度衰減比例蠢正,默認(rèn)為0.997。
          }
      ).start();
  }
  componentDidMount() {
      this.startAnimation();
  }
}
AppRegistry.registerComponent('Demo8', () = >Demo8);

其中省店,transform是一個(gè)變換數(shù)組嚣崭,常用的有scale, scaleX, scaleY, translateX, translateY, rotate, rotateX, rotateY, rotateZ

...
transform: [  // scale, scaleX, scaleY, translateX, translateY, rotate, rotateX, rotateY, rotateZ
    {scale: this.state.bounceValue},  // 縮放
    {rotate: this.state.rotateValue.interpolate({ // 旋轉(zhuǎn),使用插值函數(shù)做值映射
        inputRange: [0, 1],
        outputRange: ['0deg', '360deg']})},
    {translateX: this.state.translateValue.x}, // x軸移動(dòng)
    {translateY: this.state.translateValue.y}, // y軸移動(dòng)
],
...

插值函數(shù):
將輸入值范圍轉(zhuǎn)換為輸出值范圍懦傍,如下:將0-1數(shù)值轉(zhuǎn)換為0deg-360deg角度雹舀,旋轉(zhuǎn)View時(shí)你會(huì)用到

this.state.rotateValue.interpolate({ // 旋轉(zhuǎn),使用插值函數(shù)做值映射
        inputRange: [0, 1],
        outputRange: ['0deg', '360deg']})

組合動(dòng)畫:

  • parallel:同時(shí)執(zhí)行
  • sequence:順序執(zhí)行
  • stagger:錯(cuò)峰谎脯,其實(shí)就是插入了delay的parrllel
  • delay:組合動(dòng)畫之間的延遲方法葱跋,嚴(yán)格來講,不算是組合動(dòng)畫

讓我們來看一個(gè)示例:圖片首先縮小80%,2秒之后娱俺,旋轉(zhuǎn)360度稍味,之后沿著X軸與Y軸交叉方向向右下角移動(dòng)一段距離,最后消失變成全透明

startAnimation() {
  this.state.bounceValue.setValue(1.5); // 設(shè)置一個(gè)較大的初始值
  this.state.rotateValue.setValue(0);
  this.state.translateValue.setValue({x: 0,y: 0});
  this.state.fadeOutOpacity.setValue(1);

  Animated.sequence([
      Animated.sequence([ //  組合動(dòng)畫 parallel(同時(shí)執(zhí)行)荠卷、sequence(順序執(zhí)行)模庐、stagger(錯(cuò)峰,其實(shí)就是插入了delay的parrllel)和delay(延遲)
        Animated.spring( //  基礎(chǔ)的單次彈跳物理模型
          this.state.bounceValue, {
            toValue: 0.8,
            friction: 1,// 摩擦力油宜,默認(rèn)為7.
            tension: 40,// 張力掂碱,默認(rèn)40。
          }), 
        Animated.delay(2000), // 配合sequence慎冤,延遲2秒
        Animated.timing( // 從時(shí)間范圍映射到漸變的值疼燥。
          this.state.rotateValue, {
            toValue: 1,
            duration: 800,// 動(dòng)畫持續(xù)的時(shí)間(單位是毫秒),默認(rèn)為500
            easing: Easing.out(Easing.quad),// 一個(gè)用于定義曲線的漸變函數(shù)
            delay: 0,// 在一段時(shí)間之后開始動(dòng)畫(單位是毫秒)蚁堤,默認(rèn)為0醉者。
          }), 
        Animated.decay( // 以一個(gè)初始速度開始并且逐漸減慢停止。  S=vt-(at^2)/2   v=v - at
          this.state.translateValue, {
            velocity: 10,// 起始速度披诗,必填參數(shù)撬即。
            deceleration: 0.8,// 速度衰減比例,默認(rèn)為0.997呈队。
        }),
      ]), 
      Animated.timing(this.state.fadeOutOpacity, {
        toValue: 0,
        duration: 2000,
        easing: Easing.linear,// 線性的漸變函數(shù)
      })
  ]).start();
}

效果圖如下:

compose.gif

循環(huán)執(zhí)行動(dòng)畫:
start方法可以接受一個(gè)函數(shù)剥槐,通過監(jiān)聽動(dòng)畫結(jié)束,再調(diào)用startAnimation可以重復(fù)執(zhí)行動(dòng)畫宪摧,例如:

startAnimation() {
   this.state.translateValue.setValue({x:0, y:0});
   Animated.decay( // 以一個(gè)初始速度開始并且逐漸減慢停止粒竖。  S=vt-(at^2)/2   v=v - at
      this.state.translateValue,
      {
         velocity: 10, // 起始速度,必填參數(shù)几于。
         deceleration: 0.8, // 速度衰減比例温圆,默認(rèn)為0.997。
      }
   ).start(() => this.startAnimation());
}

監(jiān)聽當(dāng)前的動(dòng)畫值:

  • addListener(callback):動(dòng)畫執(zhí)行過程中的值
  • stopAnimation(callback):動(dòng)畫執(zhí)行結(jié)束時(shí)的值

監(jiān)聽AnimatedValueXY類型translateValue的值變化:

this.state.translateValue.addListener((value) => {   
    console.log("translateValue=>x:" + value.x + " y:" + value.y);
});
this.state.translateValue.stopAnimation((value) => {   
    console.log("translateValue=>x:" + value.x + " y:" + value.y);
});

監(jiān)聽AnimatedValue類型rotateValue的值變化:

this.state.rotateValue.addListener((state) => {   
    console.log("rotateValue=>" + state.value);
});
this.state.rotateValue.stopAnimation((state) => {   
    console.log("rotateValue=>" + state.value);
});

好了孩革,到這里我們把Animated的常用方法都介紹了,也給出了代碼示例(略微有點(diǎn)多)得运。建議大家動(dòng)手嘗試下每個(gè)效果膝蜈,這樣,可以理解的更加深刻

本文的源碼地址Demo8

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末熔掺,一起剝皮案震驚了整個(gè)濱河市饱搏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌置逻,老刑警劉巖推沸,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鬓催,警方通過查閱死者的電腦和手機(jī)肺素,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宇驾,“玉大人倍靡,你說我怎么就攤上這事】紊幔” “怎么了塌西?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)筝尾。 經(jīng)常有香客問我捡需,道長(zhǎng),這世上最難降的妖魔是什么筹淫? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任站辉,我火速辦了婚禮,結(jié)果婚禮上贸街,老公的妹妹穿的比我還像新娘庵寞。我一直安慰自己,他們只是感情好薛匪,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布捐川。 她就那樣靜靜地躺著,像睡著了一般逸尖。 火紅的嫁衣襯著肌膚如雪古沥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天娇跟,我揣著相機(jī)與錄音岩齿,去河邊找鬼。 笑死苞俘,一個(gè)胖子當(dāng)著我的面吹牛盹沈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吃谣,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼乞封,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了岗憋?” 一聲冷哼從身側(cè)響起肃晚,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仔戈,沒想到半個(gè)月后关串,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拧廊,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年晋修,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吧碾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡飞蚓,死狀恐怖滤港,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情趴拧,我是刑警寧澤溅漾,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站著榴,受9級(jí)特大地震影響添履,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脑又,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一暮胧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧问麸,春花似錦往衷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至哮笆,卻和暖如春来颤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背稠肘。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工福铅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人项阴。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓滑黔,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親环揽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拷沸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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