Facebook Paper のアニメーションエンジン「pop」のソースコードを読んでみる
先日公開されたFacebookのpop、アニメーションライブラリですよとリリース前から言われてたものの、popについて語られるときは大抵「Paperアプリのテクノロジーをオープンソース化」という枕詞がつくので、Paper風UIコンポーネント(ジェスチャーでヌルヌル操作できる)もライブラリに含まれてたらいいなとか、せめてサンプルが Paper 風だといいなとかうっすら期待してたのですが、まったくそんなことなく、やっぱり純粋なるアニメーションライブラリでした。サンプルプロジェクトすらつかない硬派っぷり。。
じゃあ今まで実現が難しかったような何か(ド派手なアニメーションとか?)ができるようになってるのか、というとそういうわけでもなくて、
In addition to basic static animations, it supports spring and decay dynamic animations, making it useful for building realistic, physics-based interactions.
ベーシックなアニメーション以外には、 spring (バネ風にボヨヨーンとなる)と、 decay (スーッと速度が減衰する) アニメーションをサポートしている、ってことで、正直地味です。
バネっぽいアニメーションに関しては iOS 7 で標準サポートされた し、イージングについてはCore Animation で自由に数式や関数の曲線を指定できるので、このあたりはどうとでもできるし、そのあたりを いい感じにラップしてくれてる OSS もいくつかあります。
そんなわけで pop の神髄はそこ自体ではないはず、この記事 にあるような、パフォーマンスへの配慮 とかカスタマイズ性 にあるはず、で、それって具体的にどういう実装になってるんだろう、とソースを見てみることにしました。
popクラス群の依存関係
`POPVector` とか `TransformationMatrix` とかどうアニメーションに活かされてるのかパッとわからなかったので、 objc_dep でクラスの依存関係を出力 してみました。
・・・相当入り組んでますが、局所的にみればこのクラスはこれとあれに参照されてるのか、とかいろいろわかります。
まずはリファクタリング・・・
さて、コードを読んでいくか、と思ったものの、「え、ほんとにこの入り組んだ依存関係、これでいいの?」というのが気になってきて、依存関係の交通整理をしてプルリク送りました。
https://github.com/facebook/pop/pull/57
(修正後の依存関係図)
自分および自分のチームだけでメンテしていく分にはこんなこと気にする必要もないと思うのですが、なにぶんオープンソースプロジェクトで、かつ多くの人が手を入れる超有名リポジトリなので、このへん交通整理しとかないと今後もっとカオスになってくるんじゃないかと思いまして。。
自分のコードであればもっと盛大にリファクタリングするのですが、まだ設計思想をしっかり理解できてない(Internalナントカ、Privateナントカはこのライブラリにおいてどういう役割として定義してるのかとか)ので、修正は最小限にしました。
(2014.5.8 Merge されました!)
POPSpringAnimation
ばね風アニメーションを司るクラス POPSpringAnimation については、下記記事でアルゴリズムが解説されています。
http://otsukafumiyuki.hatenablog.com/entry/2014/05/05/163856
(コメント欄にてお知らせいただきました!)
POPSpringSolver で加速度、位置、速度を算出しており、その際にベクトル演算が諸々定義された POPVector を参照しています。
使い方の参考例
popを使ったサンプルコードをGitHubで検索していろいろ探してみた中でおもしろかったもの。
- GitHub - victorBaro/PopPlayground: Examples and Controls made entirely using Pop (Facebook's framework)
- popのいろんな機能を使ってる
- デモ動画もあり(長い。。)
- GitHub - Appletone/PopExample: Facebook Pop Example
- UITextFieldに文字を入れるたびにぴょこっとさせる
- デモ動画あり
(つづく・・・かも・・・)