2012-05-08 10 views
5

Ich verwende die folgende Funktion eine Impulswirkung auf eine Ansicht anwendenVon CATransform3D zu 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"]; 

} 

Ich mag würde das gleiche Ergebnis mit dem CGAffineTransform self.transform anstelle des CATransform3D selbst erhalten. layer.transformieren. Ist das möglich?

+1

Aus Neugier, würde warum Es ist Ihnen wichtig, ob Sie ein CATransform3D-Objekt auf eine Ebene oder ein CGAffineTransform-Objekt auf eine Ansicht anwenden, wenn Sie das gewünschte Ergebnis bereits erhalten. –

+0

weil der Anfangswert von self.layer.transform von self.transform verschieden ist, nicht wahr? – Abramodj

+0

Ich meine, bevor ich zur Pulsmethode komme, wende ich einige affine Transformationen auf die Ansicht an, aber ich berühre die Ebene nicht, also denke ich, dass die Transformation die Identität ist – Abramodj

Antwort

2

Natürlich. Wenn Sie in den Xcode-Dokumenten nach CGAffineTransform suchen, finden Sie ein Kapitel mit dem Titel "CGAffineTransform Reference". In diesem Kapitel ist ein Abschnitt namens "Funktionen". Es enthält Funktionen, die CATransform3DScale (CGAffineTransformScale) und CATransform3DRotate (CGAffineTransformRotate) entsprechen.

Beachten Sie, dass Ihr Aufruf von CATransform3DRotate nicht wirklich sinnvoll ist. Sie müssen sich um eine Achse drehen und für alle 3 Achsen 0 übergeben. In der Regel möchten Sie CATransform3DRotate (trasform, winkel, 0, 0, 1.0) verwenden, um sich um die Z-Achse zu drehen. Um die Dokumente zu zitieren:

Wenn der Vektor Null Länge hat, ist das Verhalten nicht definiert.

+0

Aber der Punkt (vielleicht nicht klar aus meiner Frage) ist, wie ein Äquivalent von [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]; – Abramodj

+1

Sie sind wirklich nicht klar. Ich schätze aus der Tatsache, dass CGAffineTransform für Ansichten verwendet wird und CATransform3D für Schichten verwendet wird, die Sie wissen möchten, wie eine viewbasierte Animation ausgeführt wird, die eine andere Timing-Funktion angibt. Dazu möchten Sie die animateWithDuration verwenden: delay: options: animations: completion: UIView-Klassenmethode. Der Optionsparameter enthält Werte wie UIViewAnimationOptionCurveEaseInOut, UIViewAnimationOptionCurveLinear usw. Geben Sie einfach die gewünschte Option an, und ändern Sie dann die Transformation im Animationsblock. –

7

Es ist möglich, eine CATransform3D einen CGAffineTransform konvertieren, aber Sie werden einige Fähigkeiten verlieren. Ich fand es nützlich, die Aggregat-Transformation einer Ebene und ihrer Vorfahren in eine CGAffineTransform umzuwandeln, damit ich sie mit Core Graphics rendern konnte. Die Randbedingungen sind:

  • Ihre Eingaben werden als flache in der XY-Ebene
  • behandelnden
  • Ihr Ausgang wird als flach in der XY-Ebene zu
  • Perspective/Verkürzungen von .m34 wird
  • neutralisiert werden behandelnde

Wenn das klingt für Ihre Zwecke OK:

// 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 Sie werden alle Ihre Arbeit in 3D-Transformationen zuerst tun wollen, indem Sie von Ihren Superlayern verketten und dann das Aggregat CATransform3D in eine CGAffineTransform konvertieren. Da die Ebenen zunächst flach sind und auf ein flaches Ziel gerendert werden, fand ich das sehr passend, da meine 3D-Rotationen zu 2D-Scheren wurden. Ich fand es auch akzeptabel, die Verkürzung zu opfern. Es gibt keinen Weg, weil affine Transformationen parallele Linien erhalten müssen.

Um eine 3D-transformierten Schicht mit Core Graphics, zum Beispiel zu machen, können Sie die Transformationen verketten könnten (! Achtung Ankerpunkte), dann affinen konvertieren und schließlich:

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

Danke, das ist die richtige Antwort. Leider ist es eine dieser Funktionen, die * in den Cocoa-APIs * enthalten sein sollte, aber nicht, weil es keine "vollständige" Konvertierung ist (und niemals sein könnte). – SG1

+0

Ich bin so glücklich, dass ich das gefunden habe. Ich habe jetzt seit einer Woche nach "3d zu 2d Matrix" gesucht und gerade ein Bündel mathematischen Kauderwelsch gefunden. – xtravar

+0

Wie zur Hölle hast du das herausgefunden? Das ist fantastisch! Ich verneige mich vor deinem Mathe-Genie. – jjxtra

Verwandte Themen