11

私は一連のアニメーションを作成しようとしてCAAnimationGroupいます。そのオブジェクトを達成するための適切なクラスを見つけました。実際には、ビューにさまざまなサブビューを追加していて、それらのエントリをバウンス効果でアニメーション化したいのですが、実際には、前のサブビューが終了した直後にアニメーションが発生するのを見たいのです。CAAnimationGroupデリゲートを設定できることは知っていますが、正しい選択だと思いました。
後で、グループ アニメーションは 1 つのレイヤーにのみ属することができることを発見しましたが、画面上のさまざまなレイヤーに必要です。もちろん、ホスティング層では機能しません。いくつかの提案?

- (void) didMoveToSuperview {
    [super didMoveToSuperview];
    float startTime = 0;
    NSMutableArray * animArray = @[].mutableCopy;
    for (int i = 1; i<=_score; i++) {
        NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject: self.greenLeaf];
        UIImageView * greenLeafImageView = [NSKeyedUnarchiver unarchiveObjectWithData: archivedData];
        greenLeafImageView.image = [UIImage imageNamed:@"greenLeaf"];
        CGPoint leafCenter =  calculatePointCoordinateWithRadiusAndRotation(63, -(M_PI/11 * i) - M_PI_2);
        greenLeafImageView.center = CGPointApplyAffineTransform(leafCenter, CGAffineTransformMakeTranslation(self.bounds.size.width/2, self.bounds.size.height));
        [self addSubview:greenLeafImageView];

        //Animation creation
        CAKeyframeAnimation *bounceAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
        greenLeafImageView.layer.transform = CATransform3DIdentity;
        bounceAnimation.values = @[
                                  [NSNumber numberWithFloat:0.5],
                                  [NSNumber numberWithFloat:1.1],
                                  [NSNumber numberWithFloat:0.8],
                                  [NSNumber numberWithFloat:1.0]
                                  ];

        bounceAnimation.duration = 2;
        bounceAnimation.beginTime = startTime;
        startTime += bounceAnimation.duration;

        [animArray addObject:bounceAnimation];
        //[greenLeafImageView.layer addAnimation:bounceAnimation forKey:nil];


    }
    // Rotation animation
    [UIView animateWithDuration:1 animations:^{
        self.arrow.transform = CGAffineTransformMakeRotation(M_PI/11 * _score);
    }];
    CAAnimationGroup * group = [CAAnimationGroup animation];
    group.animations = animArray;
    group.duration = [[ animArray valueForKeyPath:@"@sum.duration"] floatValue];
    [self.layer addAnimation:group forKey:nil];
}
4

2 に答える 2

27

CAAnimationGroup複数のCAAnimationサブクラスを積み重ねてアニメーションを形成するためのものです。たとえば、1 つのアニメーションでスケールを実行し、もう 1 つのアニメーションで移動させ、3 つ目のアニメーションで回転させることができます。これは複数のレイヤーを管理するためのものではなく、複数のレイヤーを持つためのものです。アニメーションを重ねる。

とはいえ、あなたの問題を解決する最も簡単な方法は、以前のものすべての期間の合計に相当するものをそれぞれに割り当てることですCAAnimationbeginTime

for i in 0 ..< 20
{
    let view : UIView = // Obtain/create the view...;
    let bounce = CAKeyframeAnimation(keyPath: "transform.scale")

    bounce.duration  = 0.5;
    bounce.beginTime = CACurrentMediaTime() + bounce.duration * CFTimeInterval(i);

    // ...

    view.layer.addAnimation(bounce, forKey:"anim.bounce")
}

誰もが を取得duration * iし、はプロパティCACurrentMediaTime()を使用するときに必要であることに注意してくださいbeginTime(これは基本的に、アニメーションで使用される「今」の高精度のタイムスタンプです)。行全体は として解釈できますnow + duration * i

CAAnimations が に追加された場合CAAnimationGroup、そのbeginTimeはグループの開始時間に対して相対的になるため5.0、アニメーションの の値は5.0、グループ全体が開始してから数秒後になることに注意してください。この場合、CACurrentMediaTime() を使用しません。

于 2013-07-21T06:29:25.533 に答える
4

ドキュメントを確認すると、 はCAAnimationGroupから継承されCAAnimationCAAnimationは 1 つの にのみ割り当てることができることに注意してくださいCALayerCALayer複数のオブジェクトのアニメーションを管理するためではなく、同時に適用する複数のアニメーションを簡単に作成および管理できるようにすることを目的としていCALayerます。

CALayer異なるまたはオブジェクト間の異なるアニメーションのシーケンスを処理するためUIViewに、私が使用する手法は、NSOperationオブジェクト/アニメーションごとに を作成し、それらを にスローしNSOperationQueueてシーケンスを管理することです。アニメーション完了コールバックを使用して終了したことを伝える必要があるため、これは少し複雑ですがNSOperation、 の優れたアニメーション管理サブクラスNSOperationを作成すると、かなり便利になり、洗練されたシーケンス パスを作成できるようになります。シーケンスの目標を達成する低コストの方法は、必要なタイミングを取得するためにbeginTime、オブジェクトのプロパティを適切に設定するだけですCAAnimation(これは、プロトコルの採用に由来します)。CAMediaTiming

そうは言っても、あなたが説明したのとまったく同じユースケースを解決するために私が書いてオープンソースにしたいくつかのコードを紹介します。こちらの github で見つけることができます(同じコードが含まれています)。次のメモを追加します。

  • 私のアニメーション管理コードを使用すると、画像の変更、スケールの変更、位置の変更などのシーケンスとタイミングを特定することで、plist でアニメーションを定義できます。コードではなく plist ファイルでアニメーションを調整する方が、実際には非常に便利でクリーンです (これが私がこれを書いた理由です)。
  • 作成したサブビューをユーザーが操作することが想定されていない場合は、実際には、ホスティング ビューのレイヤーにサブレイヤーとして追加されるレイヤー オブジェクトを作成する方がはるかに優れています (オーバーヘッドが少ない)。
于 2013-07-20T22:14:09.200 に答える