慢下来&使用CoreAnimation加速动画

时间:2012-02-13 23:22:03

标签: core-animation

我正在尝试对我的应用程序应用慢动作效果,就像你按下Shift键如何减慢Mac OS的大部分图形效果一样。

我的应用程序使用CoreAnimation,所以我认为它应该没什么大不了的:将speed设置为较慢的值(如0.1)并在完成后将其设置回1 ,我走了。

不幸的是,这似乎不是正确的方法。减速效果很好,但是当我想恢复到正常速度时,它会恢复,就像速度一直是1一样。这基本上意味着如果我按住Shift足够长的时间,只要我释放它,动画就会立即完成。

我找到了一个技术质量保证页面,解释了如何暂停和恢复动画,但如果它不是完全暂停动画,我似乎无法做到正确。我在时间扭曲方面肯定不是很擅长。

使用CoreAnimation减慢然后恢复动画的正确方法是什么?

这是有用的代码:

-(void)flagsChanged:(NSEvent *)theEvent
{
    CALayer* layer = self.layer;
    [CATransaction begin];
    CATransaction.disableActions = YES;
    layer.speed = (theEvent.modifierFlags & NSShiftKeyMask) ? 0.1 : 1;
    [CATransaction commit];
}

1 个答案:

答案 0 :(得分:4)

棘手的问题......

我使用基本的UIView设置了测试。 我从它的当前点到目标点启动它的图层动画。

为了减慢核心动画的速度,我实际上必须构建并替换一个新动画(因为你不能修改现有的动画)。

了解当前动画已经进行了多远是特别重要的。这是通过访问beginTime,currentTime,计算经过的时间,然后确定新动画的持续时间应该有多长来完成的。

- (void)initiate {
    if(!initiated) {
        [CATransaction begin];
        [CATransaction disableActions];
        [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]];
        CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"];
        ba.duration = 10.0f;
        ba.fromValue = [NSValue valueWithCGPoint:view.layer.position];
        ba.toValue = [NSValue valueWithCGPoint:CGPointMake(384, 512)];
        [view.layer addAnimation:ba forKey:@"animatePosition"];
        [CATransaction commit];
        initiated = YES;
    }
}

- (void)slow {
    [CATransaction begin];
    CABasicAnimation *old = (CABasicAnimation *)[view.layer animationForKey:@"animatePosition"];
    CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"];
    CFTimeInterval animationBegin = old.beginTime;
    CFTimeInterval currentTime = CACurrentMediaTime();
    CFTimeInterval elapsed = currentTime - animationBegin;
    ba.duration = [[old valueForKey:@"duration"] floatValue] - elapsed;
    ba.duration = [[old valueForKey:@"duration"] floatValue];
    ba.autoreverses = [[old valueForKey:@"autoreverses"] boolValue];
    ba.repeatCount = [[old valueForKey:@"repeatCount"] floatValue];
    ba.fromValue = [NSValue valueWithCGPoint:((CALayer *)[view.layer presentationLayer]).position];
    ba.toValue = [old valueForKey:@"toValue"];
    ba.speed = 0.1;
    [view.layer addAnimation:ba forKey:@"animatePosition"];
    [CATransaction commit];
}

- (void)normal {
    [CATransaction begin];
    CABasicAnimation *old = (CABasicAnimation *)[view.layer animationForKey:@"animatePosition"];
    CABasicAnimation *ba = [CABasicAnimation animationWithKeyPath:@"position"];
    CFTimeInterval animationBegin = old.beginTime;
    CFTimeInterval currentTime = CACurrentMediaTime();
    CFTimeInterval elapsed = currentTime - animationBegin;
    ba.duration = [[old valueForKey:@"duration"] floatValue] - elapsed;
    ba.autoreverses = [[old valueForKey:@"autoreverses"] boolValue];
    ba.repeatCount = [[old valueForKey:@"repeatCount"] floatValue];
    ba.fromValue = [NSValue valueWithCGPoint:((CALayer *)[view.layer presentationLayer]).position];
    ba.toValue = [old valueForKey:@"toValue"];
    ba.speed = 1;
    [view.layer addAnimation:ba forKey:@"animatePosition"];
    [CATransaction commit];
}

注意:上面的代码仅适用于1个方向,而不适用于自动反转的动画......