web-dev-qa-db-ja.com

CoreAnimationアニメーションの連鎖

Core Animationコンテキストでアニメーションをチェーンするための最もエレガントでモジュール式の方法はどれですか?

つまり、他のアニメーションが終了したときに開始するアニメーションを実行することを意味します(たとえば、positionを変更してからopacityを変更します)。通常のアプローチは、プロパティを直接変更することです。

layer.position = new_point;
layer.opacity = 0.0f;

しかし、これは同時にそれらを行います。片方をもう片方を待たせたい。

そして、さまざまなオブジェクトのアニメーションをチェーンするのはどうですか?私は次のように使用されるCATransactionについて読みました:

[CATransaction begin]
layer1.property = new_property;
[CATransaction begin]
layer2.property2 = new_property2;
[CATransaction commit];
[CATransaction commit];

しかし、それは機能していないようです。

34
Jack

アニメーションのグループ化を使用して、アニメーションのbeginTimeフィールドを使用することもできます。次のようなものを試してください。

CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
[posAnimation setFromValue:[NSNumber numberWithFloat:0.0]];
[posAnimation setToValue:[NSNumber numberWithFloat:1.0]];
// Here's the important part
[posAnimation setDuration:10.0];
[posAnimation setBeginTime:0.0];

CABasicAnimation *borderWidthAnimation = [CABasicAnimation animationWithKeyPath:@"borderWidth"];
[borderWidthAnimation setFromValue:[NSNumber numberWithFloat:0.0]];
[borderWidthAnimation setToValue:[NSNumber numberWithFloat:1.0]];
// Here's the important part
[borderWidthAnimation setDuration:10.0];
[borderWidthAnimation setBeginTime:5.0];

CAAnimationGroup *group = [CAAnimationGroup animation];
[group setDuration:10.0];
[group setAnimations:[NSArray arrayWithObjects:posAnimation, borderWidthAnimation, nil]];

[layer addAnimation:group forKey:nil];

アニメーション全体の長さが10秒であることに注意してください。最初のものは2番目の0から始まり、2番目のものは5秒から始まります。

76
Matt Long

Mattが指摘したように、開始時刻が異なる同じレイヤーの異なるアニメーションで構成されるアニメーショングループを作成できます。スタンドアロンのCAAnimationオブジェクトまたはCAAnimationグループのデリゲートを設定することもできます。各アニメーションが終了すると、animationDidStop:finished:デリゲートメソッドが呼び出されます(アニメーションの一部であることに注意してください)。グループは、デリゲートのanimationDidStop:finished:メソッドを呼び出しません。

CAAnimation animationDidStop:finished:メソッドの使用をより強力にするクールなトリックを見つけました。メソッドsetValue:forKey:を使用して、キー@ "animationCompletionBlock"を使用して、コードのブロックをスタンドアロンのアニメーションまたはアニメーショングループに追加します。次に、完成したばかりのアニメーションで@ "animationCompletionBlock"キーをチェックする、一般的なanimationDidStop:finished:メソッドを記述し、見つかった場合は、そこでコードのブロックを実行します。

その手法の実用的な例については、githubでこのプロジェクトをご覧ください。

完了ブロック付きのCAAnimationデモ

また、アニメーションのグループを内部に設定します

[CATransaction begin];
//...
[[CATransaction commit];

あなたが提案したように、ブロックします。これを行う場合、CATransactionクラスメソッドsetCompletionBlock:を使用して、現在のトランザクショングループ内のすべてのアニメーションが完了したときにコードのブロックを呼び出すことができます。 1つのトランザクションの完了ブロックは、次のトランザクションをトリガーできます。

5
Duncan C

setCompletionBlockメソッドを使用してこれを実行し、最初のアニメーションが終了したときに次のアニメーションをトリガーするクロージャを定義します。

[CATransaction begin]
layer1.property = new_property;
CATransaction.setCompletionBlock {
    [CATransaction begin]
    layer2.property2 = new_property2;
    [CATransaction commit];
}
[CATransaction commit];
1
wcochran

各アニメーションの開始時刻と終了時刻を別々に設定することを常に好んでいるのは、次のとおりです。

私はA2DynamicDelegate(開発は現在 BlocksKit -Repoで行われています。理由は<_ <)を使用して、CAAnimationのCategoryにcompletionBlockプロパティを実装しました。

これにより、次のようなことができるようになりました。

CAAnimation *a = ...
CAAnimation *b = ...
CAAnimation *c = ...

a.completionHandler = ^{
    [self.layer addAnimation:b forKey:@"foo"];
    [self.layer addAnimation:c forKey:@"bar"];
};

はるかに柔軟です:)

完了ハンドラーのコードをアップロードしました ここ 。ただし、ヘッダーファイルの通知を確認してください。メソッドが呼び出されない理由は本当に混乱しています。

0
Ahti

あなたの例のように、CAアニメーションを「ネスト」できるとは思いません。

アニメーションにデリゲートを指定し、デリゲートのanimationDidStop:finished:セレクター内に2番目の「トランジション」を配置する必要があります。

Appleの アニメーションタイプとタイミングプログラミングガイド を見てみたいと思うかもしれません。

0
Meltemi