
React Native ブール値を使ったアニメーション
この記事はAIによって翻訳されたため、不正確な場合があります。
免責聲明: このブログ記事の翻訳はAIによって生成されました。翻訳の正確性について保証はありません。重要な情報については、元の記事をご参照ください。
React Nativeのアニメーション
Animated APIは、React Nativeで魅力的なアニメーションを作成するための素晴らしいアプローチです。
これはアニメーション値のトゥイーンを作成し、アニメーション値をアニメーションしたいスタイルにマップすることで動作します。Animatedに馴染みがない場合は、ドキュメントをご確認ください。
ブール値でアニメーションを制御する?
時々、ブール値でコンポーネントをアニメーションしたいことがありますが、Animated APIはデフォルトでそれを提供していません。少し不便です。例えば、ボタンにフェードイン、フェードアウト効果を持たせたい場合、実装は以下のようになるかもしれません:
Container
(before)
// ...
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にラップされたコンポーネントは、animateValue
// に基づいて実装するアニメーションを決定できます
// 0と1の間で。
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
(after)
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
はanimatedValue
をそのプロップとして必要とするため、animatedHOC
によってラップされる必要があることに注意してください。
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
に基づいて他のトランジション効果も追加できます。
結論
高階コンポーネントは、重複する部分を分離し、コンポーネントへの関心を分離することで、コードをより簡潔で保守可能にする強力な概念です。この記事が役立つことを願っています。ありがとうございます!