2013/03/21更新

[XCODE] CAAnimationを使ってキーフレームアニメーションを実装する

このエントリーをはてなブックマークに追加            

こんにちは、@yoheiMuneです。
今日は、iPhoneアプリでアニメーションを行う方法のうち、CAAnimationを使ってちょっと凝ったアニメーションを実装する方法を、ブログに書きたいと思います。

画像


CAAnimationとは

iPhoneアプリではアニメーションを行う方法はいくつか用意されていますが(UIViewベース、CALayerベース、OpenGLESベースなど)、 CALayerベースでアニメーションをさせると、比較的簡単なコードで凝ったアニメーションを行うことが出来ます。
そのCALayerベースでのアニメーションを実現する方法がCAAnimationです。

CAAnimationにはいくつかのアニメーション指定方法が用意されていますが、今回はKeyframeを用いた実装を紹介します。



今回行うアニメーション

今回行うアニメーションは、小さなダイアログが出てきて、少し止まった後に、大きくなりながらフェードアウトするという動きです。
以下の動画が実際に作ったアニメーションとなります。


http://www.youtube.com/watch?v=w3VpZkGchmA



まずは準備

CAAnimationを扱うためには、以下のライブラリを追加する必要があります。
<QuartzCore/QuartzCore.h>
このライブラリを、プロジェクトに追加して、利用するソースファイルでは上記ライブラリをインポートします。


あと、アニメーション対象のViewも準備します。今回は以下のようなViewを作成しました。
// アニメーション対象のUIView
animationView = [[UIView alloc] initWithFrame:CGRectMake((self.view.frame.size.width - ANIMATION_VIEW_SIZE)/2, (self.view.frame.size.height - ANIMATION_VIEW_SIZE*3)/2, ANIMATION_VIEW_SIZE, ANIMATION_VIEW_SIZE)];
animationView.opaque = NO;
animationView.backgroundColor = [UIColor colorWithWhite:0.2 alpha:0.85];
animationView.layer.cornerRadius = 10.0f;
animationView.layer.masksToBounds = NO;
animationView.layer.shadowOffset = CGSizeMake(5, 5);
animationView.layer.shadowOpacity = 0.7f;
animationView.layer.shadowRadius = 5.0f;
animationView.layer.shadowColor = [UIColor blackColor].CGColor;
[self.view addSubview:animationView];

// アニメーション対象のViewにのせる画像
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(15, 10, 50, 50)];
imageView.image = [UIImage imageNamed:@"icon_pocket"];
[animationView addSubview:imageView];

// アニメーション対象のViewにのせるラベル
titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 60, ANIMATION_VIEW_SIZE - 10, 20)];
titleLabel.opaque = NO;
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.font = [UIFont boldSystemFontOfSize:14.0f];
titleLabel.textColor = [UIColor colorWithWhite:0.91f alpha:1];
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.text = @"Pocket";
[animationView addSubview:titleLabel];



CAAnimationでKeyframeアニメーションを行う

ここから本題です。CAAnimationでキーフレームアニメーションを行います。
以下のように実装することで、拡大縮小と透明度を操作しながら、アニメーションを行うことが出来ます。


// scaleXとscaleYの変化量をkeyframe形式で指定する。
// arrayの個数は、後述のtimingの個数に合わせる。
NSArray *values = [NSArray arrayWithObjects:
                   [NSNumber numberWithFloat:0.1],
                   [NSNumber numberWithFloat:1.0],
                   [NSNumber numberWithFloat:1.0],
                   [NSNumber numberWithFloat:7.0],
                   nil];

// 透明度の変化量をkeyframe形式で指定する。
// arrayの個数をscaleX/scaleYと合わせて、それらと同じタイミングで
// 変化するようにしている。
NSArray *values2 = [NSArray arrayWithObjects:
                   [NSNumber numberWithFloat:0.1],
                   [NSNumber numberWithFloat:1.0],
                   [NSNumber numberWithFloat:1.0],
                   [NSNumber numberWithFloat:0.0],
                   nil];    

// Keyframeで利用する時間割を指定(0.0から1.0の間)
// 0.0と1.0は、必ず指定する。
NSArray *timing = [NSArray arrayWithObjects:
                   [NSNumber numberWithFloat:0.0],
                   [NSNumber numberWithFloat:0.25],
                   [NSNumber numberWithFloat:0.85],
                   [NSNumber numberWithFloat:1.0],
                   nil];

// アニメーション時間(単位:秒)
float duration = 1.5f;

// scaleXのkeyframeアニメーションを指定
// アニメーション対象のプロパティを、animationWithKeyPathを使って
// Key-Value Coding形式で指定する。
CAKeyframeAnimation *keyframe = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.x"];
keyframe.values = values;
keyframe.keyTimes = timing;
keyframe.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
keyframe.duration = duration;

// scaleYのアニメーション指定
CAKeyframeAnimation *keyframe2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale.y"];
keyframe2.values = values;
keyframe2.keyTimes = timing;
keyframe2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
keyframe2.duration = duration;

// 透明度のアニメーション指定
// animationWithKeyPathで指定できる内容の詳細は、
// CoreAnimation Programming Guideを参照
CAKeyframeAnimation *keyframe3 = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
keyframe3.values = values2;
keyframe3.keyTimes = timing;
keyframe3.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
keyframe3.duration = duration;


// CATransactionを使って、3つのアニメーションの開始を
// 合わせるようにする。
[CATransaction begin];
// また、アニメーション完了時のコールバックメソッドも指定する。
[CATransaction setCompletionBlock:^{
    NSLog(@"animation end.");
    [animationView removeFromSuperview];
}];
[animationView.layer addAnimation:keyframe forKey:@"transform.scale.x"];
[animationView.layer addAnimation:keyframe2 forKey:@"transform.scale.y"];
[animationView.layer addAnimation:keyframe3 forKey:@"opacity"];
// commitすることで初めてアニメーションが始まる。
// CATransactionを使わずに、上記のaddAnimationをすると、
// addAnimationを呼んだ時点でアニメーションが始まってしまう。
[CATransaction commit];

といった感じです。
CSS3のKeyframeアニメーションとも似ていて、書き方が簡単な割に、複雑なアニメーションが指定できていい感じです。



参考資料

CALayer関連のアニメーションは、以下の資料が大変参考になります。

- CoreAnimation Programming Guide(日本語)



最後に

Ojbective-Cって、便利なコードを知ってれば知ってるほどコーディングが楽になるので、勉強しがいのある言語で良いなぁと思います。 今後も便利なコードがあれば、ブログで紹介します!!

最後までご覧頂きましてありがとうございました。





こんな記事もいかがですか?

RSS画像

もしご興味をお持ち頂けましたら、ぜひRSSへの登録をお願い致します。