2012-05-08 17 views
5

estoy usando la siguiente función para aplicar un efecto de impulso a una vistaCATransform3D a CGAffineTransform

- (void)pulse { 

    CATransform3D trasform = CATransform3DScale(self.layer.transform, 1.15, 1.15, 1); 
    trasform = CATransform3DRotate(trasform, angle, 0, 0, 0); 

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 
    animation.toValue = [NSValue valueWithCATransform3D:trasform]; 
    animation.autoreverses = YES; 
    animation.duration = 0.3; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    animation.repeatCount = 2; 
    [self.layer addAnimation:animation forKey:@"pulseAnimation"]; 

} 

me gustaría obtener el mismo resultado utilizando el self.transform CGAffineTransform en lugar del auto CATransform3D. layer.transform. ¿Esto es posible?

+1

Por curiosidad, ¿por qué ¿le importa si estuviera aplicando un CATransform3D a una capa frente a un CGAffineTransform a una vista, si ya está obteniendo el resultado que desea de la primera? –

+0

porque el valor inicial de self.layer.transform es diferente de self.transform, ¿o no? – Abramodj

+0

Quiero decir, antes de llegar al método de pulso, aplico algunas transformaciones de Affine a la vista, pero no toco la capa, así que supongo que la transformación es la identidad allí – Abramodj

Respuesta

2

Por supuesto. Si realiza una búsqueda en CGAffineTransform en los documentos de Xcode, encontrará un capítulo titulado "Referencia de CGAffineTransform". En ese capítulo hay una sección llamada "Funciones". Incluye funciones que son equivalentes a CATransform3DScale (CGAffineTransformScale) y CATransform3DRotate (CGAffineTransformRotate).

Tenga en cuenta que su llamada a CATransform3DRotate realmente no tiene sentido. Debe girar alrededor de un eje, y está pasando 0 para los 3 ejes. Por lo general, usted quiere usar CATransform3DRotate (trasform, angle, 0, 0, 1.0) para rotar alrededor del eje Z. Para citar los documentos:

Si el vector tiene longitud cero, el comportamiento no está definido.

+0

Pero el punto (tal vez no está claro a partir de mi pregunta) es cómo tener un equivalente de [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]; – Abramodj

+1

Realmente no estás siendo claro. Supongo que CGAffineTransform se usa para vistas y CATransform3D se usa para capas que desea saber cómo hacer animaciones basadas en vistas que especifiquen una función de sincronización diferente. Para eso, desea usar animateWithDuration: delay: options: animations: completion: Método de clase UIView. El parámetro de opciones incluye valores como UIViewAnimationOptionCurveEaseInOut, UIViewAnimationOptionCurveLinear, etc. Solo especifique la opción que desee y luego cambie la transformación en el bloque de animaciones. –

7

Es posible convertir un CATransform3D en un CGAffineTransform, pero perderá algunas capacidades. Me resultó útil convertir la transformación agregada de una capa y sus antecesores en un CGAffineTransform para poder renderizarlo con Core Graphics. Las limitaciones son:

  • Su entrada será tratado como plana en el plano XY
  • Su salida será tratado como plana en el plano XY demasiado
  • será neutralizado
  • Perspectiva/escorzo desde .m34

Si eso suena bien para sus propósitos:

// m13, m23, m33, m43 are not important since the destination is a flat XY plane. 
    // m31, m32 are not important since they would multiply with z = 0. 
    // m34 is zeroed here, so that neutralizes foreshortening. We can't avoid that. 
    // m44 is implicitly 1 as CGAffineTransform's m33. 
    CATransform3D fullTransform = <your 3D transform> 
    CGAffineTransform affine = CGAffineTransformMake(fullTransform.m11, fullTransform.m12, fullTransform.m21, fullTransform.m22, fullTransform.m41, fullTransform.m42); 

Yo Primero querrás hacer todo tu trabajo en transformaciones tridimensionales, digamos concatenando desde tus supercapas, y finalmente convertir el agregado CATransform3D a CGAffineTransform. Dado que las capas son planas para comenzar y renderizar sobre un objetivo plano, esto me pareció muy adecuado ya que mis rotaciones 3D se convirtieron en tijeras 2D. También encontré aceptable sacrificar el escorzo. No hay forma de evitarlo porque las transformaciones afines deben preservar las líneas paralelas.

Para hacer una capa 3D-transformado mediante núcleo de gráficos, por ejemplo, es posible concatenar las transformadas (! Respetando puntos de anclaje), a continuación, convertir a afín, y finalmente:

CGContextSaveGState(context); 
    CGContextConcatCTM(context, affine); 
    [layer renderInContext:context]; 
    CGContextRestoreGState(context); 
+0

Gracias, esta es la respuesta correcta. Desafortunadamente, es una de esas funciones que * debería * incluirse en las API de Cocoa, pero no es porque no sea una conversión "completa" (y nunca podría serlo). – SG1

+0

Estoy tan feliz de haber encontrado esto. He estado buscando "3d to 2d matrix" durante una semana y acabo de encontrar un montón de galimatías matemáticos. – xtravar

+0

¿Cómo demonios te diste cuenta? ¡Esto es asombroso! Me inclino ante tu genio matemático. – jjxtra

Cuestiones relacionadas