Help us understand the problem. What is going on with this article?

Objective-Cでアニメーションまとめ

More than 5 years have passed since last update.

アニメーションさせるにはいくつか方法があるみたい。

  • beginAnimations:context:メソッドを使う
  • animateWithDuration:animations:メソッドを使う
  • CATransactionを利用する方法
  • CABasicAnimationを利用する方法

animateWithDuration:animations:を使う方法

animateWithDuration:animations:メソッドはクラスメソッドとして実行する。
(細かく指定する場合はanimateWithDuration:delay:options:animations:メソッドを使う)
blockでコールバックが実行できるので、こちらのほうが簡単。

ちなみにイメージとしては

  1. animateWithDuration:animations:クラスメソッドのanimations:に変更したい値をblock経由で渡す
  2. 渡された情報を元に、最終的なアニメーション終了後の値が設定される
  3. アニメーション実行
  4. completion:で受け取ったblockを実行して終了

という流れ。

サンプルコード

//UIViewを生成
UIView *animView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
[animView setBackgroundColor:[UIColor redColor]];

[UIView animateWithDuration:1.0f delay:0.5f options:UIViewAnimationOptionCurveEaseInOut animations:^ {
    //アニメーションで変化させたい値を設定する(最終的に変更したい値)
    animView.frame = CGRectMake(0, 0, 320, 100);
} completion:^ {
    //完了時のコールバック
}];

optionsに指定できるオプション

  • UIViewAnimationOptionCurveEaseInOut
  • UIViewAnimationOptionCurveEaseIn
  • UIViewAnimationOptionCurveEaseOut
  • UIViewAnimationOptionCurveLinear

beginAnimations:context:を使う方法

※コメントで指摘いただきました。
beginAnimations:context:メソッドのcontextは主にユーザデータとして利用するもののようです。
最初はCGContextRefを渡していましたが、これは必要ありません。

こちらもUIViewのクラス・メソッドで実行する。
手順としては

1. `CGContextRef`型のコンテキストを取得
  1. UIViewのbeginAnimations:context:メソッドでアニメーション実行の開始を宣言
  2. setAnimationDuration:メソッドでアニメーション時間を設定
  3. setAnimationDelegate:メソッドでアニメーションイベントのデリゲート先を設定
  4. setAnimationDidStopSelector:メソッドで終了時のデリゲートメソッドを指定
  5. コンテキストに登録したい viewの変更をそれぞれ設定
  6. commitAnimationsメソッドでアニメーションを実行

要はコンテキスト作って、その間に設定されたviewの変更はアニメーションされるようになる、ってことですね。

サンプルコード

UIView *animView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];

//アニメーション開始のコンテキストを設定
[UIView beginAnimations:nil context:nil];

//アニメーションの実行時間を設定(例では2秒)
[UIView setAnimationDuration:2.0];

//アニメーションイベントを受け取るデリゲート先
[UIView setAnimationDelegate:self];

//アニメーション終了後に実行されるコールバック
[UIView setAnimationDidStopSelector:@selector(endAnimation)];

//アニメーションの詳細
animView.frame = CGRectMake(0, 0, 320, 100);
//...以下、アニメーションしたいものを列挙していく。


//アニメーション開始
[UIView commitAnimations];


CATransactionを使う

上記ふたつはそれぞれUIViewに実装されたメソッドでした。
CATransactionは、CALayerに実装されたメソッドです。
ただ、基本的な概念は上記で説明したように、アニメーションの開始を宣言する部分と実際にどういう値に変化させたいかを指定することになります。
サンプルコードを見比べてもらえれば、UIViewに対する操作とCALayerに対する操作という違いがあるだけで、基本的な部分が一緒だということが分かるかと思います。

//CALayerを取得
CALayer *layer = animView.layer;

//CoreAnimationのアニメーション開始宣言
[CATransaction begin];
[CATransaction setAnimationDuration:5.0];

//どう変化させたいのかの変化を指定
layer.frame = CGRectMake(0, 0, 200, 300);

