NSAffineTransform — is een klasse uit AppKit (macOS) die een affiene transformatie in tweedimensionale grafische voorstelling vertegenwoordigt. Het kapselt een 3×3 matrix in die een combinatie van verplaatsing, schaling, rotatie en afschuiving van coördinaten beschrijft. Volgens Apple Documentation (2026) wordt NSAffineTransform veel gebruikt in Core Graphics voor het transformeren van paden, punten en grafische contexten op macOS.
Belangrijkste punten
NSAffineTransform — is een klasse uit het AppKit-framework, alleen beschikbaar op macOS. Het vertegenwoordigt een affiene transformatie in de tweedimensionale ruimte via een 3×3 matrix. In tegenstelling tot CGAffineTransform uit Core Graphics (die beschikbaar is op iOS), is NSAffineTransform een objectgeoriënteerde wrapper rond de CGAffineTransform-structuur, die handige methoden toevoegt voor het werken met NSBezierPath, NSPoint en NSSize.
Affiene transformatie — is een transformatie van het vlak die de relatie „punt ligt op een rechte lijn” en parallelliteit van lijnen behoudt. Met andere woorden, na een affiene transformatie blijven parallelle lijnen parallel en rechte lijnen recht. Echter, afstanden, hoeken en oppervlakten kunnen veranderen: schaling, rotatie en afschuiving zijn speciale gevallen van affiene transformaties.
Op iOS is de tegenhanger van NSAffineTransform de CGAffineTransform-structuur uit Core Graphics. Beide API’s zijn gebaseerd op hetzelfde wiskundige model — een 3×3 affiene transformatiematrix waarvan de laatste rij altijd [0, 0, 1] is. Het verschil is dat NSAffineTransform een klasse is (met retain/release in Objective-C), terwijl CGAffineTransform een structuur (waardetype) is in Swift en C.
NSAffineTransform ondersteunt vier basistypen transformaties: translate (verplaatsing), scale (schaling), rotate (rotatie) en shear (afschuiving). Elk type wordt vertegenwoordigd door een aparte methode en kan zowel worden toegepast op een bestaand transformatieobject als worden gebruikt om een nieuwe te maken.
| Operatie | NSAffineTransform-methode | Parameters | Visueel effect |
|---|---|---|---|
| Translate | translateXBy:yBy: | deltaX, deltaY | Verplaatsing van object langs X- en Y-as |
| Scale | scaleBy: / scaleXBy:yBy: | factor / scaleX, scaleY | Vergroten of verkleinen van afmetingen |
| Rotate | rotateByDegrees: / rotateByRadians: | hoek in graden of radialen | Rotatie rond de oorsprong van coördinaten |
| Shear | Via setTransformStruct | matrixcomponenten m12, m21 | Afschuiving van object langs de as |
Translate voegt een verplaatsing toe aan de coördinaten van alle punten van het object. De parameters deltaX en deltaY geven respectievelijk de grootte van de horizontale en verticale verplaatsing aan. Een positieve deltaX-waarde verplaatst naar rechts, deltaY — naar boven. Translate verandert de vorm of grootte van het object niet — alleen de positie.
Scale vermenigvuldigt de coördinaten van punten met een gegeven factor. Bij uniforme schaling (één parameter) wordt het object proportioneel vergroot of verkleind. Bij niet-uniforme schaling wordt de vorm vervormd. Factor 1.0 laat de grootte ongewijzigd, groter dan 1.0 vergroot, van 0.0 tot 1.0 verkleint. Negatieve waarden creëren spiegeling.
Rotate roteert het object rond de oorsprong van het coördinatenstelsel over een gegeven hoek. Een positieve rotatiehoek komt overeen met rotatie tegen de klok in. rotateByDegrees accepteert graden (0–360), rotateByRadians — radialen (0–2π). Rotatie wordt altijd uitgevoerd ten opzichte van punt (0, 0), dus voor rotatie rond een willekeurig punt moet rotate worden gecombineerd met translate.
Affiene transformatie in NSAffineTransform wordt weergegeven door een 3×3 matrix, waarvan de laatste rij altijd [0, 0, 1] is. Dit is een standaard wiskundige weergave die het mogelijk maakt een combinatie van transformaties als product van matrices weer te geven. De structuur van de matrix wordt gedefinieerd via NSAffineTransformStruct, die zes belangrijke componenten bevat: m11, m12, m21, m22, tX, tY.
De componenten m11, m12, m21, m22 zijn verantwoordelijk voor schaling, rotatie en afschuiving. De componenten tX en tY zijn verantwoordelijk voor verplaatsing. In de standaardconfiguratie (eenheidsmatrix) zijn m11 = 1, m22 = 1, de rest is 0. Om de huidige matrixwaarden op te halen, wordt transformStruct gebruikt — de eigenschap van NSAffineTransform die de structuur NSAffineTransformStruct retourneert.
Matrixvermenigvuldiging is een niet-commutatieve bewerking. Dit betekent dat de volgorde van toepassing van transformaties ertoe doet: translate + rotate geeft een ander resultaat dan rotate + translate. Bij het combineren vermenigvuldigt NSAffineTransform de nieuwe matrix links met de huidige matrix: newMatrix = operation × currentMatrix. Daarom wordt de laatst toegevoegde transformatie als eerste toegepast.
NSAffineTransform maakt het mogelijk meerdere transformaties in één object te combineren. Elke aanroep van translateXBy:yBy:, scaleBy: of rotateByDegrees: wijzigt de interne matrix — vermenigvuldigt de huidige matrix met de matrix van de corresponderende transformatie. Dit maakt het mogelijk een complexe transformatie te creëren uit een reeks eenvoudige operaties.
Voor het inverteren van een gecombineerde transformatie wordt de methode invert gebruikt. De inverse creëert een nieuwe affiene transformatie die de originele tenietdoet: als we op een punt eerst de originele transformatie toepassen en daarna de inverse, keert het punt terug naar de oorspronkelijke positie. De inverse is nuttig voor het ongedaan maken van contexttransformatie vóór het tekenen van UI-elementen die niet getransformeerd mogen worden.
Controleren of een transformatie identiteit is (coördinaten niet verandert) kan via de eigenschap isIdentity. De identiteitstransformatie is de eenheidsmatrix, bij vermenigvuldiging waarmee de coördinaten van een punt niet veranderen. Een nieuw NSAffineTransform-object wordt gemaakt als identiteitstransformatie. Deze eigenschap is nuttig voor optimalisatie: als de transformatie identiteit is, kan de toepassing ervan worden overgeslagen.
NSAffineTransform kan worden toegepast op vier soorten objecten: NSPoint, NSSize, NSBezierPath en de grafische context NSGraphicsContext. Voor elk doel bestaat een aparte methode: transformPoint:, transformSize:, transformBezierPath: en set.
Methode transformPoint: vermenigvuldigt de transformatiematrix met de coördinatenvector van het punt (x, y, 1) en retourneert de nieuwe positie van het punt. transformSize: werkt vergelijkbaar, maar houdt geen rekening met de tX- en tY-componenten — verplaatsing wordt niet toegepast, alleen schaling, rotatie en afschuiving. Dit is nuttig voor transformatie van vectoren en afmetingen die niet mogen worden verplaatst.
Methode transformBezierPath: creëert een nieuw NSBezierPath-object waarvan elk punt is getransformeerd volgens de NSAffineTransform-matrix. Het originele pad verandert niet — er wordt een kopie met getransformeerde coördinaten gemaakt. Dit is een dure operatie voor complexe paden met een groot aantal knooppunten.
Methode set past de transformatie toe op de huidige grafische context (NSGraphicsContext) en wijzigt de CTM (Current Transformation Matrix). Na het aanroepen van set wordt al het daaropvolgende tekenen in deze context getransformeerd. Gebruik voor tijdelijke transformatie saveGraphicsState / restoreGraphicsState vóór en na set.
Laten we praktische voorbeelden bekijken van het gebruik van NSAffineTransform in een macOS-applicatie voor transformatie van grafische objecten.
Het voorbeeld creëert een NSAffineTransform die verplaatsing, rotatie en schaling combineert. Eerst wordt het object verplaatst naar (100, 50), vervolgens geroteerd over 45 graden en ten slotte 1.5 keer vergroot. De volgorde is belangrijk: rotate na translate geeft rotatie ten opzichte van de nieuwe oorsprong van het coördinatenstelsel.
import AppKit
let transform = NSAffineTransform()
transform.translateXBy(100, yBy: 50)
transform.rotateByDegrees(45)
transform.scaleBy(1.5)
// Toepassen op punt
let point = NSPoint(x: 10, y: 20)
let transformedPoint = transform.transform(point)
// Toepassen op grootte
let size = NSSize(width: 100, height: 50)
let transformedSize = transform.transform(size)
Het voorbeeld toont het toepassen van NSAffineTransform op de grafische context via set en concat. Na toepassing van de transformatie wordt al het daaropvolgende tekenen uitgevoerd in het getransformeerde coördinatensysteem. Opslaan van de grafische status via saveGraphicsState maakt het mogelijk terug te keren naar de originele 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()
// Tekenen in getransformeerd coördinatensysteem
let path = NSBezierPath(roundedRect: NSRect(
x: -50, y: -50,
width: 100, height: 100
), xRadius: 10, yRadius: 10)
NSColor.blue.setFill()
path.fill()
ctx.restoreGraphicsState()
}
Het voorbeeld demonstreert het maken van een kopie van NSBezierPath met getransformeerde coördinaten. Het originele pad blijft ongewijzigd en de getransformeerde kopie kan afzonderlijk worden getekend — dit is nuttig voor het creëren van herhalende elementen op verschillende posities.
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
}
Veelgestelde vragen
NSAffineTransform — is een klasse uit AppKit (alleen macOS), en CGAffineTransform — is een structuur uit Core Graphics (iOS en macOS). NSAffineTransform is een objectgeoriënteerde wrapper en biedt methoden voor het werken met NSBezierPath. CGAffineTransform is een lichte waardetype-structuur die wordt gebruikt met CGPath.
Voer voor rotatie rond het middelpunt drie stappen uit: 1) translate naar het middelpunt van het object (verplaatsing van de oorsprong naar het midden), 2) rotate over de gewenste hoek, 3) translate terug met de negatieve vector van het middelpunt. De combinatie translate—rotate—translate geeft rotatie rond een willekeurig punt, niet rond de oorsprong van het coördinatenstelsel.
Nee, NSAffineTransform is alleen beschikbaar op macOS binnen AppKit. Op iOS wordt de CGAffineTransform-structuur uit Core Graphics gebruikt, die vergelijkbare mogelijkheden biedt: CGAffineTransformMakeTranslation, CGAffineTransformMakeScale, CGAffineTransformMakeRotation en CGAffineTransformConcat.
Gebruik de methode invert, die de inverse transformatie retourneert. Als we de originele transformatie met de inverse vermenigvuldigen, krijgen we de eenheidsmatrix (identiteitstransformatie). Gebruik voor tijdelijke toepassing saveGraphicsState vóór set en restoreGraphicsState erna.
Gebruik negatieve schaling: transform.scaleXBy(-1, yBy: 1) creëert horizontale spiegeling en scaleXBy(1, yBy: -1) verticale spiegeling. Voor spiegeling ten opzichte van een willekeurige as, combineer translate (verplaatsing naar de as), scale met -1 en inverse translate.
Samenvatting
invert maakt elke affiene transformatie ongedaanWe ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook