NSAffineTransform ist eine Klasse aus AppKit (macOS), die eine affine Transformation in der zweidimensionalen Grafik darstellt. Sie kapselt eine 3×3-Matrix, die eine Kombination aus Verschiebung, Skalierung, Drehung und Scherung von Koordinaten beschreibt. Laut Apple-Dokumentation (2026) wird NSAffineTransform in Core Graphics häufig zum Transformieren von Pfaden, Punkten und Grafikkontexten auf macOS verwendet.
Wichtige Punkte
NSAffineTransform ist eine Klasse aus dem AppKit-Framework, die nur auf macOS verfügbar ist. Sie stellt eine affine Transformation im zweidimensionalen Raum durch eine 3×3-Matrix dar. Im Gegensatz zu CGAffineTransform aus Core Graphics (das auf iOS verfügbar ist), ist NSAffineTransform ein objektorientierter Wrapper um die CGAffineTransform-Struktur, der bequeme Methoden für die Arbeit mit NSBezierPath, NSPoint und NSSize hinzufügt.
Eine affine Transformation ist eine Transformation der Ebene, die die Beziehung „Der Punkt liegt auf einer Linie“ und die Parallelität von Linien bewahrt. Mit anderen Worten: Nach einer affinen Transformation bleiben parallele Linien parallel und gerade Linien gerade. Allerdings können sich Abstände, Winkel und Flächen ändern: Skalierung, Drehung und Scherung sind Spezialfälle von affinen Transformationen.
Auf iOS ist das Äquivalent zu NSAffineTransform die CGAffineTransform-Struktur aus Core Graphics. Beide APIs basieren auf demselben mathematischen Modell — einer 3×3-Matrix für affine Transformationen, bei der die letzte Zeile immer [0, 0, 1] ist. Der Unterschied besteht darin, dass NSAffineTransform eine Klasse (mit retain/release in Objective-C) ist, während CGAffineTransform eine Struktur (Wertetyp) in Swift und C ist.
NSAffineTransform unterstützt vier grundlegende Arten von Transformationen: translate (Verschiebung), scale (Skalierung), rotate (Drehung) und shear (Scherung). Jede Art wird durch eine separate Methode dargestellt und kann auf ein vorhandenes Transformationsobjekt angewendet oder zum Erstellen eines neuen verwendet werden.
| Operation | NSAffineTransform-Methode | Parameter | Visueller Effekt |
|---|---|---|---|
| Translate | translateXBy:yBy: | deltaX, deltaY | Verschiebt das Objekt entlang der X- und Y-Achse |
| Scale | scaleBy: / scaleXBy:yBy: | factor / scaleX, scaleY | Vergrößert oder verkleinert die Größe |
| Rotate | rotateByDegrees: / rotateByRadians: | Winkel in Grad oder Bogenmaß | Dreht um den Ursprung |
| Shear | Über setTransformStruct | Matrixkomponenten m12, m21 | Neigt das Objekt entlang einer Achse |
Translate fügt den Koordinaten aller Punkte eines Objekts einen Offset hinzu. Die Parameter deltaX und deltaY legen den Betrag der horizontalen bzw. vertikalen Verschiebung fest. Ein positiver deltaX-Wert verschiebt nach rechts, deltaY nach oben. Translate ändert weder Form noch Größe des Objekts — nur seine Position.
Scale multipliziert die Koordinaten von Punkten mit einem gegebenen Faktor. Bei gleichmäßiger Skalierung (ein Parameter) vergrößert oder verkleinert sich das Objekt proportional. Bei ungleichmäßiger Skalierung wird die Form verzerrt. Ein Faktor von 1,0 belässt die Größe unverändert, größer als 1,0 vergrößert, von 0,0 bis 1,0 verkleinert. Negative Werte erzeugen eine Spiegelung.
Rotate dreht das Objekt um den Ursprung um einen gegebenen Winkel. Ein positiver Drehwinkel entspricht einer Drehung gegen den Uhrzeigersinn. rotateByDegrees akzeptiert Grad (0–360), rotateByRadians akzeptiert Bogenmaß (0–2π). Die Drehung erfolgt immer relativ zum Punkt (0, 0). Um um einen beliebigen Punkt zu drehen, muss rotate mit translate kombiniert werden.
Die affine Transformation in NSAffineTransform wird durch eine 3×3-Matrix dargestellt, bei der die letzte Zeile immer [0, 0, 1] ist. Dies ist die standardmäßige mathematische Darstellung, die es ermöglicht, eine Kombination von Transformationen als Produkt von Matrizen darzustellen. Die Matrixstruktur wird durch NSAffineTransformStruct definiert, die sechs signifikante Komponenten enthält: m11, m12, m21, m22, tX, tY.
Die Komponenten m11, m12, m21, m22 sind für Skalierung, Drehung und Scherung verantwortlich. Die Komponenten tX und tY sind für die Verschiebung verantwortlich. In der Standardkonfiguration (Einheitsmatrix) ist m11 = 1, m22 = 1, der Rest ist 0. Um die aktuellen Matrixwerte zu erhalten, wird transformStruct verwendet — die Eigenschaft von NSAffineTransform, die eine NSAffineTransformStruct-Struktur zurückgibt.
Die Matrixmultiplikation ist eine nicht-kommutative Operation. Das bedeutet, dass die Reihenfolge der Anwendung von Transformationen wichtig ist: translate + rotate ergibt ein anderes Ergebnis als rotate + translate. Beim Kombinieren multipliziert NSAffineTransform die neue Matrix von links mit der aktuellen Matrix: newMatrix = operation × currentMatrix. Daher wird die zuletzt hinzugefügte Transformation zuerst angewendet.
NSAffineTransform ermöglicht das Kombinieren mehrerer Transformationen in einem einzelnen Objekt. Jeder Aufruf von translateXBy:yBy:, scaleBy: oder rotateByDegrees: modifiziert die interne Matrix — multipliziert die aktuelle Matrix mit der Matrix der entsprechenden Transformation. Dies ermöglicht die Erstellung einer komplexen Transformation aus einer Folge einfacher Operationen.
Zum Invertieren einer kombinierten Transformation wird die Methode invert verwendet. Die Inverse erzeugt eine neue affine Transformation, die die ursprüngliche aufhebt: Wenn man die ursprüngliche Transformation auf einen Punkt anwendet und dann die invertierte, kehrt der Punkt in seine ursprüngliche Position zurück. Die Invertierung ist nützlich, um eine Kontexttransformation vor dem Zeichnen von UI-Elementen aufzuheben, die nicht transformiert werden sollen.
Um zu prüfen, ob eine Transformation identisch ist (Koordinaten nicht ändert), verwendet man die Eigenschaft isIdentity. Die Identitätstransformation ist eine Einheitsmatrix — die Multiplikation mit ihr lässt die Koordinaten des Punktes unverändert. Ein neues NSAffineTransform-Objekt wird als Identitätstransformation erstellt. Diese Eigenschaft ist nützlich für die Optimierung: Wenn die Transformation identisch ist, kann ihre Anwendung übersprungen werden.
NSAffineTransform kann auf vier Arten von Objekten angewendet werden: NSPoint, NSSize, NSBezierPath und den Grafikkontext NSGraphicsContext. Für jedes Ziel gibt es eine separate Methode: transformPoint:, transformSize:, transformBezierPath: und set.
Die Methode transformPoint: multipliziert die Transformationsmatrix mit dem Koordinatenvektor des Punktes (x, y, 1) und gibt die neue Position des Punktes zurück. transformSize: funktioniert ähnlich, berücksichtigt aber nicht die Komponenten tX und tY — die Verschiebung wird nicht angewendet, nur Skalierung, Drehung und Scherung. Dies ist nützlich für die Transformation von Vektoren und Größen, die nicht verschoben werden sollen.
Die Methode transformBezierPath: erstellt ein neues NSBezierPath-Objekt, dessen jeder Punkt gemäß der NSAffineTransform-Matrix transformiert wird. Der ursprüngliche Pfad wird nicht verändert — es wird eine Kopie mit transformierten Koordinaten erstellt. Dies ist eine teure Operation für komplexe Pfade mit vielen Knoten.
Die Methode set wendet die Transformation auf den aktuellen Grafikkontext (NSGraphicsContext) an und modifiziert dessen CTM (Current Transformation Matrix). Nach dem Aufruf von set wird alles nachfolgende Zeichnen in diesem Kontext transformiert. Für temporäre Transformationen verwenden Sie saveGraphicsState / restoreGraphicsState vor und nach set.
Betrachten wir praktische Beispiele der Verwendung von NSAffineTransform in einer macOS-Anwendung zur Transformation von Grafikobjekten.
Dieses Beispiel erstellt einen NSAffineTransform, der Verschiebung, Drehung und Skalierung kombiniert. Zuerst wird das Objekt um (100, 50) verschoben, dann um 45 Grad gedreht und schließlich um den Faktor 1,5 skaliert. Die Reihenfolge ist wichtig: Drehen nach dem Verschieben dreht relativ zum neuen Ursprung.
import AppKit
let transform = NSAffineTransform()
transform.translateXBy(100, yBy: 50)
transform.rotateByDegrees(45)
transform.scaleBy(1.5)
// Auf Punkt anwenden
let point = NSPoint(x: 10, y: 20)
let transformedPoint = transform.transform(point)
// Auf Größe anwenden
let size = NSSize(width: 100, height: 50)
let transformedSize = transform.transform(size)
Dieses Beispiel zeigt die Anwendung von NSAffineTransform auf einen Grafikkontext über set und concat. Nach dem Anwenden der Transformation erfolgt alles nachfolgende Zeichnen im transformierten Koordinatensystem. Das Speichern des Grafikzustands über saveGraphicsState ermöglicht die Rückkehr zur ursprünglichen Matrix.
func drawWithTransform(in rect: NSRect) {
guard let ctx = NSGraphicsContext.current
else { return }
ctx.saveGraphicsState()
let xfm = NSAffineTransform()
xfm.translateXBy(rect.midX, yBy: rect.midY)
xfm.rotateByDegrees(30)
xfm.scaleBy(0.8)
xfm.concat()
// Zeichnen im transformierten Koordinatensystem
let path = NSBezierPath(roundedRect: NSRect(
x: -50, y: -50,
width: 100, height: 100
), xRadius: 10, yRadius: 10)
NSColor.blue.setFill()
path.fill()
ctx.restoreGraphicsState()
}
Dieses Beispiel zeigt das Erstellen einer Kopie eines NSBezierPath mit transformierten Koordinaten. Der ursprüngliche Pfad bleibt unverändert, und die transformierte Kopie kann separat gezeichnet werden — dies ist nützlich für das Erstellen von wiederholten Elementen an verschiedenen Positionen.
func createTransformedTriangle() -> NSBezierPath {
let triangle = NSBezierPath()
triangle.move(to: NSPoint(x: 0, y: 0))
triangle.line(to: NSPoint(x: 100, y: 0))
triangle.line(to: NSPoint(x: 50, y: 100))
triangle.close()
let xfm = NSAffineTransform()
xfm.translateXBy(200, yBy: 100)
xfm.scaleXBy(1.5, yBy: 1.5)
xfm.rotateByDegrees(45)
let transformed = xfm.transform(triangle)
return transformed
}
Häufig gestellte Fragen
NSAffineTransform ist eine Klasse aus AppKit (nur macOS), während CGAffineTransform eine Struktur aus Core Graphics (iOS und macOS) ist. NSAffineTransform ist ein objektorientierter Wrapper und bietet Methoden für die Arbeit mit NSBezierPath. CGAffineTransform ist eine leichte Werttyp-Struktur, die mit CGPath verwendet wird.
Um um den Mittelpunkt zu drehen, führen Sie drei Schritte aus: 1) Verschieben zum Mittelpunkt des Objekts (Ursprung in die Mitte verschieben), 2) um den gewünschten Winkel drehen, 3) um den negativen Mittelpunktvektor zurückverschieben. Die Kombination Verschiebung—Drehung—Verschiebung ergibt eine Drehung um einen beliebigen Punkt, anstatt um den Ursprung.
Nein, NSAffineTransform ist nur auf macOS als Teil von AppKit verfügbar. Auf iOS wird die CGAffineTransform-Struktur aus Core Graphics verwendet, die ähnliche Funktionen bietet: CGAffineTransformMakeTranslation, CGAffineTransformMakeScale, CGAffineTransformMakeRotation und CGAffineTransformConcat.
Verwenden Sie die invert-Methode, die die inverse Transformation zurückgibt. Wenn Sie die ursprüngliche Transformation mit der inversen multiplizieren, erhalten Sie eine Einheitsmatrix (Identitätstransformation). Für eine temporäre Anwendung rufen Sie saveGraphicsState vor set und restoreGraphicsState danach auf.
Verwenden Sie negative Skalierung: transform.scaleXBy(-1, yBy: 1) erzeugt eine horizontale Spiegelung, während scaleXBy(1, yBy: -1) eine vertikale Spiegelung erzeugt. Für eine Spiegelung relativ zu einer beliebigen Achse kombinieren Sie translate (Verschiebung zur Achse), scale mit -1 und inverse translate.
Zusammenfassung
invert hebt jede affine Transformation aufWir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch