2012-02-13 5 views
5

Shiftキーを押したときにMac OSのほとんどのグラフィカルエフェクトを遅くする方法と同じように、アプリケーションにスローモーションエフェクトを適用しようとしています。CoreAnimationでアニメーションのスローダウンとアクセラレーションを行う

私のアプリケーションはCoreAnimationを使用していますので、私はそれがとても重要あってはならないと思った:いくつかの低速の値(のような0.1)にspeedを設定し、私は終わりだ、とここで私は行くいったん戻っ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

通常シフトを保持するだけのアニメーションに適用が開始しましたアニメーションのスピードアップ。これは、一般に、アニメーションが作成された時点でシフトが押されているかどうかに依存して、アニメーションの持続時間を変えることによって簡単に達成できます。 –

+1

@ケビン・バラード、私は知っている;しかし、それはクールな効果を除いて、それはおそらく私の文脈ではいつでもそれを遅くすることができる可能性があります。 – zneak

+0

まあ、速度を変更すると、oldspeed * time == newspeed * time + offset –

答えて

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

関連する問題