そーす

福岡在住のプログラマ

React Nativeのアニメーションで簡単なチュートリアル画面を作った

React Nativeで個人開発アプリを開発中なのですが、ちょうどアニメーション周りを結構調べていたので試しに簡単なチュートリアルを作ってみました。

f:id:saburesan:20170906143339g:plain

Component

ほとんどAnimatedを使いました。コンポーネントもデフォルトのAnimated.View, Text, Imageのみです。

一部LayoutAnimationを使っていますが、最初にLayoutAnimationを使っていた名残で変更していないだけです。

LayoutAnimationは導入も使い方も非常に楽なので気に入っていたのですが、複雑なアニメーションをしようとするとかなり面倒くさく、あまり自由度が無いところから使わなくなりました。

ARTを使ってSVGでやることも考えたのですが、Animatedでも十分パフォーマンスが出る結果だったので今回は採用していません。

saburesan.hatenablog.com

Easing

Easingもデフォルトのtimingとspringしか使っていません。

Sequence, Stagger, Parallel

アニメーションを連続で再生するためのAPIがありますが、今回はsequence, stagger, parallelを使いました。

facebook.github.io

ドキュメントを読んだだけだとStaggerの使い所があまりわからなかったのですが、

今回検索文字の入力の部分や、3回タップのアニメーションの所などで使っています。

Interpolate

今回、すべてのアニメーションはAnimated.Valueを使っています。

また、基本的にValueは0->1の変化のみとして、Animated.Valueの値をinterpolateメソッドで適宜補間する形にしました。

理由はValueの値をスタイルで直接使う値にしてしまうと同じタイミングで始まるアニメーションがあったときにAnimated.Valueを使いまわせないからです。

同じにタイミングでもEasingやDurationが違う場合などはParallelを使用していますが、

EasingもDurationも同じでいい場合が結構多くinterpolateで補間するほうがわかりやすくなりました。

Valueを0->1にしてinterpolateで補間することでアニメーション自体の定義とスタイルの定義を完全に別にして考える事ができるのでお薦めです。

ハマったこと

Animated.XXXにして無い時にエラーで上手く教えてくれない

これは私が初期にLayoutAnimationで組んで居た所をAnimatedに変更したときにコンポーネントの定義でAnimated.XXXにし忘れていたのですが、エラーが非常にわかりにくく手間取りました。

Devモードだとアニメーションが重すぎる

めっちゃ重たいです。デバッグ無理です。

Androidであれば開発モードのDev SettingsJS Dev Modeをオフにしてデバッグしましょう。

iOSAndroidと同じ事が出来ないのでReleaseビルドでデバッグしましょう。

position: ‘absolute'で指定しているAnimated.Viewを消すとそれ以降のアニメーションが重くなる

これはホントの所の原因がわかっていないのですが、フルスクリーン表示したViewをアニメーションが終わった後に描画しない処理(renderXXXがnullを返す)をすると、それ以降のアニメーションがやたら重くなる現象が起きました。

leftの値をいじって画面外に出しても重くなってしまい、完全な原因が謎です。

今回は一番最後にボタンをタップできるようにする必要があっただけのでフルスクリーンのViewにpointerEvents=“none”を設定することで解決できましたが、ちょっと謎ですね…

まとめ

今回やった範囲だとハマりどころが多いという感じはしませんでした。

JS側UIスレッド側のFPSも57~60位で特にパフォーマンスが悪くなるような事も特に無く、アニメーションは実際ネイティブで書くと面倒ですがAndroid/iOSどっちも同じように書けるのはかなりのメリットだなぁと思いました。

AnimatedのAPIはまだ使ってないものもありますし、ARTとAnimatedを組み合わせると更に自由度が上がると思いますので色々遊んでみたいと思います。