NSAffineTransform — je třída z AppKit (macOS), která představuje afinní transformaci ve dvourozměrné grafice. Zapouzdřuje matici 3×3, která popisuje kombinaci posunutí, měřítka, otočení a zkosení souřadnic. Podle Apple Documentation (2026) je NSAffineTransform široce používán v Core Graphics pro transformaci cest, bodů a grafických kontextů na macOS.
Hlavní body
NSAffineTransform — je třída z frameworku AppKit, dostupná pouze na macOS. Představuje afinní transformaci ve dvourozměrném prostoru pomocí matice 3×3. Na rozdíl od CGAffineTransform z Core Graphics (který je dostupný na iOS), je NSAffineTransform objektově orientovaným obalem struktury CGAffineTransform, který přidává pohodlné metody pro práci s NSBezierPath, NSPoint a NSSize.
Afinní transformace — je transformace roviny, která zachovává vztah „bod leží na přímce“ a rovnoběžnost přímek. Jinými slovy, po afinní transformaci zůstávají rovnoběžné čáry rovnoběžné a přímky přímkami. Avšak vzdálenosti, úhly a plochy se mohou měnit: měřítko, otočení a zkosení jsou speciálními případy afinních transformací.
Na iOS je obdobou NSAffineTransform struktura CGAffineTransform z Core Graphics. Obě API jsou založena na stejném matematickém modelu — matici afinní transformace 3×3, kde poslední řádek je vždy [0, 0, 1]. Rozdíl je v tom, že NSAffineTransform je třída (s retain/release v Objective-C), zatímco CGAffineTransform je struktura (hodnotový typ) ve Swift a C.
NSAffineTransform podporuje čtyři základní typy transformací: translate (posunutí), scale (měřítko), rotate (otočení) a shear (zkosení). Každý typ je reprezentován samostatnou metodou a může být aplikován jak na existující transformační objekt, tak použit k vytvoření nového.
| Operace | Metoda NSAffineTransform | Parametry | Vizuální efekt |
|---|---|---|---|
| Translate | translateXBy:yBy: | deltaX, deltaY | Posunutí objektu podél os X a Y |
| Scale | scaleBy: / scaleXBy:yBy: | factor / scaleX, scaleY | Zvětšení nebo zmenšení rozměrů |
| Rotate | rotateByDegrees: / rotateByRadians: | úhel ve stupních nebo radiánech | Otočení kolem počátku souřadnic |
| Shear | Přes setTransformStruct | složky m12, m21 matice | Zkosení objektu podél osy |
Translate přidává posunutí k souřadnicím všech bodů objektu. Parametry deltaX a deltaY určují velikost posunutí horizontálně a vertikálně. Kladná hodnota deltaX posouvá doprava, deltaY — nahoru. Translate nemění tvar ani velikost objektu — pouze jeho polohu.
Scale násobí souřadnice bodů daným faktorem. Při rovnoměrném měřítku (jeden parametr) se objekt proporcionálně zvětšuje nebo zmenšuje. Při nerovnoměrném měřítku se tvar deformuje. Faktor 1.0 ponechává velikost nezměněnou, větší než 1.0 zvětšuje, od 0.0 do 1.0 zmenšuje. Záporné hodnoty vytvářejí zrcadlení.
Rotate otáčí objekt kolem počátku souřadnic o daný úhel. Kladný úhel otočení odpovídá otočení proti směru hodinových ručiček. rotateByDegrees přijímá stupně (0–360), rotateByRadians — radiány (0–2π). Otočení se vždy provádí vzhledem k bodu (0, 0), proto pro otočení kolem libovolného bodu je třeba kombinovat rotate s translate.
Afinní transformace v NSAffineTransform je reprezentována maticí 3×3, kde poslední řádek je vždy [0, 0, 1]. Toto je standardní matematická reprezentace, která umožňuje prezentovat kombinaci transformací jako součin matic. Struktura matice je definována prostřednictvím NSAffineTransformStruct, která obsahuje šest důležitých složek: m11, m12, m21, m22, tX, tY.
Složky m11, m12, m21, m22 jsou odpovědné za měřítko, otočení a zkosení. Složky tX a tY jsou odpovědné za posunutí. Ve standardní konfiguraci (jednotková matice) je m11 = 1, m22 = 1, ostatní jsou 0. Pro získání aktuálních hodnot matice se používá transformStruct — vlastnost NSAffineTransform vracející strukturu NSAffineTransformStruct.
Násobení matic je nekomutativní operace. To znamená, že pořadí aplikace transformací má význam: translate + rotate dává jiný výsledek než rotate + translate. Při kombinování NSAffineTransform násobí novou matici zleva aktuální maticí: newMatrix = operation × currentMatrix. Proto se naposledy přidaná transformace aplikuje jako první.
NSAffineTransform umožňuje kombinovat několik transformací v jednom objektu. Každé volání translateXBy:yBy:, scaleBy: nebo rotateByDegrees: modifikuje vnitřní matici — násobí aktuální matici maticí příslušné transformace. To umožňuje vytvořit složitou transformaci z posloupnosti jednoduchých operací.
Pro inverzi kombinované transformace se používá metoda invert. Inverze vytváří novou afinní transformaci, která ruší původní: pokud na bod aplikujeme původní transformaci a poté invertovanou, bod se vrátí do původní polohy. Inverze je užitečná pro zrušení transformace kontextu před kreslením UI prvků, které by neměly být transformovány.
Ověření, zda je transformace identitická (nemění souřadnice), lze provést pomocí vlastnosti isIdentity. Identická transformace je jednotková matice, při jejímž násobení se souřadnice bodu nemění. Nový objekt NSAffineTransform je vytvořen jako identická transformace. Tato vlastnost je užitečná pro optimalizaci: pokud je transformace identická, její aplikaci lze přeskočit.
NSAffineTransform lze aplikovat na čtyři typy objektů: NSPoint, NSSize, NSBezierPath a grafický kontext NSGraphicsContext. Pro každý účel existuje samostatná metoda: transformPoint:, transformSize:, transformBezierPath: a set.
Metoda transformPoint: násobí transformační matici vektorem souřadnic bodu (x, y, 1) a vrací novou polohu bodu. transformSize: funguje podobně, ale nebere v úvahu složky tX a tY — posunutí se neaplikuje, pouze měřítko, otočení a zkosení. To je užitečné pro transformaci vektorů a velikostí, které by neměly být posunuty.
Metoda transformBezierPath: vytváří nový objekt NSBezierPath, jehož každý bod je transformován podle matice NSAffineTransform. Původní cesta se nemění — vytváří se kopie s transformovanými souřadnicemi. Toto je nákladná operace pro složité cesty s velkým počtem uzlů.
Metoda set aplikuje transformaci na aktuální grafický kontext (NSGraphicsContext) a modifikuje jeho CTM (Current Transformation Matrix). Po zavolání set bude veškeré následné kreslení v tomto kontextu transformováno. Pro dočasnou transformaci použijte saveGraphicsState / restoreGraphicsState před a po set.
Podívejme se na praktické příklady použití NSAffineTransform v aplikaci pro macOS pro transformaci grafických objektů.
Příklad vytváří NSAffineTransform kombinující posunutí, otočení a měřítko. Nejprve je objekt posunut o (100, 50), poté otočen o 45 stupňů a nakonec zvětšen 1.5krát. Pořadí je důležité: rotate po translate dává otočení vzhledem k novému počátku souřadnic.
import AppKit
let transform = NSAffineTransform()
transform.translateXBy(100, yBy: 50)
transform.rotateByDegrees(45)
transform.scaleBy(1.5)
// Aplikace na bod
let point = NSPoint(x: 10, y: 20)
let transformedPoint = transform.transform(point)
// Aplikace na velikost
let size = NSSize(width: 100, height: 50)
let transformedSize = transform.transform(size)
Příklad ukazuje aplikaci NSAffineTransform na grafický kontext pomocí set a concat. Po aplikaci transformace probíhá veškeré následné kreslení v transformovaném souřadném systému. Uložení stavu grafiky pomocí saveGraphicsState umožňuje návrat k původní matici.
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()
// Kreslení v transformovaném souřadném systému
let path = NSBezierPath(roundedRect: NSRect(
x: -50, y: -50,
width: 100, height: 100
), xRadius: 10, yRadius: 10)
NSColor.blue.setFill()
path.fill()
ctx.restoreGraphicsState()
}
Příklad demonstruje vytvoření kopie NSBezierPath s transformovanými souřadnicemi. Původní cesta zůstává nezměněna a transformovaná kopie může být kreslena samostatně — to je užitečné pro vytváření opakujících se prvků na různých pozicích.
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
}
Často kladené otázky
NSAffineTransform — je třída z AppKit (pouze macOS), zatímco CGAffineTransform — je struktura z Core Graphics (iOS a macOS). NSAffineTransform je objektově orientovaný obal a poskytuje metody pro práci s NSBezierPath. CGAffineTransform je lehká struktura hodnotového typu používaná s CGPath.
Pro otočení kolem středu proveďte tři kroky: 1) translate do středu objektu (posunutí počátku souřadnic do středu), 2) rotate o požadovaný úhel, 3) translate zpět o záporný vektor středu. Kombinace translate—rotate—translate poskytuje otočení kolem libovolného bodu, ne kolem počátku souřadnic.
Ne, NSAffineTransform je dostupný pouze na macOS v rámci AppKit. Na iOS se používá struktura CGAffineTransform z Core Graphics, která poskytuje podobné možnosti: CGAffineTransformMakeTranslation, CGAffineTransformMakeScale, CGAffineTransformMakeRotation a CGAffineTransformConcat.
Použijte metodu invert, která vrací inverzní transformaci. Pokud vynásobíme původní transformaci inverzní, získáme jednotkovou matici (identickou transformaci). Pro dočasnou aplikaci zavolejte saveGraphicsState před set a restoreGraphicsState po.
Použijte záporné měřítko: transform.scaleXBy(-1, yBy: 1) vytváří horizontální zrcadlení a scaleXBy(1, yBy: -1) — vertikální zrcadlení. Pro zrcadlení vzhledem k libovolné ose kombinujte translate (posunutí na osu), scale s -1 a inverzní translate.
Shrnutí
invert ruší účinek jakékoli afinní transformaceVyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také