2012-02-13 79 views
5

我試圖將慢動作效果應用於我的應用程序,就像如何按Shift鍵可以減慢Mac OS的大多數圖形效果。使用CoreAnimation減速並加速動畫

我的應用程序使用CoreAnimation,所以我想應該沒有什麼大問題:設置speed一些速度較慢的值(如0.1),並設置回1一旦我做的,我來到這裏。

不幸的是,這似乎不是正確的方法。減速效果很好,但是當我想恢復到正常速度時,它會像整個時間速度爲1一樣恢復。這基本上意味着,如果我持續了足夠長的Shift,只要我釋放它,動畫即刻完成。

我發現了一個技術QA頁面來解釋如何暫停和恢復動畫,但如果不是完全暫停動畫,我似乎無法做到。我在時間扭曲方面絕對不是很好。

什麼是減慢速度然後用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

通常按住shift只適用於動畫開始時移舉行,它放手不會立即加速動畫。這通常可以簡單地通過使動畫的持續時間取決於在動畫創建時是否按下移位來實現。 – 2012-02-13 23:31:21

+1

@凱文巴拉德,我知道;但除了這是一個很酷的效果之外,在我的情況下,它可能會在任何時候都有所減慢。 – zneak 2012-02-13 23:35:49

+0

嗯,我想當你改變速度時,你還必須計算一個時間偏移量,以便舊時速度*時間==新聞速度*時間+偏移量 – 2012-02-13 23:36:45

回答

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個方向,不與自動翻轉動畫...

+1

我發佈了我的代碼。 – zneak 2012-03-10 17:49:33