UIBezierPath — třída z UIKit, která zapouzdřuje vektorovou cestu pro 2D grafiku v iOS. Spojuje geometrický popis kontury s možnostmi kreslení a umožňuje vytvářet čáry, Bézierovy křivky, oblouky a obdélníky. Na rozdíl od CGPath obsahuje UIBezierPath vlastní metody kreslení přímo v aktuálním grafickém kontextu. Podle Apple Developer Documentation, 2026 podporuje UIBezierPath všechny standardní operace Quartz 2D v objektově orientovaném obalu.
Hlavní body
UIBezierPath — třída frameworku UIKit, dědící NSObject a implementující NSCopying, NSSecureCoding. Poskytuje vysokoúrovňové Objective-C/Swift API pro stavbu a kreslení vektorových kontur. Interně UIBezierPath ukládá referenci na CGPathRef — objekt Core Graphics, ale přidává pohodlné metody pro kreslení, změnu geometrie a správu stylů.
Hlavní výhoda UIBezierPath oproti přímému použití CGPath jsou vestavěné metody kreslení. Volání fill() nebo stroke() na instanci UIBezierPath automaticky nakonfiguruje kontext a nakreslí cestu. Třída také podporuje vlastnosti lineWidth, lineCapStyle, lineJoinStyle, miterLimit a flatness, což umožňuje spravovat vzhled bez samostatného objektu pro ukládání stylů.
UIBezierPath se používá ve většině iOS aplikací pro vlastní kreslení uvnitř UIView: od jednoduchých ikon po složité animované grafy. Metoda draw(_:) třídy UIView je hlavním místem, kde vývojáři vytvářejí a kreslí UIBezierPath. Třída je plně kompatibilní s Core Animation a lze ji použít pro animaci cesty přes CAShapeLayer a CABasicAnimation.
Metoda move(to:) přesune počáteční bod cesty na zadané souřadnice bez kreslení. Toto je povinné volání před stavbou libovolného segmentu. addLine(to:) přidá přímý úsek z aktuální pozice do zadaného bodu. Pro uzavření kontury se používá metoda close(), která vede čáru od posledního bodu k prvnímu bodu posledního move(to:).
UIBezierPath poskytuje několik pohodlných inicializátorů pro hotové tvary. init(rect:) vytvoří obdélník, init(roundedRect:cornerRadius:) — obdélník se zaoblenými rohy. Parametr UIRectCorner umožňuje zaoblovat pouze vybrané rohy, například topLeft a bottomRight, ostatní nechává rovné. To je široce používáno pro vytváření vlastních tlačítek a karet.
init(ovalIn:) vytvoří elipsu vepsanou do zadaného obdélníku. Pokud je obdélník čtverec, elipsa se změní na kruh. init(roundedRect:byRoundingCorners:cornerRadii:) — nejflexibilnější varianta, umožňující nastavit různé poloměry pro každý roh. Tento inicializátor se objevil v iOS 6 a zůstává standardem pro vytváření zaoblených kontejnerů.
let path = UIBezierPath()
path.move(to: CGPoint(x: 50, y: 50))
path.addLine(to: CGPoint(x: 200, y: 50))
path.addLine(to: CGPoint(x: 200, y: 150))
path.addLine(to: CGPoint(x: 125, y: 200))
path.addLine(to: CGPoint(x: 50, y: 150))
path.close()
addQuadCurve(to:controlPoint:) přidá kvadratickou Bézierovu křivku s jedním řídicím bodem. Tento typ křivky se používá pro jednoduché plynulé ohyby, když je třeba minimalizovat počet výpočtů. Kvadratická křivka je vždy parabola a zaručeně leží uvnitř trojúhelníku tvořeného počátečním, řídicím a koncovým bodem.
addCurve(to:controlPoint1:controlPoint2:) přidá kubickou Bézierovu křivku se dvěma řídicími body. Kubické křivky se používají ve všech moderních vektorových editorech a TrueType fontech. Dva řídicí body poskytují více stupňů volnosti pro přesné řízení tvaru křivky. Tato metoda je doporučena pro stavbu organických a složitých kontur.
Při stavbě křivek je důležité dodržovat princip spojitosti — hladkost křivky v bodě připojení segmentů. Pro spojitost C1 (tečna) musí řídicí bod následující křivky ležet na stejné přímce jako řídicí bod předchozí. Pro spojitost C2 (křivost) je vyžadováno složitější přizpůsobení, které je automaticky zajištěno v CAShapeLayer při animaci mezi dvěma UIBezierPath se stejným počtem řídicích bodů.
| Metoda | Typ | Řídicích bodů | Stupeň |
|---|---|---|---|
| addQuadCurve | Kvadratická Bézier | 1 | 2 |
| addCurve | Kubická Bézier | 2 | 3 |
| addArc | Oblouk | — | — |
addArc(withCenter:radius:startAngle:endAngle:clockwise:) přidá oblouk kruhu se zadanými parametry. Úhly se zadávají v radiánech vzhledem ke středu kruhu. Nulový úhel odpovídá směru doprava (3 hodiny na ciferníku). Parametr clockwise určuje směr: true — po směru hodinových ručiček, false — proti směru. Oblouky jsou nepostradatelné pro koláčové grafy, rychloměry a interaktivní prstence průběhu.
Pro plný kruh stačí startAngle = 0 a endAngle = .pi * 2. Pro vytvoření sektoru (jako část koláčového grafu) použijte addArc následovaný addLine(to:) do středu a close(). UIBezierPath nemá vestavěnou metodu addCircle — kruh se vytvoří přes init(ovalIn:) se čtvercovým obdélníkem nebo přes addArc s plným úhlem.
Metoda addArc(withCenter:radius:startAngle:endAngle:clockwise:) automaticky provede move(to:) do počátečního bodu oblouku, pokud se aktuální pozice s ním neshoduje. Pokud je aktuální pozice jiná, je mezi ní a začátkem oblouku vedena přímá čára. Toto chování se liší od práce s Core Graphics, kde je vyžadován explicitní move(to:) před každou novou konturou.
let center = CGPoint(x: 150, y: 150)
let slice = UIBezierPath()
slice.move(to: center)
slice.addArc(
withCenter: center,
radius: 100,
startAngle: 0,
endAngle: .pi * 0.75,
clockwise: true
)
slice.close()
fill() vyplní vnitřní oblast cesty aktuální barvou fillColor nebo barvou nastavenou v grafickém kontextu přes setFill(). Pro cesty s vlastními průsečíky je pravidlo vyplnění určeno vlastností usesEvenOddFillRule. Pokud je true, použije se pravidlo even-odd: bod je považován za uvnitř tvaru, pokud paprsek z něj protíná konturu lichý počet krát.
stroke() kreslí konturu cesty s aktuálním nastavením lineWidth, lineCapStyle a lineJoinStyle. lineCapStyle určuje tvar konců otevřených segmentů: .butt (rovný řez), .round (půlkruhový), .square (čtvercový s výstupkem). lineJoinStyle určuje tvar rohů spojů: .miter (ostrý), .round (zaoblený), .bevel (seříznutý).
Pro přerušované čáry se používá vlastnost setLineDash(_:count:phase:). Přijímá pole délek střídajících se čárek a mezer, počet prvků a počáteční fázi. Vizualizace přerušované čáry probíhá ve fázi rasterizace cesty — složité vzory nezvyšují geometrickou složitost kontury. CAShapeLayer podporuje animaci vlastnosti strokeEnd pro efekt “kreslení” čáry od začátku do konce.
override func draw(_ rect: CGRect) {
let path = UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 200, height: 200))
UIColor.blue.setFill()
UIColor.black.setStroke()
path.lineWidth = 4
path.fill()
path.stroke()
}
Vytvořme vlastní indikátor průběhu ve tvaru prstence pomocí UIBezierPath. Prstenec se staví ze dvou oblouků stejného poloměru, ale s různou barvou obrysu. První oblouk je plný šedý kruh (pozadí), druhý je segment zobrazující průběh. Pro animaci se používají CAShapeLayer a CABasicAnimation.
class RingView: UIView {
private let progressLayer = CAShapeLayer()
override func layoutSubviews() {
super.layoutSubviews()
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = bounds.width * 0.4
let lineWidth: CGFloat = 12
let backgroundRing = UIBezierPath()
backgroundRing.addArc(withCenter: center, radius: radius,
startAngle: -.pi / 2, endAngle: .pi * 1.5, clockwise: true)
progressLayer.path = backgroundRing.cgPath
progressLayer.strokeColor = UIColor.systemBlue.cgColor
progressLayer.lineWidth = lineWidth
progressLayer.lineCap = .round
progressLayer.fillColor = UIColor.clear.cgColor
progressLayer.strokeEnd = 0
layer.addSublayer(progressLayer)
}
func animateProgress(to value: CGFloat) {
CABasicAnimation(keyPath: "strokeEnd").apply {
$0.toValue = value
$0.duration = 1.5
$0.timingFunction = CAMediaTimingFunction(name: .easeOut)
progressLayer.add($0, forKey: nil)
}
progressLayer.strokeEnd = value
}
}
V tomto příkladu se UIBezierPath používá k vytvoření kruhové kontury, která je pak předána CAShapeLayer přes vlastnost cgPath. Animace strokeEnd od 0 do 1 vizualizuje vyplňování prstence. Tento přístup se používá v indikátorech načítání, fitness trackerech a widgetech průběhu. Metoda layoutSubviews zaručuje přestavbu cesty při změně rozměrů View.
lineCap = .round přidá zaoblené konce oblouku, což dává indikátoru úhlednější vzhled. Vlastnost strokeEnd je animovatelná vlastnost CAShapeLayer, která nevyžaduje překreslení celé kontury v každém snímku. Animace je provedena zcela na GPU přes Core Animation, což zajišťuje 60 FPS bez zatížení CPU.
Často kladené otázky
UIBezierPath — objektově orientovaný obal CGPath obsahující vestavěné metody fill() a stroke(). CGPath je nemodifikovatelný C objekt Core Graphics vyžadující explicitní kreslení přes CGContext. UIBezierPath je pohodlnější pro UIKit, CGPath je výkonnější pro opakované použití.
Použijte init(roundedRect:byRoundingCorners:cornerRadii:) s parametrem .topLeft a .topRight pro roundedRect. Toto je jediná metoda UIBezierPath umožňující selektivní zaoblení rohů bez vytváření složité složené cesty.
Vlastnost cgPath vrací neměnný CGPathRef, který lze předat CAShapeLayer nebo použít s různými barvami a tloušťkami. Modifikace UIBezierPath (přesun bodů) neovlivní dříve získaný cgPath do explicitní aktualizace.
Zkontrolujte usesEvenOddFillRule — pokud má kontura vlastní průsečíky, pravidlo even-odd může ponechat oblasti nevyplněné. Nastavte usesEvenOddFillRule = false pro standardní pravidlo vyplnění non-zero winding.
Použijte CABasicAnimation s klíčovou cestou “path” na CAShapeLayer. Oba stavy cesty musí obsahovat stejný počet segmentů a řídicích bodů — jinak bude animace trhaná nebo nebude fungovat.
Shrnutí
Vyvineme 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é