2009-02-12 14 views
28

Estoy escribiendo una aplicación para iPhone, y tengo una imagen que me gustaría girar hacia afuera.¿Puedo usar CGAffineTransformMakeRotation para rotar una vista de más de 360 ​​grados?

Actualmente mi código es el siguiente (envuelto en un beginAnimations/bloque commitAnimations):

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

pero me parece que si trato de cambiar el ángulo de la rotación a, digamos, 4 * M_PI, se no gira en absoluto. ¿Es posible obtener una rotación de 720˚ usando CGAffineTransformRotate, o debo cambiar a otra tecnología?

Si tengo que cambiar a otra tecnología, ¿me recomendaría usar otro hilo (o un temporizador) para hacer la animación, o OpenGL sería una mejor ruta?

Gracias,
Blake.

Respuesta

64

Puede girar una vista, por cierto número de radianes, independientemente de si es menos que una rotación completa o muchos múltiplos de una rotación completa, sin tener que dividir la rotación en partes. Como ejemplo, el siguiente código girará una vista, una vez por segundo, durante un número específico de segundos. Puede modificarlo fácilmente para hacer girar una vista por un cierto número de rotaciones, o por una cierta cantidad de radianes.

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

Esto funciona. ¡Gracias por publicarlo y por insistir cuando comentas en las publicaciones de otras personas! ¡Estaba a punto de dividir mi animación! – Dimitris

+0

Solía ​​dividirlos también y eso simplemente no parecía correcto. – mahboudz

+0

asegúrate de hacer esto para transform.rotation.z Tuve problemas al tratar de hacerlo en la transformación con CATransform3DMakeRotation. Seguí corriendo en "bloqueo de cardán" cuando usé la función de rotación de marca. ¡Cuando uso transform.rotation.z como se indica arriba, funciona muy bien! – Jay

5

Puedes, pero deberás dividir tu animación en rotaciones de medio círculo. Proporciono un ejemplo de esto en respuesta a this question, usando una CABasicAnimation repetitiva aplicada a la capa debajo de la vista. Como sugiero allí, hacer estas medias rotaciones como partes de una CAKeyframeAnimation probablemente sería la mejor forma de estructurar esto, porque la animación sería más suave (hay un ligero enganche entre medias rotaciones en mi ejemplo), y podrías hacer una buena aceleración/desaceleración al principio y al final.

+0

Cool. Esto parece hacer lo que estaba esperando, y creo que también puedo agregar una transformación de escalado y recibir una notificación de regreso a mi clase por mi cuenta. Gracias! – bwinton

+2

Es incorrecto decir que debe dividir una animación en rotaciones de medio círculo. Ver mi respuesta – mahboudz

+0

Lo hace, si confía en un CATransform3D como el valor que está animando. No había pensado en su enfoque, utilizando las extensiones de keypath que Core Animation proporciona para los campos de estructura de transformación. Tienes razón, esa es probablemente una manera más limpia de acercarte a esto. –

5

Respuesta al título: Sí, CGAffineTransform puede rotar más de 360 ​​grados sin problemas.
Respuesta a la pregunta: Sí, pero no se puede animar porque no hay nada que animar.

Recuerde que the affine transformation is a matrix, y que una matriz de rotación contiene los números de seno y coseno precalculados. Es como si dijeras:

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]; 

Ahora, vamos a revisar algunos valores de muestra para cos y sin:

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

Recuerde, la matriz no contiene el ángulo - que sólo contiene el coseno y seno. Y esos valores no cambian de un múltiplo de un círculo a otro. Por lo tanto, no hay nada para animar.

(Tenga en cuenta que Calculator.app da resultados erróneos para cos (xπ) y sin (xπ). Trate Grapher, calc o Google.)

que se necesitan para dividir la animación en fracciones de un círculo. Los semicírculos sugeridos por Brad Larson servirán muy bien.

+2

No es necesario dividir la animación. Ver mi respuesta – mahboudz

Cuestiones relacionadas