我正在尝试制作一系列动画,我在CAAnimationGroup
找到了正确的类来实现该对象。在实践中,我添加了一个视图不同的子视图,我想用弹跳效果动画他们的条目,事实是我想看到他们的动画发生在前一个完成后。我知道我可以设置代理,但我认为CAAnimationGroup
是正确的选择。
后来我发现组动画只能属于一个图层,但我需要它在屏幕上的不同图层上。当然在托管层上不起作用。
一些建议?
- (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];
}
答案 0 :(得分:23)
CAAnimationGroup
用于将多个CAAnimation
子类堆叠在一起形成动画,例如,一个动画可以执行缩放,另一个动画可以移动它,而第三个可以旋转它,它不是用于管理多个图层,而是用于多个叠加动画。
尽管如此,我认为解决问题的最简单方法是将每个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
,CACurrentMediaTime()
在使用beginTime
属性时是必需的(它基本上是“现在”的高精度时间戳,用于动画)。整行可以解释为now + duration * i
。
必须注意,如果将CAAnimation
添加到CAAnimationGroup
,则其beginTime
会相对于群组的开始时间,因此值为5.0
在动画上,整个小组开始后5.0
秒。在这种情况下,您不使用CACurrentMediaTime()
答案 1 :(得分:2)
如果您查看the documentation,则会注意到CAAnimationGroup
继承自CAAnimation
,而CAAnimation
只能分配给CALayer
。它的目的是让您可以轻松创建和管理您希望同时应用于CALayer
的多个动画,而不是管理多个CALayer
对象的管理器动画。
为了处理不同CALayer
或UIView
个对象之间不同动画的排序,我使用的一种技术是为每个对象/动画创建一个NSOperation
,然后将它们放入{ {1}}管理排序。这有点复杂,因为您必须使用动画完成回调来告诉NSOperationQueue
它已完成,但如果您编写了一个NSOperation
的良好动画管理子类,它可以相当方便并允许您创建复杂的排序路径。实现排序目标的低租金方式是在NSOperation
对象上设置beginTime
属性(来自它CAAnimation
协议的采用),以便获得时间你想要的。
话虽如此,我将指出一些我编写的代码和开源代码,以解决您描述的完全相同的用例。您可能会发现on github here(包含相同的代码)。我将添加以下注释: