Facebookは先頃,同社のiOS用PaperアプリのアニメーションエンジンであるPopをオープンソース化した。Popは"ファイア・アンド・フォーゲット"の範疇を越えるアニメーション,例えばインタラクティブなアニメーションを容易に開発することを目標として,固定的なアニメーションに留まらず,"Sping"や"Decay"などのダイナミックなアニメーション,独自のアニメーション作成などをサポートする。
Kimon Tsinteris氏(Push Pop Pressの共同創業者,同社は2001年にFacebookに買収された)によると,FacebookのPaperアプリ開発者たちがPopを作成したおもな動機は,スクリーン上の要素を物理的にリアルな方法で,直接操作(Direct Manipulation)可能にすることだった。Objc.ioの記事でインタラクティブなアニメーションを詳しく分析したChris Eidhof氏とFlorian Kugler氏は,2007年に最初のiPhoneが発表されたときのテーブルをスクロールする操作が聴衆に与えた強い印象を思い出させてくれる。合わせて彼らは,直接操作のパラダイムを受け入れて,実行時あるいは中断時のインタラクティブ操作が可能なアニメーションを実行できるアプリケーションの数は,現時点では非常に少ないことも指摘している。iOSでのファイア・アンド・フォーゲット形式の例は,ホームスクリーンでのグループのオープンとクローズ,ナビゲーションコントローラのアニメーションなどだ。一方でAppleのPassbookアプリなどは,リアルでインタラクティブなアニメーションを提供している。
FacebookのBrian Amerige氏は,ユーザのジェスチャとリアルなアニメーションとのギャップを埋めることの複雑さについて,分かりやすく説明してくれている。そこで重要なのは,ジェスチャの終了する時点に,それと同じ速さでアニメーションを続けることによって,ユーザの操作の意図を維持することだ。そうすればアニメーションがリアルな流れを持ってジェスチャを引き継いで,一連の操作を完了させることが可能になる。
iOSのレイヤベースのアニメーションエンジンであるCore Animationでは,アニメーションの開始速度の指定はネイティブにはサポートされていない。そのため,Core AnimationのデフォルトAPIで作り出したアニメーションを使ってインタラクティブな操作をしようとすると,そのアニメーションは不連続ベロシティカーブ(discontinuous velocity curve)を示すことになる。
ApplieはiOS 7で,UIKit Dynamicsというアニメーションフレームワークを導入した(WWDC 2013のセッション206および221参照)。UIDynamicItem
プロトコルを実装するものすべてをアニメーション化可能な仮想物理エンジンをベースとする。Eidhof, Kugler両氏によると,このフレームワークは複雑な動作を可能にする非常にパワフルなものである反面,ユーザインターフェースで一般的に必要とされるような種類のアニメーションに対しては,APIの規模がやや大き過ぎるようだ。
これに対してPopでは,全体を可能な限りシンプルにしようとしている。 特に注目すべきなのは,PopのAPIが,iOS開発者が慣れ親しんでいるCore AnimationのAPIに極めて近いことだ。そのためPopのAPIでは,Core Animationと非常によく似た方法で新たなアニメーションを作成することができる。
POPSpringAnimation *spring = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation]; spring.velocity = [NSValue valueWithCGPoint:velocity]; [viewToAnimate.layer pop_addAnimation:spring forKey:@"rotationAnimation"];
この短いサンプルは,UI要素の回転に対してバウンドエフェクトの追加を可能にするものだ。UIPanGestureRecognizerを使って制御される回転のジェスチャの最後に,この効果を使用することができる。
- (void)panHandler:(UIPanGestureRecognizer *) panGesture { if (panGesture.state == UIGestureRecognizerStateEnded) { CGPoint velocity = [recognizer velocityInView:self.view]; POPSpringAnimation *spring = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation]; spring.velocity = [NSValue valueWithCGPoint:velocity]; [viewToAnimate.layer pop_addAnimation:spring forKey:@"rotationAnimation"]; } else { //-- transform the layer as per your gesture logics } }
初期速度の他にもPopでは,張力や摩擦,弾性など,Springアニメーション用にいくつかのパラメータを定義することができる。
APIこそCore Animationにヒントを得ているが,Pop自体は,アニメーション用の定義であるCALayer
プロパティのように,アニメーション操作に制約されたものではない。実施にPopでは,Core Animationのアニメーション可能なプロパティを拡張して,CALayer
のアニメーション化に使用されるものと同じAPIを,UIView
のUINavigationBar
やUITabBar
のプロパティのアニメーション化に使用することができる。ここで非常に興味深く思われるのが,Popがオープンソースであるという点を考えると,これら以外のクラスにもアニメーション用プロパティの追加が可能であるという点だ。Popが現在サポートしているアニメーション用プロパティの一覧は,ヘッダファイルPOPAnimatableProperty.hに記述されている。
Popの魔法を作り上げている基本的なメカニズムは,アニメーションに特定のリズムを提供するために,CADisplayLink
を使用してすべてのアニメーションロジックを自分自身で処理する,というものだ。
このアプローチにおける欠点は,UIKit Dynamicsに共通するものとしてAndy Matuschak氏が指摘するように,CADisplayLink
がアプリケーションと同じプライオリティで動作することである。これに対して,UIViewやCAAnimationアニメーションを処理するレンダリングサーバは高プライオリティで動作するため,システム上で動作している他タスクの影響を受けることは少ない。