はじめてのアニメーション
Animatedコンポーネント・共有値・アニメーション関数の3つを組み合わせて、最初のアニメーションを手で作りながらReanimatedの基本をつかみます。
第1部ではReanimatedがどんなライブラリで、なぜ滑らかに動くのかを眺めました。ここからは実際に手を動かします。最初のアニメーションを一歩ずつ組み立てながら、Reanimatedを支える3つの部品、Animatedコンポーネント・共有値(Shared Value)・アニメーション関数を体で覚えていきましょう。
Animatedコンポーネントを用意する
まずは画面に置くものが必要です。アニメーションさせたい要素は、Animatedオブジェクトが提供するコンポーネントで作ります。
import Animated from "react-native-reanimated";
このAnimatedは、ViewやScrollView、FlatListといったReact Nativeの組み込みコンポーネントをラップしたものを持っています。使い方はふつうのJSXと変わりません。
import Animated from "react-native-reanimated";
export default function App() {
return (
<Animated.View
style={{
width: 100,
height: 100,
backgroundColor: "violet",
}}
/>
);
}
Animated.Viewのように、Animatedが用意しているコンポーネントを使うと、その要素はアニメーション可能になります。組み込み以外のコンポーネントをアニメーションさせたいときはcreateAnimatedComponentで自分でラップできますが、それは第2部の後半であらためて扱います。
共有値を用意する
次に、動きの源になる値を用意します。ここで使うのが共有値です。共有値の考え方は第1部で紹介したとおりで、JavaScript側とUIスレッド側をつなぐ、アニメーションの駆動役です。共有値はuseSharedValueフックで作ります。
import { useSharedValue } from "react-native-reanimated";
ほかのReactフックと同じく、コンポーネントの本体で呼び出します。共有値には数値・文字列・真偽値のほか、配列やオブジェクトも入れられます。ここでは初期値を100にして、その値をAnimated.Viewの幅に渡してみます。
import Animated, { useSharedValue } from "react-native-reanimated";
export default function App() {
const width = useSharedValue(100);
return (
<Animated.View
style={{
width,
height: 100,
backgroundColor: "violet",
}}
/>
);
}
共有値を書き換える
共有値に入れた値は、.valueプロパティで読み書きします。セッターのようなものはありません。.valueを直接書き換えるだけです。
ボタンを押すたびに幅を50ずつ増やすhandlePressを用意してみます。
import { Button, View } from "react-native";
import Animated, { useSharedValue } from "react-native-reanimated";
export default function App() {
const width = useSharedValue(100);
const handlePress = () => {
width.value = width.value + 50;
};
return (
<View style={{ flex: 1, alignItems: "center" }}>
<Animated.View
style={{
width,
height: 100,
backgroundColor: "violet",
}}
/>
<Button onPress={handlePress} title="押してみて" />
</View>
);
}
このコードでもボタンを押すと幅は変わります。ただ、値がパッと切り替わるだけで、まだアニメーションにはなっていません。
アニメーション関数で包む
ここでアニメーション関数の出番です。withSpringを読み込み、新しい値をwithSpringで包んでから代入します。すると、いまの値から新しい値まで、バネのようにはねながら変化するようになります。
import { Button, View } from "react-native";
import Animated, {
useSharedValue,
withSpring,
} from "react-native-reanimated";
export default function App() {
const width = useSharedValue(100);
const handlePress = () => {
width.value = withSpring(width.value + 50);
};
return (
<View style={{ flex: 1, alignItems: "center" }}>
<Animated.View
style={{
width,
height: 100,
backgroundColor: "violet",
}}
/>
<Button onPress={handlePress} title="押してみて" />
</View>
);
}
これで最初のアニメーションができました。実際に動かしてみましょう。ボタンを押すたびに、四角形の幅がバネのように伸びていきます。
「コード」タブを開くと、このデモの実装を確認できます。デモでは初期表示のちらつきを避けるためにuseAnimatedStyleを使っていますが、幅をwithSpringで包んで代入するという骨格は上のコードと同じです。useAnimatedStyleは次章でくわしく取り上げます。
この章のまとめ
最初のアニメーションを通して、Reanimatedの土台となる部品がそろいました。
Animatedコンポーネントは、アニメーション可能な要素を定義するために使います- 共有値はすべてのアニメーションの駆動役で、
useSharedValueフックで作ります - 共有値の読み書きはつねに
.valueを通して行います(例:sv.value = 100) - 値を
withSpringなどのアニメーション関数で包んで代入すると、なめらかに変化します
次章では、共有値とスタイルの結びつきをもう一歩深めます。インラインのスタイルではできないことと、それを解決するuseAnimatedStyleを見ていきます。