2009-03-22 8 views
8

Lo siento si esto es obvio o está cubierto en otro lugar, pero he estado buscando en Google todo el día y no he encontrado una solución que realmente funcionó.¿Puedo mover el origen al hacer una transformación de rotación en Cuarzo 2D para el iPhone?

Mi problema es el siguiente: actualmente estoy dibujando una imagen en una pantalla completa de UIView, por ejemplo, diremos que la imagen está en la esquina inferior derecha de UIView. Me gustaría hacer una transformación de rotación (CGAffineTransformMakeRotation) en el centro de esa imagen, sin embargo, de forma predeterminada, el comando de rotación gira alrededor del centro de la UIView self. Como resultado, mi imagen se mueve alrededor de la pantalla cuando giro en lugar de permanecer en su lugar y girar alrededor de su propio centro.

Según lo que he reunido, necesito traducir mi contexto para que el origen (centro de UIView) esté en el centro de mi imagen, Girar y restaurar el contexto traduciendo al lugar original.

Lo siguiente es lo más cercano que he puesto a trabajar, pero el problema es que mientras la imagen está girando, se mueve hacia abajo mientras gira. Creo que esto es causado por la animación interpolación de la primera etapa de traducir y tercera etapa se traduce en lugar de simplemente darse cuenta de que el punto de inicio y el final de los traduce sería el mismo ...

// Before this i'd make a call to a function that draws a path to a passed in context 
CGAffineTransform inverseTranslation = CGAffineTransformMakeTranslation(transX, transY); 
CGAffineTransform translation = CGAffineTransformMakeTranslation(-transX, -transY); 
CGAffineTransform rot = CGAffineTransformMakeRotation(3.14); 
CGAffineTransform final = CGAffineTransformConcat(CGAffineTransformConcat(inverseTranslation, rot), translation); 
// Then i apply the transformation animation like normal using self.transform = final etc etc 

También he intentado cosas por el estilo CGContextTranslateCTM y CGContextSaveGState/UIGraphicsPushContext, pero estos parecen tener poco efecto.

He estado luchando con esto durante días y mi solución actual parece cercana, pero no tengo ni idea de cómo deshacerme de esa interpolación de traducción. ¿Alguien tiene una solución para esto o una mejor manera de hacerlo?

[update] Por el momento estoy dibujando mi imagen centrada en el centro de UIview y luego establezco la propiedad UIView.center en el origen que me gustaría rotar y luego hago el comando de girar. Parece un truco, pero hasta que consiga las traducciones reales, es mi única opción. Gracias!

Respuesta

14

La respuesta de duncanwilcox es la correcta, pero omitió la parte donde se cambia el ancla de la capa de la vista al punto que se desea rotar.

CGSize sz = theview.bounds.size; 
// Anchorpoint coords are between 0.0 and 1.0 
theview.layer.anchorPoint = CGPointMake(rotPoint.x/sz.width, rotPoint.y/sz.height); 
[UIView beginAnimations:@"rotate" context:nil]; 
theview.transform = CGAffineTransformMakeRotation(45./180. * M_PI); 
[UIView commitAnimations]; 

Esto está documentado aquí: http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Layers.html

+2

comentario rápido editado para mostrar que debe usar constantes math.h cuando se trabaja con valores pi. M_PI_4, M_PI_2, M_PI son mejores y más precisos que todos los errores de redondeo :) –

2

La rotación ocurre alrededor del punto de ancla de la capa de la vista. El valor predeterminado para el punto de anclaje es el centro (0.5, 0.5), por lo que la rotación sola sin las traducciones debería ser suficiente.

realizó un test rápido y esto funciona para mí:

[UIView beginAnimations:@"rotate" context:nil]; 
self.transform = CGAffineTransformMakeRotation(45./180. * 3.14); 
[UIView commitAnimations]; 
+0

Tal vez mi descripción fue un poco engañosa. Estoy dibujando algo en un contexto (lo llamé una imagen, pero es algo que dibujé usando comandos de contexto) y no está en el mejor de los contextos. Quiero rotar como si el centro del contexto estuviera en el centro de mi "imagen". – Skyler

+0

comentario rápido editado para mostrar que debe usar constantes math.h cuando se trabaja con valores pi. M_PI_4, M_PI_2, M_PI son mejores y más precisos que todos los errores de redondeo :) –

1

Si no desea que se produzca una animación, pero acaba de establecer la nueva rotación, puede utilizar esto:

CGFloat newRotation = 3.14f 

[UIView beginAnimations:nil context:NULL]; 
[UIView setAnimationDuration:0.0]; // no tweening 
CGAffineTransform transform = CGAffineTransformMakeRotation(newRotation); 
self.transform = transform; 
[UIView commitAnimations]; 

La rotación debería tener lugar en el centro de la UIView. Configurando animationDuration en cero garantiza que no debe haber tweening.

Asegúrate de no hacer esto 60 veces por segundo. Es muy tentador crear juegos como animaciones con estas herramientas. Este tipo de animaciones no están pensadas exactamente para un juego basado en fotograma a fotograma, "muchos sprites volando por todas partes".

Para eso, y he seguido por ese camino, el único camino a seguir es OpenGL.

+0

Bueno, quiero animación para la rotación, quizás puedo usar su duración de 0 segundos para la traducción previa y posterior ya que CGContextTranslateCTM no parece funcionar. .. – Skyler

+0

Asegúrese de guardar el estado CGContext antes de hacer CGContextTranslateCTM. Luego restaura el estado. No tiene (aparente) efecto si solo traduces el CTM después de dibujar en tu contexto. – Kriem

7

Esta es también una opción: un simple cambio de base ;-)

CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y); 
transform = CGAffineTransformRotate(transform, angle); 
transform = CGAffineTransformTranslate(transform,-x,-y); 

donde (x,y) es el centro de rotación te gusta

Cuestiones relacionadas