使用CAAnimationGroup进行序列animation

我正在尝试制作一系列animation,我在CAAnimationGroupfind了实现该对象的正确类。 在实践中,我添加了一个视图不同的子视图,我想animation他们的入口具有反弹效果,事实是,我希望看到他们的animation发生在前一个完成后。 我知道我可以设置代表,但我认为CAAnimationGroup是正确的select。
后来我发现组animation只能属于一层,但是我需要在屏幕上的不同层次上。 当然,托pipe层不起作用。 有些build议?

 - (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]; } 

CAAnimationGroup是为了让多个CAAnimation子类堆叠在一起形成一个animation,例如,一个animation可以执行一个缩放,另一个可以移动它,而第三个可以旋转它,但并不意味着要pipe理多个图层,有多个叠加animation。

也就是说,我认为解决你的问题最简单的方法就是给每个CAAnimation分配一个与所有前面的持续时间总和相等的beginTime ,来说明:

 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 ,而使用beginTime属性(基本上是animation中使用的“now”的高精度时间戳CACurrentMediaTime()时, CACurrentMediaTime()是必需的。 整条线可以被解释为now + duration * i

必须注意的是,如果将一个CAAnimation添加到一个CAAnimationGroup ,那么它的beginTime就相对于该组的开始时间,所以对一个animation的值为5.0 ,在整个组开始之后是5.0秒。 在这种情况下,您不使用CACurrentMediaTime()

如果您查看文档 ,您将注意到CAAnimationGroupCAAnimationinheritance,并且CAAnimation只能分配给一个CALayer 。 它的目的是让您轻松地创build和pipe理多个animation,而不是同时应用到CALayer上,而不是pipe理多个CALayer对象的animation。

为了处理不同CALayerUIView对象之间不同animation的sorting,我使用的一种技术是为每个对象/animation创build一个NSOperation ,然后将它们放到NSOperationQueue来pipe理sorting。 这有点复杂,因为你必须使用animation完成callback来告诉NSOperation它已经完成了,但是如果你写了一个NSOperation的好的animationpipe理子类,它可以相当方便,并且允许你创build复杂的sortingpath。 完成sorting目标的低租金方式是简单地在您的CAAnimation对象(来自于它采用CAMediaTiming协议)上设置beginTime属性,以获得您想要的时间。

有了这个说法,我将指出你写的一些代码,我写了一些代码,并且开源来解决你描述的完全相同的用例。 你可以在github上find它(包括相同的代码)。 我将添加以下注释:

  • 我的animationpipe理代码允许您通过识别图像变化的顺序和时间,缩放比例,位置变化等来定义您的animation。实际上,在plist文件而不是代码中调整animation非常方便和干净这就是我写这个的原因)。
  • 如果用户不希望与您创build的子视图进行交互,那么创build图层对象实际上会更好(开销更less),并将其作为子图层添加到托pipe视图的图层中。