2010-07-15 16 views
3

que je veux animer un roulement à billes 1000 pixels à droite, en spécifiant une fonction de synchronisation dans le processus - quelque chose comme ceci:CAAnimation qui appelle une méthode dans des intervalles périodiques d'animation-progression?

UIView *ball = [[UIView alloc] initWithFrame:CGRectMake(0,0,30,30)]; 
CABasicAnimation* anim = 
     [CABasicAnimation animationWithKeyPath:@"transform.translation.x"]; 
anim.toValue = [NSNumber numberWithFloat:ball.frame.origin.x + 1000.0]; 
              // move 1000 pixels to the right 
anim.duration = 10.0; 
anim.timingFunction = [CAMediaTimingFunction functionWithControlPoints: 
         0.1 :0.0 :0.3 :1.0]; // accelerate fast, decelerate slowly 
[ball.layer addAnimation:anim forKey:@"myMoveRightAnim"]; 

Ce que je veux finalement est d'avoir une méthode, dire -(void)animationProgressCallback:(float)progress, être appelé pendant l'animation, à intervalles réguliers de la progression de l'animation en termes de «distance» absolue entre les valeurs de début et de fin, c'est-à-dire en ignorant la fonction de temporisation.

Je vais essayer d'expliquer l'exemple ci-dessus avec le roulement à billes 1000px à droite (tracée par l'axe y, dans notre cas 100% = 1000px):

alt text

Je veux que mon méthode de rappel à invoquer chaque fois que la balle a progressé de 250 pixels. En raison de la fonction de chronométrage, les 250 premiers pixels peuvent être atteints en = 2 secondes, la moitié de la distance totale atteinte juste à = 0,7 secondes plus tard (accélérations accélérées), le 750px marque un autre ti = 1,1 secondes plus tard, et ayant besoin du reste ti = 5,2 secondes pour atteindre la marque 100% (1000px).

Ce qui serait bien, mais ne sont pas fournis:

Si l'animation appelée méthode déléguée à des intervalles cours d'animation comme décrit, je ne aurais pas besoin de poser cette question ... ;-)

idées comment résoudre le problème:

Une solution que je peux penser est de calculer les valeurs de la courbe de Bézier, la carte que la ti k valeurs (nous savons l'animation totale durée), et lorsque l'animation est lancée, nous exécutons séquentiellement notre sélecteur animationProgresssCallback: avec ces retards manuellement.

De toute évidence, c'est fou (calculer bezier courbes manuellement ??) et, plus important encore, peu fiable (nous ne pouvons pas compter sur le thread d'animation et le thread principal pour être synchronisés - ou pouvons-nous?).

Des idées?

Dans l'attente de vos idées!

Répondre

1

idées sur la façon de résoudre le problème:

Une solution que je peux penser est de calculer les valeurs de la courbe de Bézier, carte que les valeurs de tik (nous savons la durée totale d'animation), et lorsque l'animation est démarrée, nous exécuter séquentiellement notre animationProgresssCallback: selector avec ces retards manuellement.

De toute évidence, cela est fou (calcul courbes bezier manuellement ??) et, plus important encore, peu fiable (nous ne pouvons pas compter sur le fil d'animation et le fil principal pour être synchronisé - ou pouvons-nous?).

En fait, c'est fiable. CoreAnimation est basé sur le temps, vous pouvez donc utiliser le délégué pour être averti lorsque l'animation commence réellement. Et à propos du calcul du Bézier ... eh bien regardez-le de cette façon: Cela pourrait être pire si vous voulez implémenter une surface dans OpenGLES vous devrez calculer un Bézier Cubique !. lol. Votre cas n'est qu'une dimension, n'est pas si difficile si vous connaissez les maths.

+0

Merci de m'avoir fait remarquer que je n'ai pas besoin de me soucier de la synchronisation inter-thread. Cela m'a encouragé à aller de l'avant et à le faire comme je l'ai proposé. Jusqu'à présent, ça a l'air bien! –