2009-02-12 5 views
28

J'écris une application pour iPhone, et j'ai une image que j'aimerais faire tourner vers l'extérieur.Puis-je utiliser CGAffineTransformMakeRotation pour faire pivoter une vue de plus de 360 ​​degrés?

Actuellement mon code ressemble à ceci (enveloppé dans un beginAnimations/bloc commitAnimations):

scale = CGAffineTransformScale(CGAffineTransformIdentity, 5.0f, 5.0f); 
swirl = CGAffineTransformRotate(scale, M_PI); 
[player setTransform:swirl];  
[player setAlpha:0.0f]; 

Mais je trouve que si j'essaie de changer l'angle de la rotation, disons, 4 * M_PI, il ne tourne pas du tout. Est-il possible d'obtenir une rotation de 720˚ en utilisant CGAffineTransformRotate, ou dois-je passer à une autre technologie?

Si je dois passer à une autre technologie, recommanderiez-vous d'utiliser un autre thread (ou une minuterie) pour faire moi-même l'animation, ou OpenGL serait-il une meilleure solution?

Merci,
Blake.

Répondre

64

Vous pouvez faire pivoter une vue d'un certain nombre de radians, qu'elle soit inférieure à une rotation complète ou à plusieurs multiples d'une rotation complète, sans avoir à diviser la rotation en morceaux. À titre d'exemple, le code suivant va tourner une vue, une fois par seconde, pendant un nombre de secondes spécifié. Vous pouvez facilement le modifier pour faire tourner une vue d'un certain nombre de rotations ou d'un certain nombre de radians.

- (void) runSpinAnimationWithDuration:(CGFloat) duration; 
{ 
    CABasicAnimation* rotationAnimation; 
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 
    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ]; 
    rotationAnimation.duration = duration; 
    rotationAnimation.cumulative = YES; 
    rotationAnimation.repeatCount = 1.0; 
    rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 

    [myView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"]; 
} 
+0

Cela fonctionne. Merci de l'avoir posté et d'avoir insisté pour commenter les posts des autres! J'étais sur le point de partager mon animation! – Dimitris

+0

J'avais l'habitude de les diviser aussi et cela ne semblait pas juste. – mahboudz

+0

Assurez-vous de faire cela pour transform.rotation.z J'ai eu des problèmes en essayant de le faire sur Transformer avec CATransform3DMakeRotation. J'ai continué à courir dans "verrou de cardan" quand j'ai utilisé la fonction de rotation de faire. Quand j'utilise transform.rotation.z comme indiqué ci-dessus, cela fonctionne magnifiquement! – Jay

5

Vous pouvez, mais vous devrez diviser votre animation en rotations en demi-cercle. Je fournis un exemple de ceci en réponse à this question, en utilisant une CABasicAnimation répétée appliquée au calque sous la vue. Comme je le suggère, faire ces demi-rotations comme parties d'un CAKeyframeAnimation serait probablement la meilleure façon de structurer cela, parce que l'animation serait plus fluide (il y a un léger accroc entre les demi-rotations dans mon exemple), et vous pourriez faire une belle accélération/décélération au début et à la fin.

+0

Cool. Cela semble faire ce que j'espérais, et je me dis que je peux aussi ajouter une transformation de mise à l'échelle, et recevoir une notification de retour à mon cours par moi-même. Merci! – bwinton

+2

Il est incorrect de dire que vous devez diviser une animation en rotations en demi-cercle. Vois ma réponse. – mahboudz

+0

Vous le faites, si vous comptez sur un CATransform3D comme valeur que vous animez. Je n'avais pas pensé à votre approche, en utilisant les extensions keypath fournies par Core Animation pour les champs de structure de transformation. Vous avez raison, c'est probablement une façon plus simple d'aborder cela. –

5

Répondre au titre: Oui, CGAffineTransform peut tourner de plus de 360 ​​degrés.
Réponse à la question: Oui, mais vous ne pouvez pas l'animer car il n'y a rien à animer.

Rappelez-vous que the affine transformation is a matrix, et en ce qu'une matrice de rotation contient le sinus et le cosinus de numéros précalculée. Il est comme si vous avez dit:

CGFloat angle = 4.0 * M_PI; 
NSAffineTransformStruct matrix = { 
    .m11 = cos(angle), 
    .m12 = sin(angle), 
    .m21 = -sin(angle), 
    .m22 = cos(angle), 
    .tx = 0.0, 
    .ty = 0.0 
}; 
NSAffineTransform *transform = [NSAffineTransform transform]; 
[transform setTransformStruct:matrix]; 

Maintenant, nous allons examiner quelques valeurs d'échantillon pour cos et sin:

  • cos(0π) = 1
  • sin(0π) = 0
  • cos(2π) = 1
  • sin(2π) = 0
  • cos(4π) = 1
  • sin(4π) = 0

Rappelez-vous, la matrice ne contient pas l'angle - elle ne contient que le cosinus et sinus. Et ces valeurs ne changent pas d'un multiple de cercle à l'autre. Par conséquent, il n'y a rien à animer.

(Notez que Calculator.app donne des résultats erronés pour cos (xπ) et sin (xπ). Essayez Grapher, calc ou Google.)

Vous aurez besoin de diviser l'animation en fractions de cercle. Les demi-cercles suggérés par Brad Larson feront l'affaire.

+2

Vous n'avez pas besoin de diviser l'animation. Vois ma réponse. – mahboudz

Questions connexes