最近 FacebookがOSSとして公開した pop は
Paperで使われているアニメーションライブラリです
https://github.com/facebook/pop
少し触ってみたので基本的な使い方などをまとめてみます
##pop とは
公式ブログに記事があるのでそちらがとても参考になります
Introducing Pop, the animation engine behind Paper
iOS や OS X でアニメーションを実装しようとするとCoreAnimationを使うと思うのですが実はCoreAnimationはなかなか使いにくいライブラリだったりします。確かにCABasicAnimation
は簡単ですが、Timing Functionをlinear
, ease-in
, ease-out
, ease-in ease-out
の四種類と3次ベジェ曲線のいずれかからしか指定することができません。これだとバネだとかバウンドだとかの表現が出来ませんよね。一方CAKeyframeAnimation
は万能ですが、パスを逐一作らなければならず手間がかかりコードも煩雑になります。
pop はCABasicAnimation
の簡単さを保ちつつCAKeyframeAnimation
並みの表現力を持ったアニメーションを作れるAPIを提供しています。またそのAPIもCoreAnimationに似せていて学習コストを下げる工夫がされています。
pop の目標として
- よく使われるアニメーションを簡単に書けるようにすること
- 拡張可能なフレームワークであること
- 開発者にとって使いやすく強力なプログラミングモデルを構築すること
の3つが掲げてあり、今後もFacebookが中心となってメンテされていくことを考えると安心して使って行けます。
##基本的な使い方
###導入
Cocoapods経由でインストールします(もちろん直接プロジェクトに追加することも可能です)。適当なXcodeプロジェクトのルートフォルダにPodfile
を作成して
pod 'pop', '~> 1.0'
の行を追加しpod install
します。これで準備完了です☆
あとは使いたいファイルの先頭に
#import "pop/pop.h"
を追加しましょう。
###POPSpringAnimation
POPSpringAnimation
はpopの威力を知るのに一番簡単でとても強力な例になるでしょう。
まずはアニメーションさせる対象を作ります
_view = [[UIView alloc] initWithFrame:CGRectMake(200,200,80,80)];
[_view setBackgroundColor:[UIColor cyanColor]];
これに対し適当なタイミングでアニメーションオブジェクトを作成して登録してやることでアニメーションを発生させます。
例えば以下のようにします
POPSpringAnimation *animation = [POPSpringAnimation animation];
animation.property = [POPAnimatableProperty propertyWithName:kPOPLayerSize];
animation.toValue = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
animation.springBounciness = 24.0f;
animation.springSpeed = 6.0f;
[_view pop_addAnimation:animation forKey:@"bound"];
これで対象の大きさをバネのような弾性を持ったアニメーションで変化させることが出来ます。
例としてサイズの変更を挙げましたがPOPAnimatableProperty propertyWithName:
の引数の定数を変えることで色々なプロパティを変化させることが出来ます。用意されている定数の一覧はPOPAnimatableProperty.hで見ることが出来ます。
以上の断片的なコードをまとめて以下の様なViewControllerの実装を作ればすぐにでも試すことが出来ます。
ビルドしたら画面をタップしてみてください!
#import "pop/pop.h"
#import "ViewController.h"
@implementation ViewController
{
UIView *_view;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_view = [[UIView alloc] initWithFrame:CGRectMake(120, 120, 80, 80)];
[_view setBackgroundColor:[UIColor cyanColor]];
[self.view addSubview:_view];
[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(startAnimation)]];
}
-(void) startAnimation
{
POPSpringAnimation *animation = [POPSpringAnimation animation];
animation.property = [POPAnimatableProperty propertyWithName:kPOPLayerSize];
animation.toValue = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
animation.springBounciness = 24.0f;
animation.springSpeed = 6.0f;
[_view pop_addAnimation:animation forKey:@"spring"];
}
@end
パラメータを調節すればもっと激しい動きをさせることも出来ますよ!
参考: Playing with Pop (ii)
###POPDecayAnimation
POPDecayAnimation
はease-out
よりももっとゆっくり変化がとまるようなアニメーションです。
先ほどのstartAnimation
を例えば以下のように変更してみてください
-(void) startAnimation
{
POPDecayAnimation *animation = [POPDecayAnimation animation];
animation.property = [POPAnimatableProperty propertyWithName:kPOPLayerSize];
animation.velocity = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
[_view pop_addAnimation:animation forKey:@"decay"];
}
POPDecayAnimation
は少し癖があって例えばtoValue
のプロパティを設定するとエラーを吐きます。
これはこのオブジェクトがfromValue
とvelocity
とdeceleration
の3つのプロパティからduration
とtoValue
を自動的に決定するからです。なので使う時は前の3つを設定してやれば使うことが出来ます(実際にはfromValue
とdeceleration
はデフォルト値が存在するので省略可能です)。
###POPCustomAnimation
POPCustomAnimation
は以上3つのクラスとは違って自分でオリジナルのアニメーションを作るためのクラスです。
実際にどうやって作るのが正しいのかわかりませんが、実装をみながら簡単なアニメーションを作ってみたいと思います。
アニメーションといえばバウンドの表現もよく使うと思うのですがこれは標準では用意されていないようです。今回はPOPCustomAnimation
を使ってバウンドのアニメーションを実装してみたいと思います。
-(void) startAnimation
{
float duration = 0.6;
CGPoint fromValue = _view.frame.origin;
CGPoint toValue = CGPointMake(120,240);
float dx = toValue.x - fromValue.x;
float dy = toValue.y - fromValue.y;
POPCustomAnimation *animation = [POPCustomAnimation animationWithBlock:^BOOL(id target, POPCustomAnimation *animation) {
float t = (animation.currentTime-animation.beginTime)/duration;
float d = 8/pow(2, floor(log2(1 + 11*(1-t))));
float timing = pow(t*11/4-3*(1-1/d), 2) + (1-1/d)*(1+1/d);
UIView *view = (UIView *)target;
CGSize size = view.frame.size;
CGRect after = CGRectMake(fromValue.x + timing * dx, fromValue.y + timing * dy, size.width, size.height);
[view setFrame:after];
return t < 1.0;
}];
[_view pop_addAnimation:animation forKey:@"bounce"];
}
POPCustomAnimation animationWithBlock:
のブロックはアニメーションの各フレームで呼び出されるのでその中でtarget
がどのように変化するのかを記述しています。
ブロックの引数のanimation
からは
- beginTime - 開始時間
- currentTime - 現在の時間
- elapsedTime - 1ステップにかかった時間
が取得できるのでこれらの値を使ってtarget
のプロパティを更新して行きます。
今の場合target
には_view
が入っています。
ブロックの返り値はアニメーションを続けるかどうかの真偽値を返します。
今の場合はt
が1.0より小さい時はYES
が返ってアニメーションが継続され、t
が1.0より大きくなるとNO
が返ってその時点でアニメーションが停止します。
###POPBasicAnimation
POPBasicAnimation
はCABasicAnimation
と同等のアニメーションを置き換えたクラスになっています。
-(void) startAnimation
{
POPBasicAnimation *animation = [POPBasicAnimation animation];
//POPBasicAnimation *animation = [POPBasicAnimation easeInEaseOutAnimation];
animation.property = [POPAnimatableProperty propertyWithName:kPOPLayerSize];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.toValue = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
[_view pop_addAnimation:animation forKey:@"basic"];
}
コメントアウトしている
POPBasicAnimation *animation = [POPBasicAnimation easeInEaseOutAnimation];
は
POPBasicAnimation *animation = [POPBasicAnimation animation];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
と全く同等の処理になっています。
##まとめ
以上ざっと pop の基本的な使い方を見てきました。
紹介したのは
- POPSpringAnimation
- POPDecayAnimation
- POPCustomAnimation
- POPBasicAnimation
の四つだけでしたがどれもとても簡単に使えたと思います。
pop には他にも
- POPPropertyAnimation
- POPAnimatableProperty
などのクラスがありまだまだ出来ることは多そうです。
pop はBSDライセンスで公開されています。
https://github.com/facebook/pop