2012-05-08 18 views
5

sto usando la seguente funzione per applicare un effetto di impulsi ad unDa CATransform3D 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"]; 

} 

desidero ottenere lo stesso risultato utilizzando la self.transform CGAffineTransform invece del sé CATransform3D. layer.transform. È possibile?

+1

Per curiosità, perché sarebbe ti interessa se stavi applicando un CATransform3D a un layer o un CGAffineTransform a una vista, se stai già ottenendo il risultato che desideri dal primo? –

+0

perché il valore iniziale di self.layer.transform è diverso da self.transform, non è vero? – Abramodj

+0

Voglio dire, prima di arrivare al metodo dell'impulso applico alcune trasformazioni Affine alla vista, ma non tocco il livello, quindi suppongo che la trasformazione sia l'identità lì – Abramodj

risposta

2

Naturalmente. Se esegui una ricerca su CGAffineTransform nei documenti Xcode, troverai un capitolo intitolato "Riferimento CGAffineTransform". In quel capitolo c'è una sezione chiamata "Funzioni". Include funzioni equivalenti a CATransform3DScale (CGAffineTransformScale) e CATransform3DRotate (CGAffineTransformRotate).

Si noti che la vostra chiamata a CATransform3DRotate non ha molto senso. Hai bisogno di ruotare attorno ad un asse e stai passando 0 per tutti e 3 gli assi. Tipicamente si desidera utilizzare CATransform3DRotate (trasform, angle, 0, 0, 1.0) per ruotare attorno all'asse Z. Per citare i documenti:

Se il vettore ha lunghezza zero, il comportamento non è definito.

+0

Ma il punto (forse non chiaro dalla mia domanda) è come avere un equivalente di [funzioneComeTestFunctionWithName: kCAMediaTimingFunctionEaseInEaseOut]; – Abramodj

+1

Non sei davvero chiaro. Suppongo che CGAffineTransform venga utilizzato per le visualizzazioni e CATransform3D sia utilizzato per i livelli che si desidera sapere come eseguire un'animazione basata sulla visualizzazione che specifica una diversa funzione di temporizzazione. Per questo si desidera utilizzare AnimateWithDuration: ritardo: opzioni: animazioni: completamento: Metodo della classe UIView. Il parametro options include valori come UIViewAnimationOptionCurveEaseInOut, UIViewAnimationOptionCurveLinear, ecc. Basta specificare l'opzione desiderata e quindi modificare la trasformazione nel blocco di animazioni. –

7

E 'possibile convertire un CATransform3D ad un CGAffineTransform, ma si perde alcune funzionalità. Ho trovato utile convertire la trasformazione aggregata di un layer e dei suoi antenati in un CGAffineTransform così da renderlo disponibile con Core Graphics. I vincoli sono:

  • vostro contributo verrà considerato piatta nel piano XY
  • L'output verrà considerato piatta nel piano XY troppo
  • Perspective/scorcio dal .m34 verrà neutralizzata

Se questo suona bene per i vostri scopi:

// 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 vorrai fare tutto il tuo lavoro nelle trasformazioni 3D prima, ad esempio concatenando dai tuoi superplayer e infine convertendo l'aggregato CATransform3D in un CGAffineTransform. Dato che i livelli sono piatti all'inizio e il rendering su un target piatto, ho trovato questo molto adatto poiché le mie rotazioni 3D sono diventate cesoie 2D. Ho anche trovato accettabile sacrificare lo scorcio. Non c'è modo di aggirare questo perché le trasformazioni affini devono preservare le linee parallele.

Per rendere un livello 3D-trasformata utilizzando core grafico, per esempio, si potrebbe concatenare le trasformazioni (! Rispettando punti di ancoraggio), poi convertire in affine, e infine:

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

Grazie, questa è la risposta corretta. Sfortunatamente, è una di quelle funzioni che * dovrebbe * essere inclusa nelle API Cocoa, ma non è perché non è una conversione "completa" (e mai potrebbe essere). – SG1

+0

Sono così felice di averlo trovato. Sono stato alla ricerca di "3d to 2d matrix" per una settimana e ho appena trovato un mucchio di parole senza senso matematiche. – xtravar

+0

Come diavolo hai capito? Questo e spettacolare! Mi inchino al tuo genio matematico. – jjxtra

Problemi correlati