React-Native項目中使用動畫-Animated

動畫 Animated

RN中的動畫在某種程度上可以理解為“屬性動畫”,也就是以某種過渡方式改變組件樣式屬性值(如組件樣式的left值),驅(qū)動組件以動畫的形式發(fā)生變化(位移、形變或轉(zhuǎn)動)

可動畫化的組件:

  • View (Animated.View)
  • Text (Animated.Text)
  • Image (Animated.Image)
  • 使用createAnimatedComponent自定義

三種動畫類型:

  • spring 基礎(chǔ)的單次彈跳物理模型
  • decay 以一個初始速度開始并且按一定的衰減比逐漸減慢直至停止
  • timing 時間和變量線性變化

1.關(guān)聯(lián)屬性的初始化

關(guān)聯(lián)屬性指的是動畫過程中對應變化的屬性,這個屬性的類型是Animated.Value,可以通過new Animated.Value()、new Animated.ValueXY()(處理2D動畫)等方法初始化,如下:

class PlaygroundContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            left1: new Animated.Value(0),
            rotation2: new Animated.Value(0),
            pan: new Animated.Value({x:0, y:0})
        }
    }
    ...
}

2.與組件關(guān)聯(lián)

用spring實現(xiàn)的動畫

import loadingImage from '../../assets/0.gif'
...
class PlaygroundContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            left1: new Animated.Value(0),
        }
    }
    componentDidMount() {
        Animated.spring(this.state.left1, {
            toValue: 100,       //屬性目標值
            friction: 1,        //摩擦力 (越小 振幅越大)
            tension: 100,       //拉力 
        }).start();         //執(zhí)行動畫
    }
    render(){
        return (
            ...
            <Animated.Image
                style={[styles.image,{left: this.state.left1}]}
                source={ loadingImage }/>
            ...
        )
    }
}

用timing實現(xiàn)的翻轉(zhuǎn)動畫效果

import loadingImage from '../../assets/0.gif'
...
class PlaygroundContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            rotation2: new Animated.Value(0),
        }
    }
    componentDidMount() {
        Animated.timing(this.state.rotation2, {
            toValue: 1,     //屬性目標值
            duration: 3000  //動畫執(zhí)行時間
        }).start(); //執(zhí)行動畫
    }
    render(){
        return (
            ...
            <Animated.Image
                style={[styles.image,{
                    transform:[
                        {
                            rotateX: this.state.rotation2.interpolate({
                                inputRange:[0,1],
                                outputRange:['0deg','360deg']
                            })
                        }
                    ]
                }]}
                source={ loadingImage }/>
            ...
        )
    }
}

<b> 這里用到<l style="color:red">插值函數(shù)</l>interpolate,它可以接受一個輸入?yún)^(qū)間,然后將其映射到另一個的輸出區(qū)間,如下:</b>

{
    rotateX: this.state.rotation2.interpolate({
        inputRange:[0,1],
        outputRange:['0deg','360deg']
    })
}

通過映射,

rotation2的value 映射輸出
0
0.2 72°
0.5 180°
1 360°

用decay實現(xiàn)衰減動畫

import loadingImage from '../../assets/0.gif'
...
class PlaygroundContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            decayLeft4: new Animated.Value(0),
        }
    }
    componentDidMount() {
        Animated.decay(this.state.decayLeft4, {
            velocity: 2,// 起始速度,必填參數(shù)。
            deceleration:0.992  //速度衰減比例,默認為0.997。
        }).start();
    }
    render(){
        return (
            ...
            <Animated.Image
                style={[styles.image,{
                    left: this.state.decayLeft4
                }]}
                source={ loadingImage }/>
            ...
        )
    }
}

組合畫效果

  • static sequence(animations: Array<CompositeAnimation>) (接受一個動畫數(shù)組,<b style="color: red">依次</b>執(zhí)行數(shù)組里的動畫)

  • static parallel(animations: Array<CompositeAnimation>, config?: ParallelConfig) (接受一個動畫數(shù)組,<b style="color: red">同時</b>執(zhí)行數(shù)組里的動畫)

      import loadingImage from '../../assets/0.gif'
      ...
      class PlaygroundContainer extends Component {
          constructor(props) {
              super(props);
              this.state = {
                  left3: new Animated.Value(0),
                  rotation3: new Animated.Value(0),
                  scale3: new Animated.Value(0.5),                }
          }
          componentDidMount() {
              //串行執(zhí)行
              Animated.sequence([ 
                  // 并行執(zhí)行(滾動,同時旋轉(zhuǎn))
                  Animated.parallel([
                      Animated.timing(this.state.left3, {
                          toValue: 1,
                          duration: 3000,
                      }),
                      Animated.timing(this.state.rotation3, {
                          toValue: 1,
                          duration: 1000,
                      }),
                  ]),
                  // 滾動、旋轉(zhuǎn)結(jié)束  執(zhí)行縮放
                  Animated.timing(this.state.scale3, {
                      toValue: 1,
                      duration: 500,
                  })
              ]).start()  //執(zhí)行動畫
          }
          render(){
              return (
                  ...
                  <Animated.Image
                      style={[styles.image,{
                          left: this.state.left3.interpolate({
                              inputRange:[0,1],
                              outputRange:[0, width - 100]
                          }),
                          transform:[
                              {rotateZ: this.state.rotation3.interpolate({
                                      inputRange:[0,1],
                                      outputRange:['0deg','360deg']})
                              },
                              {rotateX: this.state.rotation3.interpolate({
                                      inputRange:[0,1],
                                      outputRange:['0deg','360deg']})
                              },
                              {scale: this.state.scale3}
                          ]
                      }]}
                      source={ loadingImage }/>
                  ...
              )
          }
      }
    

用delay做延時動畫

Animated.delay(1000)延時1000ms
delay動畫放進sequence 執(zhí)行串行的動畫數(shù)組中

import loadingImage from '../../assets/0.gif'
...
class PlaygroundContainer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            left5: new Animated.Value(0),
        }
    }
    componentDidMount() {
        Animated.sequence([
            // 1000 ms后執(zhí)行
            Animated.delay(1000),
            Animated.timing(this.state.left5, {
                toValue: 100,// 起始速度,必填參數(shù)。
                duration: 1000
            })
        ]).start()
    }
    render(){
        return (
            ...
            <Animated.Image
                style={[styles.image,{
                    left: this.state.left5
                }]}
                source={ loadingImage }/>
            ...
        )
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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