<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ReactNative入門 —— 動(dòng)畫篇(下)

      在上篇?jiǎng)赢嬋腴T文章中我們了解了在 React Native 中簡單的動(dòng)畫的實(shí)現(xiàn)方式,本篇將作為上篇的延續(xù),介紹如何使用 Animated 實(shí)現(xiàn)一些比較復(fù)雜的動(dòng)畫。

      動(dòng)畫組合

      在 Animated 中提供了一些有趣的API方法來輕松地按我們的需求實(shí)現(xiàn)組合動(dòng)畫,它們分別是 Animated.parallel、Animated.sequence、Animated.stagger、Animated.delay。

      我們會(huì)分別介紹這些方法,并從中學(xué)習(xí)到一些其它有用的API。最后我們會(huì)得到一個(gè)有趣的DOGE動(dòng)畫 

       

      1. Animated.parallel

      并行執(zhí)行一系列指定動(dòng)畫的方法,其格式如下:

      Animated.parallel(Animates<Array>, [conf<Object>])

      第一個(gè)參數(shù)接受一個(gè)元素為動(dòng)畫的數(shù)組,通過執(zhí)行 start() 方法可以并行執(zhí)行該數(shù)組中的所有方法。

      如果數(shù)組中任意動(dòng)畫被中斷的話,該數(shù)組內(nèi)對(duì)應(yīng)的全部動(dòng)畫會(huì)一起停止,不過我們可以通過第二個(gè)(可選)參數(shù) conf 來取消這種牽連特性:

      {stopTogether: false}

      我們先看一個(gè)簡單的、沒有使用 Animated.parallel 的例子:

      class AwesomeProject extends Component {
          constructor(props) {
              super(props);
              this.state = {
                  grassTransY : new Animated.Value(Dimensions.get('window').height/2),
                  bigDogeTrans : new Animated.ValueXY({
                      x: 100,
                      y: 298
                  })
              }
          }
      
          componentDidMount() {
              Animated.timing(this.state.grassTransY, {
                  toValue: 200,
                  duration: 1000,
                  easing: Easing.bezier(0.15, 0.73, 0.37, 1.2)
              }).start();
      
              Animated.timing(this.state.bigDogeTrans, {
                  toValue: {
                      x : Dimensions.get('window').width/2 - 139,
                      y : -200
                  },
                  duration: 2000,
                  delay: 1000
              }).start();
          }
      
          render() {
              return (
                  <View style={styles.container}>
                      <Animated.View style={[styles.doges, {transform: this.state.bigDogeTrans.getTranslateTransform()}]} >
                          <Image source={require('./src/img/bdoge.png')}/>
                      </Animated.View>
      
                      <Animated.View style={[styles.grass, {transform: [{translateY: this.state.grassTransY}]}]}></Animated.View>
      
                  </View>
      
      
              );
          }
      }
      
      var styles = StyleSheet.create({
          grass: {
            position: 'absolute',
            width:  Dimensions.get('window').width,
            backgroundColor: '#A3D900',
            height: 240
          },
          doges: {
              position: 'absolute'
          },
          container: {
              flex: 1,
              justifyContent: 'center',
              alignItems: 'center',
              backgroundColor: '#73B9FF'
          }
      });

      執(zhí)行如下:

      更改為 Animated.parallel 形式為(只需要修改 componentDidMount 代碼塊):

          componentDidMount() {
              var timing = Animated.timing;
              Animated.parallel([
                  timing(this.state.grassTransY, {
                      toValue: 200,
                      duration: 1000,
                      easing: Easing.bezier(0.15, 0.73, 0.37, 1.2)
                  }),
                  timing(this.state.bigDogeTrans, {
                      toValue: {
                          x : Dimensions.get('window').width/2 - 139,
                          y : -200
                      },
                      duration: 2000,
                      delay: 1000
                  })
              ]).start();
          }

      執(zhí)行后效果是一致的。

      不過對(duì)于上方的代碼,這里提一下倆處API:

              new Animated.ValueXY({
                      x: 100,
                      y: 298
              })

      以及我們給 doge 設(shè)置的樣式:

      {transform: this.state.bigDogeTrans.getTranslateTransform()}

      它們是一個(gè)語法糖,Animated.ValueXY 方法會(huì)生成一個(gè) x 和 y 的映射對(duì)象,方便后續(xù)使用相關(guān)方法將該對(duì)象轉(zhuǎn)換為需要的樣式對(duì)象。

      例如這里我們通過 .getTranslateTransform() 方法將該 ValueXY 對(duì)象轉(zhuǎn)換為 translate 的樣式值應(yīng)用到組件上,即其初始樣式等價(jià)于 

      {transform: [{
          translateX: 100
      },
      {
          translateY: 298
      }]}

      注意在 Animated.timing 中設(shè)置動(dòng)畫終值時(shí)需要以

      { x: XXX,
        y: YYY
      }

      的形式來做修改:

                  timing(this.state.bigDogeTrans, {
                      toValue: {  //注意這里
                          x : Dimensions.get('window').width/2 - 139,
                          y : -200
                      },
                      duration: 2000,
                      delay: 1000
                  })

      另外,除了能將 ValueXY 對(duì)象轉(zhuǎn)為 translateX/Y 的 getTranslateTransform() 方法,我們還能通過 getLayout() 方法來將 ValueXY 對(duì)象轉(zhuǎn)為 {left, top} 形式的樣式對(duì)象:

       style={{
         transform: this.state.anim.getTranslateTransform()
       }}

      不過這里就不舉例了。

      我們回到 Animated.parallel 方法的話題來。我們對(duì)開頭的代碼做小小的改動(dòng)來學(xué)習(xí)一個(gè)新的API—— interpolate 插值函數(shù):

      class AwesomeProject extends Component {
          constructor(props) {
              super(props);
              this.state = {
                  //注意這里初始化value都為0
                  grassTransY : new Animated.Value(0),
                  bigDogeTransY : new Animated.Value(0)
              }
          }
      
          componentDidMount() {
              var timing = Animated.timing;
              Animated.parallel(['grassTransY', 'bigDogeTransY'].map((prop, i) => {
                  var _conf = {
                      toValue: 1,    //注意這里設(shè)置最終value都為1
                      duration: 1000 + i * 1000
                  };
                  i || (_conf.easing = Easing.bezier(0.15, 0.73, 0.37, 1.2));
      
                  return timing(this.state[prop], _conf)
              })).start();
          }
      
          render() {
              return (
                  <View style={styles.container}>
                      <Animated.View style={[styles.doges, {transform: [{
                              translateX: Dimensions.get('window').width/2 - 139
                          },
                          {
                              translateY: this.state.bigDogeTransY.interpolate({
                                  inputRange: [0, 1],  //動(dòng)畫value輸入范圍
                                  outputRange: [298, -200]  //對(duì)應(yīng)的輸出范圍
                          })
                      }]}]}>
                          <Image source={require('./src/img/bdoge.png')}/>
                      </Animated.View>
      
                      <Animated.View style={[styles.grass, {transform: [{
                          translateY: this.state.grassTransY.interpolate({
                              inputRange: [0, 1],
                              outputRange: [Dimensions.get('window').height/2, 200]
                          })
                      }]}]}></Animated.View>
      
                  </View>
              );
          }
      }

      注意我們這里統(tǒng)一把動(dòng)畫屬性初始值都設(shè)為0:

              this.state = {
                  //注意這里初始化value都為0
                  grassTransY : new Animated.Value(0),
                  bigDogeTransY : new Animated.Value(0)
              }

      然后又把動(dòng)畫屬性的終值設(shè)為1:

                  var _conf = {
                      toValue: 1,    //注意這里設(shè)置最終value都為1
                      duration: 1000
                  };
      
                  return timing(this.state[prop], _conf)

      然后通過 interpolate 插值函數(shù)將 value 映射為正確的值:

                          translateY: this.state.bigDogeTransY.interpolate({
                              inputRange: [0, 1],  //動(dòng)畫value輸入范圍
                              outputRange: [298, -200]  //對(duì)應(yīng)的輸出范圍
                          })

      這意味著當(dāng) value 的值為0時(shí),interpolate 會(huì)將其轉(zhuǎn)為 298 傳給組件;當(dāng) value 的值為1時(shí)則轉(zhuǎn)為 -200。

      因此當(dāng)value的值從0變化到1時(shí),interpolate 會(huì)將其轉(zhuǎn)為 (298 - 498 * value) 的值。

      事實(shí)上 inputRange 和 outputRange 的取值非常靈活,我們看官網(wǎng)的例子:

      value.interpolate({
        inputRange: [-300, -100, 0, 100, 101],
        outputRange: [300,    0, 1,   0,   0],
      });

      其映射為:

      Input       Output
      -400        450
      -300        300
      -200        150
      -100        0
      -50         0.5
      0           1
      50          0.5
      100         0
      101         0
      200         0

      2. Animated.sequence

      Animated的動(dòng)畫是異步執(zhí)行的,如果希望它們能以隊(duì)列的形式一個(gè)個(gè)逐步執(zhí)行,那么 Animated.sequence 會(huì)是一個(gè)最好的實(shí)現(xiàn)。其語法如下:

      Animated.sequence(Animates<Array>)

      事實(shí)上了解了開頭的 parallel 方法,后面幾個(gè)方法都是一樣套路了。

      來個(gè)例子,我們依舊直接修改上方代碼即可:

          componentDidMount() {
              var timing = Animated.timing;
              Animated.sequence(['grassTransY', 'bigDogeTransY'].map((prop, i) => {
                  var _conf = {
                      toValue: 1
                  };
                  if(i==0){
                      _conf.easing = Easing.bezier(0.15, 0.73, 0.37, 1.2)
                  }
      
                  return timing(this.state[prop], _conf)
              })).start();
          }

      這樣 doge 的動(dòng)畫會(huì)在 草地出來的動(dòng)畫結(jié)束后才開始執(zhí)行:

      3. Animated.stagger

      該方法為 sequence 的變異版,支持傳入一個(gè)時(shí)間參數(shù)來設(shè)置隊(duì)列動(dòng)畫間的延遲,即讓前一個(gè)動(dòng)畫結(jié)束后,隔一段指定時(shí)間才開始執(zhí)行下一個(gè)動(dòng)畫。其語法如下:

      Animated.stagger(delayTime<Number>, Animates<Array>)

      其中 delayTime 為指定的延遲時(shí)間(毫秒),我們繼續(xù)拿前面的代碼來開刀(為了給力點(diǎn)我們?cè)偌尤胍粋€(gè)running doge的動(dòng)畫事件)

      class AwesomeProject extends Component {
          constructor(props) {
              super(props);
              this.state = {
                  grassTransY : new Animated.Value(0),
                  bigDogeTransY : new Animated.Value(0),
                  runningDogeTrans : new Animated.ValueXY({
                      x: Dimensions.get('window').width,
                      y: Dimensions.get('window').height/2 - 120
                  })
              }
          }
      
          componentDidMount() {
              var timing = Animated.timing;
              Animated.stagger(1500, ['grassTransY', 'bigDogeTransY', 'runningDogeTrans'].map((prop, i) => {
                  var _conf = {
                      toValue: 1
                  };
                  if(i==0){
                      _conf.easing = Easing.bezier(0.15, 0.73, 0.37, 1.2)
                  }
      
                  if(i==2){ //running doge
                      _conf.toValue = {
                          x: Dimensions.get('window').width - 150,
                          y: Dimensions.get('window').height/2 - 120
                      }
                  }
      
                  return timing(this.state[prop], _conf)
              })).start();
          }
      
          render() {
              return (
                  <View style={styles.container}>
                      <Animated.View style={[styles.doges, {transform: [{
                          translateX: Dimensions.get('window').width/2 - 139
                      },
                      {
                          translateY: this.state.bigDogeTransY.interpolate({
                              inputRange: [0, 1],  
                              outputRange: [298, -200]
                          })
                      }]}]}>
                          <Image source={require('./src/img/bdoge.png')}/>
                      </Animated.View>
      
                      <Animated.View style={[styles.grass, {transform: [{
                          translateY: this.state.grassTransY.interpolate({
                              inputRange: [0, 1],
                              outputRange: [Dimensions.get('window').height/2, 200]
                          })
                      }]}]}></Animated.View>
      
                      <Animated.View style={[styles.doges, {
                          transform: this.state.runningDogeTrans.getTranslateTransform()
                      }]}>
                          <Image source={require('./src/img/sdoge.gif')}/>
                      </Animated.View>
      
                  </View>
              );
          }
      }

      我們把三個(gè)動(dòng)畫間隔時(shí)間設(shè)定為 2000 毫秒,執(zhí)行效果如下:

      4. Animated.delay

      噢這個(gè)接口實(shí)在太簡單了,就是設(shè)置一段動(dòng)畫的延遲時(shí)間,接收一個(gè)時(shí)間參數(shù)(毫秒)作為指定延遲時(shí)長:

      Animated.delay(delayTime<Number>)

      常規(guī)還是跟好基友 Animated.sequence 一同使用,我們繼續(xù)修改前面的代碼:

      class AwesomeProject extends Component {
          constructor(props) {
              super(props);
              this.state = {
                  grassTransY : new Animated.Value(0),
                  bigDogeTransY : new Animated.Value(0),
                  runningDogeTrans : new Animated.ValueXY({
                      x: Dimensions.get('window').width,
                      y: Dimensions.get('window').height/2 - 120
                  })
              }
          }
      
          componentDidMount() {
              var timing = Animated.timing;
              Animated.sequence([
                  Animated.delay(1000),  //延遲1秒再開始執(zhí)行動(dòng)畫
      
                  timing(this.state.grassTransY, {
                      toValue: 1,
                      duration: 1000,
                      easing: Easing.bezier(0.15, 0.73, 0.37, 1.2)
                  }),
      
                  timing(this.state.bigDogeTransY, {
                      toValue: 1,
                      duration: 3000
                  }),
      
                  Animated.delay(2000),  //延遲2秒再執(zhí)行running doge動(dòng)畫
      
                  timing(this.state.runningDogeTrans, {
                      toValue: {
                          x: Dimensions.get('window').width - 150,
                          y: Dimensions.get('window').height/2 - 120
                      },
                      duration: 2000
                  }),
      
                  Animated.delay(1000),  //1秒后跑到中間
      
                  timing(this.state.runningDogeTrans, {
                      toValue: {
                          x: Dimensions.get('window').width/2 - 59,
                          y: Dimensions.get('window').height/2 - 180
                      },
                      duration: 1000
                  })
              ]
      
              ).start();
          }
      
          render() {
              return (
                  <View style={styles.container}>
                      <Animated.View style={[styles.doges, {transform: [{
                          translateX: Dimensions.get('window').width/2 - 139
                      },
                      {
                          translateY: this.state.bigDogeTransY.interpolate({
                              inputRange: [0, 1],  //動(dòng)畫value輸入范圍
                              outputRange: [298, -200]  //對(duì)應(yīng)的輸出范圍
                          })
                      }]}]}>
                          <Image source={require('./src/img/bdoge.png')}/>
                      </Animated.View>
      
                      <Animated.View style={[styles.grass, {transform: [{
                          translateY: this.state.grassTransY.interpolate({
                              inputRange: [0, 1],
                              outputRange: [Dimensions.get('window').height/2, 200]
                          })
                      }]}]}></Animated.View>
      
                      <Animated.View style={[styles.doges, {
                          transform: this.state.runningDogeTrans.getTranslateTransform()
                      }]}>
                          <Image source={require('./src/img/sdoge.gif')}/>
                      </Animated.View>
      
                  </View>
              );
          }
      }

      執(zhí)行如下:

      到這里我們基本就掌握了 RN 動(dòng)畫的常用API了,對(duì)于本章的 Doge 動(dòng)畫我們?cè)俑銖?fù)雜一點(diǎn)——再加一只running doge,然后在動(dòng)畫結(jié)束后,讓最大的Doge頭一直不斷地循環(huán)旋轉(zhuǎn):

      class AwesomeProject extends Component {
          constructor(props) {
              super(props);
              this.state = {
                  grassTransY : new Animated.Value(0),
                  bigDogeTransY : new Animated.Value(0),
                  bigDogeRotate : new Animated.Value(0),
                  runningDogeTrans : new Animated.ValueXY({
                      x: Dimensions.get('window').width,
                      y: Dimensions.get('window').height/2 - 120
                  }),
                  runningDoge2Trans : new Animated.ValueXY({
                      x: Dimensions.get('window').width,
                      y: Dimensions.get('window').height/2 - 90
                  })
              }
          }
      
          componentDidMount() {
              var timing = Animated.timing;
              Animated.sequence([
                  Animated.delay(1000),  //延遲1秒再開始執(zhí)行動(dòng)畫
      
                  timing(this.state.grassTransY, {
                      toValue: 1,
                      duration: 1000,
                      easing: Easing.bezier(0.15, 0.73, 0.37, 1.2)
                  }),
      
                  timing(this.state.bigDogeTransY, {
                      toValue: 1,
                      duration: 3000
                  }),
      
                  Animated.parallel([
                      Animated.sequence([
                          timing(this.state.runningDogeTrans, {
                              toValue: {
                                  x: Dimensions.get('window').width - 150,
                                  y: Dimensions.get('window').height/2 - 120
                              },
                              duration: 2000
                          }),
      
                          Animated.delay(1000),  //1秒后跑到中間
      
                          timing(this.state.runningDogeTrans, {
                              toValue: {
                                  x: Dimensions.get('window').width/2 - 99,
                                  y: Dimensions.get('window').height/2 - 180
                              },
                              duration: 1000
                          })
                      ]),
      
                      Animated.sequence([
                          timing(this.state.runningDoge2Trans, {
                              toValue: {
                                  x: Dimensions.get('window').width/2 + 90,
                                  y: Dimensions.get('window').height/2 - 90
                              },
                              duration: 2000
                          }),
      
                          Animated.delay(1000),
      
                          timing(this.state.runningDoge2Trans, {
                              toValue: {
                                  x: Dimensions.get('window').width/2 + 20,
                                  y: Dimensions.get('window').height/2 - 110
                              },
                              duration: 1000
                          })
                      ])
      
                  ])
              ]
      
              ).start(()=>{
                  this.bigDogeRotate()
              });
          }
      
          //大doge一直不斷循環(huán)
          bigDogeRotate(){
              this.state.bigDogeRotate.setValue(0);  //重置Rotate動(dòng)畫值為0
              Animated.timing(this.state.bigDogeRotate, {
                  toValue: 1,
                  duration: 5000
              }).start(() => this.bigDogeRotate())
          }
      
          render() {
              return (
                  <View style={styles.container}>
                      <Animated.View style={[styles.doges, {transform: [{
                          translateX: Dimensions.get('window').width/2 - 139
                      },
                      {
                          translateY: this.state.bigDogeTransY.interpolate({
                              inputRange: [0, 1],  //動(dòng)畫value輸入范圍
                              outputRange: [298, -200]  //對(duì)應(yīng)的輸出范圍
                          })
                      },
                      {
                          rotateZ: this.state.bigDogeRotate.interpolate({
                                  inputRange: [0, 1],  //動(dòng)畫value輸入范圍
                                  outputRange: ['0deg', '360deg']  //對(duì)應(yīng)的輸出范圍
                          })
                      }]}]}>
                          <Image source={require('./src/img/bdoge.png')}/>
                      </Animated.View>
      
                      <Animated.View style={[styles.grass, {transform: [{
                          translateY: this.state.grassTransY.interpolate({
                              inputRange: [0, 1],
                              outputRange: [Dimensions.get('window').height/2, 200]
                          })
                      }]}]}></Animated.View>
      
                      <Animated.View style={[styles.doges, {
                          transform: this.state.runningDogeTrans.getTranslateTransform()
                      }]}>
                          <Image source={require('./src/img/sdoge.gif')}/>
                      </Animated.View>
      
                      <Animated.View style={[styles.doges, {
                          transform: this.state.runningDoge2Trans.getTranslateTransform()
                      }]}>
                          <Image source={require('./src/img/sdoge.gif')}/>
                      </Animated.View>
      
                  </View>
              );
          }
      }
      View Code

      最終效果如下:

      寫完這篇文章都凌晨了,我也是蠻拼的 

      共勉~

      donate

       

      posted @ 2016-04-24 00:35  vajoy  閱讀(12571)  評(píng)論(3)    收藏  舉報(bào)
      Copyright © 2014 - 2022 VaJoy Studio
      主站蜘蛛池模板: 亚洲国产区男人本色vr| 亚洲欧美日韩高清一区二区三区| 精品一区二区三区不卡| aaa少妇高潮大片免费看| 国产在线精品一区二区三区| 三级4级全黄60分钟| 97视频精品全国免费观看 | 中文字幕日韩熟女av| 句容市| 亚洲av色在线播放一区| 啦啦啦视频在线日韩精品| 波多野结衣一区二区三区高清| 免费国产一级特黄aa大片在线| 狠狠婷婷综合久久久久久| 中文字幕久久六月色综合| 偷拍一区二区三区在线视频| 亚洲av片在线免费观看| 亚洲欧美综合中文| 国产大尺度一区二区视频| 精品人妻伦一二三区久久aaa片| 豆国产97在线 | 亚洲| 青草内射中出高潮| 久久亚洲精品中文字幕无| 久久精品国产亚洲av麻豆长发| 亚洲a人片在线观看网址| 日韩精品亚洲专在线电影| 久久亚洲精品天天综合网| 亚洲狠狠婷婷综合久久久| 人人妻人人做人人爽夜欢视频| 亚洲av优女天堂熟女久久| 免费观看日本污污ww网站69| 亚洲欧美综合精品成人网站| 中文字幕av日韩有码| 影音先锋大黄瓜视频| 无码h片在线观看网站| 最近中文字幕国产精品| 久久久久国色av免费观看性色| 国产区精品视频自产自拍| 久视频久免费视频久免费| 成熟了的熟妇毛茸茸| 99久久免费精品国产色|