使用CAAnimationGroup进行序列animation
我正在尝试制作一系列animation,我在CAAnimationGroup
find了实现该对象的正确类。 在实践中,我添加了一个视图不同的子视图,我想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()
如果您查看文档 ,您将注意到CAAnimationGroup
从CAAnimation
inheritance,并且CAAnimation
只能分配给一个CALayer
。 它的目的是让您轻松地创build和pipe理多个animation,而不是同时应用到CALayer
上,而不是pipe理多个CALayer
对象的animation。
为了处理不同CALayer
或UIView
对象之间不同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视图的图层中。