//CATransactionを入れ子にすることによって複数のアニメーションを実行可能
[CATransaction begin];
[CATransaction setAnimationDuration:1.0];

layer.opacity = 0.5;

//CALayerのアニメーションを開始
[CATransaction commit];
[CATransaction commit];

アニメーションを中止する

上記のアニメーションを実行中に、それを中止するには以下のメソッドを呼べば中止されます。

[layer removeAllAnimations];

CABasicAnimationを使う

CABasicAnimationクラスを使うことで、キーフレームアニメーションを実装できます。
CABasicAnimationを使う手順は、アニメーションさせたいプロパティ名をNSStringで与え、それに対してどうアニメーションさせるか、というのを指定します。

サンプルコード

//なにがしかのUIViewからlayerを取得
CALayer *layer = sampleView.layer;

//CABasicAnimationオブジェクトを生成
//サンプルでは"position"をアニメーションさせる例。
//他に、transformを変更したい場合は@"transform.translate.x"などと指定する
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];

//アニメーション時間
animation.duration = 2.5;

//アニメーションの繰り返し回数
animation.repeatCount = 1;

//アニメーションの開始時間
animation.beginTime = CACurrentMediaTime() + 2; //2秒後から開始

//アニメーション終了時に、逆方向にもアニメーションさせるか
animation.autoreverses = NO; //YESにした場合はアニメーションが往復する

//アニメーションのイージングを制御
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

//アニメーションの開始と終了の値を設定
animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(320, 480)];

//アニメーション終了時、元の状態に戻すか否かの設定(サンプルではアニメーション後はそのまま)
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

//アニメーションキーを設定(任意の名前)
[layer addAnimation:animation forKey:@"sample-animation"];

複数アニメーションを組み合わせる

アニメーションを組み合わせるにはCAAnimationGroupクラスを利用します。

サンプルコード

//ひとつめのアニメーション
CABasicAnimation *animation1 = [CABasicAnimation animationWithKeyPath:@"position.x"];

//終点を設定
animation1.toValue = @50.0f;

//ふたつめのアニメーション
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"position.y"];

animation2.fromValue = @0.0f;
animation2.toValue = @55.0f;

//アニメーショングループを作成
CAAnimationGroup *group = [CAAnimationGroup animation];

//アニメーショングループの設定
group.duration = 3.0;
group.repeatCount = 1;
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;

//グループにアニメーションを追加
group.animations = @[animation1, animation2];
[layer addAnimation:group forKey:@"group-animation-test"];

HTMLを使っている人には、CSSによるアニメーションをベースに考えるとイメージしやすいかもしれません。


UIImageViewを使ってスプライトアニメーション

UIImageViewにはスプライトアニメーションを簡単に行える方法があります。
まず簡単にフローを書くと、

  1. UIImageインスタンスをスプライトアニメーションで使用する分だけ生成(10コマなら10個)
  2. 生成したUIImageをNSMutableArrayインスタンスの配列として格納
  3. NSMutableArrayを、UIImageViewのanimationImagesプロパティにセット
  4. UIImageViewのanimationDurationanimationRepeatCountを設定する
  5. UIImageViewのstartAnimatingメソッドでアニメーション開始

そもそもプロパティでスプライトアニメーション用のものが存在していて、それに設定していく、という流れです。

サンプルコード

//スプライトアニメーションを表示するUIImageViewを生成
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];

//スプライトアニメーション用画像配列
NSMutableArray *imageList = [NSMutableArray array];

//コマ数分UIImageを生成
for (NSInteger i = 1; i < 10; i++) {
    NSString *imagePath = [NSString stringWithFormat:@"hoge_%d.png", i];
    UIImage *img = [UIImage imageNamed:imagePath];
    [imageList addObject:img];
}

[self.view addSubview:imageView];

//スプライトアニメーション用画像をセット
imageView.animationImages = imageList;

//アニメーションする時間
imageView.animationDuration = 2.0;

//アニメーションのリピート回数
imageView.animationRepeatCount = 5;

//アニメーション開始
[imageView startAnimating];

参考記事

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした