2013-12-11 12 views
7

Ho appena creato un animazione keyframe come questo:animazione keyframe momento chiave

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

E questo è un CAKeyframeAnimation che viene creato:

(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> 

Domanda:

Il l'intera animazione dovrebbe impiegare 10 secondi con l'opacità che anima per 10 * 0,1 = 1 secondo, giusto? Quando guardo l'animazione, il cambiamento viene animato in modo molto più lungo di 1 secondo.

Perché?

+0

Il debug di output è corretta (da 0 a 1 secondo animate da 100% a 0% poi per 9 secondi in più animati da 0% a 0%). Puoi descrivere quello che stai vedendo? Stai cambiando l'opacità da qualche altra parte? Non hai attivato animazioni lente nel simulatore, giusto? –

+0

Sì, CAKeyframeAnimazione sembra completamente giusto. Quello che vedo è che l'opacità viene cambiata per 2 - 2,5 secondi, non uno. Non lo sto cambiando da nessuna parte e le animazioni lente sono disattivate. –

+1

Vedete la stessa cosa se create l'animazione del fotogramma chiave da soli (non tramite i metodi di UIView)? –

risposta

8

Il motivo è che la funzione di temporizzazione dell'animazione non è lineare.

“Tempo e spazio sono concetti relativi.” - Theory of relativity

livello ed animazioni utilizzano un sistema di distribuzione gerarchica, dove ogni oggetto ha il suo tempo locale che dipende dei suoi genitori e la sua propri parametri di temporizzazione.

Ad esempio, le animazioni hanno una funzione di temporizzazione che definisce il loro pacing. Le funzioni di temporizzazione predefinite per un'animazione creata da UIKit è la funzione di temporizzazione della facilità d'uso che definisce un tempo che inizia lentamente, accelera a metà della sua durata, quindi rallenta nuovamente prima di completarlo. Crea animazioni fluide che non si avviano o si fermano bruscamente. Tuttavia sarà anche temperare con i momenti chiave dell'animazione keyframe, che è fastidioso quando hai bisogno di un tempismo preciso.

È possibile disattivare il tempo di andamento facilitato passando l'opzione UIViewAnimationOptionCurveLinear al metodo animateKeyframesWithDuration:delay:options:animations:completion:. Non sono sicuro se è inteso in quanto è necessario trasmettere il valore da UIViewAnimationOptions a UIViewKeyframeAnimationOptions e la documentazione non dice nulla al riguardo. Forse un modo migliore (ma più dettagliato) è di incorporare il blocco fotogramma chiave animazione all'interno di un blocco di animazione standard come questo:

[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

Ho passato due ore a chiedermi perché questa animazione * $! § non fosse lineare anche se passavo 'UIViewKeyframeAnimationOptionCalculationModeLinear' (più il suo valore predefinito). Lei mi ha salvato, grazie. – AncAinu

+0

Mi sono imbattuto casualmente in questa risposta. Lo sto facendo da anni e sicuramente risolve il problema, anche se non sono ancora riuscito a scoprire esattamente perché ho bisogno di "hackerarlo" in questo modo incorporando l'animazione standard di 'UIView' attorno a un KeyFrameAnimation. Funziona, lo so, ma la mia curiosità mi prude :-) +1 per l'analisi. – Unheilig

+0

@Nicolas questo non sembra funzionare su iOS 9 più. Qualche alternativa? – Xzya