Expo SDK 40でReanimatedを使ってみたよ
この記事は React Native アドベントカレンダーの21日目の記事です。
これはなに
Expo SDK 40
の個人的な目玉機能である「Reanimated v2-rc
」について触ってみた、です。デモ付きです。
Expo SDK 40
Expoは、ReactNativeにおける開発を支援するフレームワークです。先日、今年最後のアップデートであるSDK40がリリースされました。SDK40のアップデートはこちらに公式のアナウンスがあります。SDK40では、「SDK 39
から大きな変更はない」とのことですが、個人的に「Reanimated v2-rc
が使える」ことが気になり、触ってみました。
つくったアプリ
今回は、アニメーションの動作を確認するために、ボタンを押したら絵文字が吹き出すアプリ👇を作りました。このアプリで、ReactNative標準のAnimated
のものと、Reanimated v2-rc
をいれたアプリを比較しました。
標準のAnimatedをつかったアプリ
アニメーションのあるアプリをつくってみる
標準のAnimated
標準のAnimated
をつかってアニメーションを描画させるコード例を、ざっくり示します。公式ドキュメントはこちらです。「標準のAnimatedをつかったアプリ」は、このようなコードで作成しました。
/* AnimationIcon.tsx */
/* 標準ライブラリのAnimatedを使う */
import { StyleSheet, Animated, Easing, Text } from "react-native";
export class AnimationIcon extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
/* 絵文字の座標と、透明度を変化させます */
animeY: new Animated.Value(0),
animeX: new Animated.Value(0),
animeOpacity: new Animated.Value(1),
};
}
componentDidMount() {
this._startAnimation();
}
componentWillUnmount() {
this.state.animeX.stopAnimation(); // アニメーションの後処理
}
_startAnimation = () => {
const toValueY = /* どこまでY座標を変化させるか */
Animated.timing(this.state.animeY, {
toValue: toValueY,
duration,
useNativeDriver: true,
// アニメーションをどのように変化させたいか
// https://reactnative.dev/docs/easing
easing: Easing.inOut(Easing.linear),
delay: delay,
}).start();
/* 他の値もアニメーションを定義する */
};
render() {
const icon = this.props.icon || "😊";
return (
<>
<Animated.View
style={[
styles.icon,
/* アニメーションで変化させる値をstyleにあてる */
{ opacity: this.state.animeOpacity },
{
transform: [
{ translateY: this.state.animeY },
{ translateX: this.state.animeX },
],
},
]}
>
<Text style={styles.iconText}>{icon}</Text>
</Animated.View>
</>
);
}
}
react-native-reanimated対応
さて、上記で示した標準のAnimatedを使ったアプリをreact-native-reanimated
対応させてみましょう。
Reanimatedとは
expo SDK 40
の 公式アナウンスより、
Now with more bugfixes and improvements, the react-native-reanimated v2 release candidate is available in SDK 40!
とありますので、expo SDK 40ではReanimated v2-rc
が使えるようです。追加するライブラリとしては、 react-native-reanimated
となります。
React Native アドベントカレンダー 3日目の記事React Native 2020年の振り返りにもあるように、2020/11にReactNativeで対応されたものが、今回Expoでも対応されたということですね。ReactNativeのアニメーションの中でも特に、Androidのアニメーションは遅いので、このライブラリを使うと早くなるかを見てみます。
Reanimatedをいれる
ドキュメントReanimatedのとおりに、まずはライブラリの追加をしてみます。なんと、これだけです![1]
expo install react-native-reanimated
# yarnを使っている人向け
yarn add react-native-reanimated@2.0.0-rc.0
# babel.config.jsを編集し、
# plugins: ["react-native-reanimated/plugin"]を追加する
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: ["react-native-reanimated/plugin"],
};
};
Reanimatedを使う
上記のとおり追加したライブラリをつかったアニメーションを実装してみます。
/* AnimationIcon.tsx */
/* 追加したReanimatedライブラリをつかう */
import { StyleSheet, Text } from "react-native";
import Animated, {
Easing,
useSharedValue,
useAnimatedStyle,
withTiming,
} from "react-native-reanimated";
/* Hooks対応しないと使えないようでした */
export const AnimationIcon: React.FC<Props> = ({ icon = "😊" }) => {
const valueY = useSharedValue(/* 最終値 */);
useEffect(() => {
valueY.value = /* 初期値 */;
}, []);
const transformStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: withTiming(valueY.value, {
duration: FADE_DURATION,
easing: Easing.inOut(Easing.linear),
}),
},
/* 省略 */
],
};
});
const opacityStyle = useAnimatedStyle(() => {
/* こちらも同様に */
});
return (
<>
{/* 上記で用意したReanimatedのスタイルを当てる */}
<Animated.View style={[styles.icon, transformStyle, opacityStyle]}>
<Text style={styles.iconText}>{icon}</Text>
</Animated.View>
</>
);
};
DEMO - Androidによるアニメーションの比較
Reanimatedでつくったアプリと、標準のAnimatedをつかったアプリを比較してみましょう。どうでしょうか。
標準のAnimated | Reanimatedを使った場合 |
---|---|
ぱっと見、スムーズになった気がしますね!!!
特にボタンを押し始めたときの挙動が滑らかになったようですね。
計測する
上記のDemoでも表示していますが、パフォーマンスモニターをみてみます。
パフォーマンスモニターは、実機で見ている場合は端末を振ると表示できます。Androidのエミュレーターでは、ターミナルから adb shell input keyevent 82
を実行すると開くことができます。
パフォーマンスモニターを開くと、画面右上に表示されます。その中でも、 JS xx fps
の数値が重要です。
JS xx fps
の数値は、秒間にJSフレームレートを描画できた回数を表す数値[2]です。
通常この値は60であり、この値が小さいほど描画が「カクつく」ことになります。
この値を比較すると、数値的にも違いがあること・Reanimatedの方がより滑らかなこと、がわかります。
- 標準のAnimated: 5 前後
- Reanimated v2: 5-25 前後
まとめ
アニメーションを使う場合は、Reanimatedをつかうと動きが滑らかになることを確認できました。
ExpoでもSDK40で、簡単に対応できるようになっていました。
お知らせ
12/26〜の技術書典10で、「Firestore Testing −なぜテストを書くのか、どう書くのかがよくわかる!−」 という本を出版予定です。
こちらの👉👉サークルページ👈👈 に追加される予定です。お楽しみに!
-
bare workflowの場合には、追加の作業がありますので、こちらのドキュメント通りの作業が必要ですが、今回は割愛します。 ↩︎
-
パフォーマンスの指標について、詳しくはこちらのReactNativeドキュメントに記載されています。 ↩︎
Discussion