2013-12-11 10 views
7

ich nur eine Keyframe-Animation wie diese erstellt haben:Keyframe-Animation Schlüssel Zeit

[UIView animateKeyframesWithDuration:10 delay:0 options:0 animations:^{ 
    [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:.1 animations:^{ 
     view.alpha = 0; 
    }]; 
} completion:nil]; 

Und das ist ein CAKeyframeAnimation, die erstellt wird:

(lldb) po [self.layer animationForKey:@"opacity"] 
<CAKeyframeAnimation:0x10a6364b0; keyTimes = (
    0, 
    "0.1", 
    1 
); values = (
    1, 
    0, 
    0 
); calculationMode = linear; delegate = <UIViewKeyframeAnimationState: 0x10a6358d0>; fillMode = both; timingFunction = easeInEaseOut; duration = 10; keyPath = opacity> 

Frage:

Die Die gesamte Animation sollte 10 Sekunden dauern, wobei die Deckkraft für 10 * 0,1 = 1 Sekunde animiert wird, oder? Wenn ich mir die Animation ansehe, wird die Änderung weit länger als 1 Sekunde animiert.

Warum?

+0

Die Debug-Ausgabe (von 0 bis 1 Sekunde belebter von 100% auf 0%, dann richtig sucht 9 weitere Sekunden animieren von 0% bis 0%). Kannst du beschreiben, was du siehst? Änderst du die Opazität woanders? Sie haben keine langsamen Animationen im Simulator eingeschaltet, oder? –

+0

Ja, CAKeyframeAnimation sieht völlig richtig aus. Was ich sehe ist, dass die Opazität für 2 - 2,5 Sekunden geändert wird, nicht eine. Ich ändere es nicht irgendwo und Slow Animationen sind ausgeschaltet. –

+1

Sehen Sie das gleiche, wenn Sie die Keyframe-Animation selbst erstellen (nicht über die UIView-Methoden)? –

Antwort

8

Der Grund ist, dass die Timing-Funktion der Animation nicht linear ist.

„Zeit und Raum sind relative Begriffe.“ - Relativitätstheorie

Schicht und Animationen verwenden ein hierarchisches Timing-System, wobei jedes Objekt seine eigene lokale Zeit hat, die seine Eltern abhängig ist und sein eigene Timing-Parameter.

Zum Beispiel haben Animationen eine Timing-Funktion, die ihre Stimulation definiert. Die Standard-Timing-Funktionen für eine Animation, die von UIKit erstellt wurde, ist die Ease-In-Timing-Funktion, die ein Timing definiert, das langsam beginnt, sich in der Mitte seiner Dauer beschleunigt und dann vor dem Abschluss wieder verlangsamt. Es sorgt für flüssige Animationen, die nicht abrupt starten oder stoppen. Es wird aber auch die Key-Zeiten Ihrer Keyframe-Animation beeinflussen, was ärgerlich ist, wenn Sie genaues Timing benötigen.

Sie können das Easy-In-Easy-Out-Timing deaktivieren, indem Sie die Option UIViewAnimationOptionCurveLinear an die animateKeyframesWithDuration:delay:options:animations:completion:-Methode übergeben. Ich bin nicht sicher, ob es beabsichtigt ist, da Sie den Wert von UIViewAnimationOptions zu UIViewKeyframeAnimationOptions umwandeln müssen, und die Dokumentation sagt nichts darüber. Vielleicht eine bessere (aber ausführliche) Art und Weise ist es, den Keyframe-Animation-Block in einem Standard-Animationsblock wie folgt einbetten:

[UIView animateWithDuration:10 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ 
    [UIView animateKeyframesWithDuration:0 /*inherited*/ delay:0 options:0 animations:^{ 
     [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:.1 animations:^{ 
      view.alpha = 0; 
     }]; 
    } completion:nil]; 
} completion:nil]; 
+0

Ich habe zwei Stunden damit verbracht, mich zu wundern, warum diese * $! §-Animation nicht linear war, auch wenn ich 'UIViewKeyframeAnimationOptionCalculationModeLinear' (plus den Standardwert) übergeben habe. Sie haben mich gerettet, danke. – AncAinu

+0

Ich bin zufällig auf diese Antwort gestoßen. Ich mache das selbst seit Jahren und es behebt sicher das Problem, obwohl ich immer noch nicht genau herausfinden konnte, warum ich es auf diese Weise "hacken" muss, indem ich die Standard-UIView-Animation um eine KeyFrameAnimation einbettele. Es funktioniert, ich weiß, aber meine Neugier juckt mich :-) +1 für die Analyse. – Unheilig

+0

@Nicolas scheint dies nicht mehr auf iOS 9 zu funktionieren. Irgendwelche Alternative? – Xzya