6

我的 中有两个旋转动画CAAnimationGroup,一个从零开始,另一个从该状态重复和自动反转:

- (void)addWobbleAnimationToView:(UIView *)view amount:(float)amount speed:(float)speed
{
    NSMutableArray *anims = [NSMutableArray array];

    // initial wobble
    CABasicAnimation *startWobble = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    startWobble.toValue = [NSNumber numberWithFloat:-amount];
    startWobble.duration = speed/2.0;
    startWobble.beginTime = 0;
    startWobble.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [anims addObject:startWobble];

    // rest of wobble
    CABasicAnimation *wobbleAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    wobbleAnim.fromValue = [NSNumber numberWithFloat:-amount];
    wobbleAnim.toValue = [NSNumber numberWithFloat:amount];
    wobbleAnim.duration = speed;
    wobbleAnim.beginTime = speed/2.0;
    wobbleAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    wobbleAnim.autoreverses = YES;
    wobbleAnim.repeatCount = INFINITY;
    [anims addObject:wobbleAnim];

    CAAnimationGroup *wobbleGroup = [CAAnimationGroup animation];
    wobbleGroup.duration = DBL_MAX; // this stops it from working
    wobbleGroup.animations = anims;

    [view.layer addAnimation:wobbleGroup forKey:@"wobble"];
}

由于 CFTimeInterval 被定义为双精度,我尝试将动画组的持续时间设置为DBL_MAX,但这会阻止动画组运行。但是,如果我将其设置为较大的数字,例如 10000,则运行良好。在 a 的持续时间内我可以使用的最大数字是多少CAAnimationGroup,以确保它尽可能接近无穷大?

更新:似乎如果我输入一个非常大的值,例如DBL_MAX / 4.0它会冻结一秒钟,然后开始动画。如果我输入这个值DBL_MAX / 20.0,那么一开始的冻结就会小很多。似乎具有如此大的持续时间值导致它冻结。除了使用非常大的持续时间值之外,还有更好的方法吗?

4

2 回答 2

1

我现在面临着完全相同的问题......我希望有人证明我错了,但我认为处理这种情况的唯一合理方法是将第一个动画移动到 a CATransaction,并将其与自动反转动画链接使用:

[CATransaction setCompletionBlock:block];

这并不理想,但可以完成工作。

关于您关于从后台返回时暂停动画的问题,这是 CoreAnimation 框架的经典限制,已为此提出了许多解决方案。我解决它的方法是简单地在动画的随机点重置动画,通过随机化timeOffset属性。用户无法准确判断动画状态应该是什么,因为应用程序在后台。这是一些可以提供帮助的代码(查找//RANDOMIZE!!评论):

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(startAnimating)
                                             name:UIApplicationWillEnterForegroundNotification
                                           object:[UIApplication sharedApplication]];

...

for (CALayer* layer in _layers) 
{
    // RANDOMIZE!!!
    int index = arc4random()%[levels count];
    int level = ...;
    CGFloat xOffset = ...;

    layer.position = CGPointMake(xOffset, self.bounds.size.height/5.0f + yOffset * level);

    CGFloat speed = (1.5f + (arc4random() % 40)/10.f);
    CGFloat duration = (int)((self.bounds.size.width - xOffset)/speed);

    NSString* keyPath = @"position.x";
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:keyPath];

    anim.fromValue      = @(xOffset);
    anim.toValue        = @(self.bounds.size.width);
    anim.duration       = duration;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    // RANDOMIZE!!
    anim.timeOffset     = arc4random() % (int) duration;
    anim.repeatCount    = INFINITY;

    [layer removeAnimationForKey:keyPath];
    [layer addAnimation:anim forKey:keyPath];
    [_animatingLayers addObject:layer];
}
于 2013-08-02T20:22:25.873 回答
0

使用单个关键帧动画而不是一组两个单独的动画要简单得多。

- (void)addWobbleAnimationToView:(UIView *)view amount:(CGFloat)amount speed:(NSTimeInterval)speed {
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
    animation.duration = 2 * speed;
    animation.values = @[ @0.0f, @(-amount), @0.0f, @(amount), @0.0f ];
    animation.keyTimes = @[ @0.0, @0.25, @0.5, @0.75, @1.0 ];
    CAMediaTimingFunction *easeOut =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    CAMediaTimingFunction *easeIn =[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    animation.timingFunctions = @[ easeOut, easeIn, easeOut, easeIn ];
    animation.repeatCount = HUGE_VALF;
    [view.layer addAnimation:animation forKey:animation.keyPath];
}
于 2013-08-02T21:08:07.013 回答