
2018年5月6日3 分鐘閱讀
React Native 布林值動畫
這篇文章是通過 AI 翻譯生成,可能有不準確之處。
React Native 中的動畫
Animated API 是 React Native 中創建引人入勝動畫的絕佳方法。
它通過建立一個動畫數值補間,然後將動畫數值映射到您想要動畫化的樣式上來工作。如果您對 Animated 不熟悉,請查看文檔。
用布林值控制動畫?
有時,我們想要使用布林值來為組件製作動畫,但 Animated API 預設並不提供此功能。這有點不方便。例如,您想要在按鈕上實現淡入、淡出效果。實現可能如下所示:
Container
(之前)
// ...
class MyContainer extends React.Component {
// ...
toggleBtn() {
if (this.state.btnActive) {
this.setState({ btnActive: false })
Animated.spring(this.state.animatedValue, {
duration: 300,
toValue: 0,
friction: 10,
}).start()
} else {
this.setState({ btnActive: true })
Animated.spring(this.state.animatedValue, {
duration: 300,
toValue: 1,
friction: 10,
}).start()
}
}
render() {
return (
// ...
<Animated.View
style={{
opacity: this.state.animateValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
}}
>
<Button title="I am a button" />
</Animated.View>
// ...
)
}
}
這並不理想,原因有兩個:
- 要切換按鈕需要執行兩個任務
- 動畫實現細節在
Container
檔案中
動畫高階組件
創建一個 animatedHOC
可以解決這個問題。額外的層級可以抽象化切換按鈕動畫的細節,這樣 Container
就不再需要關心按鈕應該如何動畫化。
animatedHOC
處理所有動畫數值補間邏輯如下:
import React, { Component } from 'react';
import {
Animated,
InteractionManager
} from 'react-native';
export default function animatedHOC(WrappedComponent) {
return class AnimatedCtrl extends Component {
constructor(props) {
super(props);
this.state = {
active: props.active,
animateValue: new Animated.Value(0)
};
}
componentWillReceiveProps(nextProps) {
if (this.state.active === nextProps.active) return;
Animated.spring(
this.state.animateValue,
{
duration: this.props.duration,
// 被 HOC 包裝的組件可以根據 0 到 1 之間的
// animateValue 來決定要實現什麼動畫。
toValue: nextProps.active ? 1 : 0,
friction: 10
}
).start();
this.setState({
active: nextProps.active
});
}
render() {
return (<WrappedComponent
{ ...this.props }
animateValue={ this.state.animateValue }
/>);
}
};
FadeAnimationBtn
接收 animateValue
屬性來實現相應的動畫。
Container
(之後)
import React from 'react'
import { View, Animated, Button, Text } from 'react-native'
import Button from 'path/to/myButton'
import animatedHOC from '../animatedHOC'
export const FloatBtn = ({ onPress, title, animateValue }) => (
<Animated.View
style={{
opacity: animateValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
}}
>
<Button onPress={onPress} title={title} />
</Animated.View>
)
export default animatedHOC(FloatBtn)
注意 FadeAnimationBtn
必須被 animatedHOC
包裝,因為 FadeAnimationBtn
需要 animatedValue
作為其屬性。
Container
// ...
import FadeAnimationBtn from 'path/to/FadeAnimationBtn';
class MyContainer extends React.Component {
// ...
toggleBtn() {
this.setState({
btnActive: !this.state.btnActive
});
}
render() {
return (
// ...
<FadeAnimationBtn
active={ this.state.btnActive }
title="I am a Button"
>
// ...
);
}
}
通過這種方法,我們可以更簡潔地實現布林值動畫。Container
只需要關心按鈕的狀態。
以上只是最基本的實現。您可以通過添加 InteractionManager
或任何您想要的功能來增強 AnimatedHOC
。您還可以根據 animatedValue
添加其他過渡效果。
結論
高階組件是一個強大的概念,通過將重複的部分和關注點分離到組件中,使我們的程式碼更簡潔和可維護。希望這篇文章對您有所幫助,謝謝!