2009-03-22 11 views
8

Entschuldigung, wenn das offensichtlich ist oder anderswo behandelt wird, aber ich google den ganzen Tag und habe keine Lösung gefunden, die tatsächlich funktioniert hat.Kann ich den Ursprung verschieben, wenn ich eine Transformation in Quartz 2D für das iPhone mache?

Mein Problem ist wie folgt: Ich zeichne derzeit ein Bild in einem Vollbild UIView, zum Beispiel werden wir sagen, das Bild befindet sich in der unteren rechten Ecke des UIView. Ich würde gerne eine Rotationstransformation (CGAffineTransformMakeRotation) in der Mitte des Bildes machen, jedoch rotiert der Rotationsbefehl standardmäßig um die Mitte der UIView selbst. Als Ergebnis bewegt sich mein Bild auf dem Bildschirm, wenn ich mich drehe, anstatt dass es an seinem Platz bleibt und sich um sein eigenes Zentrum dreht.

Von dem, was ich gesammelt habe, muss ich meinen Kontext übersetzen, so dass der Ursprung (Mittelpunkt der UIView) in der Mitte meines Bildes ist, Drehen, und dann den Kontext wiederherstellen, indem Sie zurück zum ursprünglichen Punkt.

Das Folgende ist das nächste, was ich habe zu arbeiten, aber das Problem ist, dass während das Bild rotiert, es bewegt sich nach unten, während es dreht. Ich denke, das durch Animation verursacht wird Tweenen der 1. Schritt übersetzen und dritter Schritt übersetzen, anstatt nur zu realisieren, dass der Anfang und Endpunkt auf den übersetzt das gleiche sein würde ...

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

Ich habe auch versucht, Sachen wie CGContextTranslateCTM und CGContextSaveGState/UIGraphicsPushContext, aber diese scheinen wenig Wirkung zu haben.

Ich habe seit Tagen damit zu kämpfen und meine aktuelle Lösung scheint in der Nähe, aber ich habe keine Ahnung, wie man das Übersetzen Tweening loswerden. Hat jemand eine Lösung dafür oder einen besseren Weg?

[update] Momentan zeichne ich mein Bild in der Mitte der UIview zentriert und setze dann die UIView.center-Eigenschaft auf den Ursprung, den ich drehen möchte, und dann den Drehbefehl. Scheint wie ein bisschen wie ein Hack, aber bis ich die echten Übersetzungen bekomme funktioniert es ist meine einzige Wahl. Danke!

Antwort

14

duncanwilcox 'Antwort ist die richtige, aber er hat den Teil weggelassen, wo Sie den Anker der Ansichtsschicht an den Punkt ändern, an dem Sie sich drehen wollen.

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

Dies ist hier dokumentiert: http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Layers.html

+2

kurzer Kommentar - bearbeitet, um zu zeigen, dass Sie math.h-Konstanten verwenden sollten, wenn Sie mit pi-Werten arbeiten. M_PI_4, M_PI_2, M_PI sind besser und genauer als alle Rundungsfehler :) –

2

Die Drehung erfolgt um den Ankerpunkt der Ebene der Ansicht. Der Standardwert für den Ankerpunkt ist der Mittelpunkt (0,5, 0,5), daher sollte die Drehung allein ohne die Übersetzungen ausreichen.

habe einen schnellen Test und das funktioniert für mich:

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

mag, ist vielleicht Meine Beschreibung war ein bisschen irreführend. Ich zeichne etwas auf einen Kontext (ich habe es ein Bild genannt, aber es ist nur etwas, das ich mit Kontextbefehlen zeichne) und es ist nicht im Kontext des Kontextes. Ich möchte rotieren, als ob der Mittelpunkt des Kontexts im Zentrum meines "Bildes" stünde. – Skyler

+0

kurzer Kommentar - bearbeitet, um zu zeigen, dass Sie math.h-Konstanten verwenden sollten, wenn Sie mit pi-Werten arbeiten. M_PI_4, M_PI_2, M_PI sind besser und genauer als alle Rundungsfehler :) –

1

Wenn Sie eine Animation, auftreten, sondern nur die neue Rotation versetzt nicht wollen haben, können Sie diese verwenden:

CGFloat newRotation = 3.14f 

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

Die Rotation sollte in der Tat um die Mitte der UIView stattfinden. Wenn Sie die animationDuration auf 0 setzen, garantiert, dass kein Tweening stattfinden soll.

Seien Sie sicher, obwohl Sie dies nicht 60 Mal pro Sekunde tun. Es ist sehr verlockend, Spiele wie Animationen mit diesen Tools zu erstellen. Diese Art von Animationen sind nicht gerade für ein Frame-to-Frame-basiertes "Spiel mit vielen Sprites" gedacht.

Dafür - und ich habe diesen Weg - der einzige Weg zu gehen, ist OpenGL.

+0

Nun, ich möchte Animation für die Rotation, vielleicht kann ich Ihre 0 sec Dauer für die Pre-und Post-Übersetzungen, da CGContextTranslateCTM schien nicht zu funktionieren. .. – Skyler

+0

Stellen Sie sicher, dass Sie den CGContext-Status speichern, bevor Sie CGContextTranslateCTM ausführen. Stellen Sie dann den Status wieder her. Es hat keine (scheinbare) Wirkung, wenn Sie einfach die CTM nach dem Zeichnen in Ihrem Kontext übersetzen. – Kriem

7

Dies ist auch eine Option: eine einfache Änderung der Basis ;-)

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

wo (x,y) das Rotationszentrum Sie