UIBezierPath — een klasse uit UIKit die een vectorpad inkapselt voor 2D-graphics in iOS. Het combineert de geometrische beschrijving van een contour met tekenmogelijkheden, waardoor lijnen, Bézier-curven, bogen en rechthoeken kunnen worden gemaakt. In tegenstelling tot CGPath bevat UIBezierPath eigen tekenmethoden die direct in de huidige grafische context werken. Volgens Apple Developer Documentation, 2026 ondersteunt UIBezierPath alle standaard Quartz 2D-operaties in een objectgeoriënteerde verpakking.
Belangrijkste punten
UIBezierPath — een klasse van het UIKit-framework, die NSObject erft en NSCopying, NSSecureCoding implementeert. Het biedt een hoogwaardige Objective-C/Swift API voor het bouwen en tekenen van vectorcontouren. Intern slaat UIBezierPath een referentie naar CGPathRef op — een Core Graphics-object, maar voegt handige methoden toe voor tekenen, geometriewijziging en stijlbeheer.
Het belangrijkste voordeel van UIBezierPath ten opzichte van direct gebruik van CGPath zijn de ingebouwde tekenmethoden. Het aanroepen van fill() of stroke() op een UIBezierPath-instantie configureert automatisch de context en tekent het pad. De klasse ondersteunt ook de eigenschappen lineWidth, lineCapStyle, lineJoinStyle, miterLimit en flatness, waardoor het uiterlijk kan worden beheerd zonder een apart object voor stijlopslag.
UIBezierPath wordt in de meeste iOS-applicaties gebruikt voor aangepast tekenen binnen UIView: van eenvoudige pictogrammen tot complexe geanimeerde grafieken. De methode draw(_:) van de UIView-klasse is de belangrijkste plek waar ontwikkelaars UIBezierPath maken en tekenen. De klasse is volledig compatibel met Core Animation en kan worden gebruikt voor padanimatie via CAShapeLayer en CABasicAnimation.
De methode move(to:) verplaatst het beginpunt van het pad naar de opgegeven coördinaten zonder te tekenen. Dit is een verplichte aanroep voordat een segment wordt gebouwd. addLine(to:) voegt een recht lijnsegment toe van de huidige positie naar het opgegeven punt. Voor het sluiten van de contour wordt de methode close() gebruikt, die een lijn trekt van het laatste punt naar het eerste punt van de laatste move(to:).
UIBezierPath biedt verschillende handige initializers voor kant-en-klare vormen. init(rect:) maakt een rechthoek, init(roundedRect:cornerRadius:) — een rechthoek met afgeronde hoeken. De parameter UIRectCorner maakt het mogelijk alleen geselecteerde hoeken af te ronden, bijvoorbeeld topLeft en bottomRight, terwijl de andere recht blijven. Dit wordt veel gebruikt voor het maken van aangepaste knoppen en kaarten.
init(ovalIn:) maakt een ellips die in de opgegeven rechthoek past. Als de rechthoek een vierkant is, verandert de ellips in een cirkel. init(roundedRect:byRoundingCorners:cornerRadii:) — de meest flexibele variant, waarmee verschillende stralen voor elke hoek kunnen worden ingesteld. Deze initializer verscheen in iOS 6 en blijft de standaard voor het maken van afgeronde containers.
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:) voegt een kwadratische Bézier-curve toe met één controlepunt. Dit type curve wordt gebruikt voor eenvoudige vloeiende buigingen wanneer het aantal berekeningen moet worden geminimaliseerd. De kwadratische curve is altijd een parabool en ligt gegarandeerd binnen de driehoek gevormd door het begin-, controle- en eindpunt.
addCurve(to:controlPoint1:controlPoint2:) voegt een kubische Bézier-curve toe met twee controlepunten. Kubische curven worden gebruikt in alle moderne vectorbewerkers en TrueType-lettertypen. Twee controlepunten bieden meer vrijheidsgraden voor nauwkeurige controle van de curvevorm. Deze methode wordt aanbevolen voor het bouwen van organische en complexe contouren.
Bij het bouwen van curven is het belangrijk het continuïteitsprincipe te volgen — de gladheid van de curve op het verbindingspunt van segmenten. Voor C1-continuïteit (raaklijn) moet het controlepunt van de volgende curve op dezelfde rechte lijn liggen als het controlepunt van de vorige. Voor C2-continuïteit (kromming) is een complexere aanpassing vereist, die automatisch wordt gegarandeerd in CAShapeLayer bij animatie tussen twee UIBezierPath-instanties met hetzelfde aantal controlepunten.
| Methode | Type | Controlepunten | Graad |
|---|---|---|---|
| addQuadCurve | Kwadratische Bézier | 1 | 2 |
| addCurve | Kubische Bézier | 2 | 3 |
| addArc | Boog | — | — |
addArc(withCenter:radius:startAngle:endAngle:clockwise:) voegt een cirkelboog toe met de opgegeven parameters. Hoeken worden in radialen opgegeven ten opzichte van het middelpunt van de cirkel. Een hoek van nul komt overeen met de richting naar rechts (3 uur op de wijzerplaat). De parameter clockwise bepaalt de richting: true — met de klok mee, false — tegen de klok in. Bogen zijn onmisbaar voor cirkeldiagrammen, snelheidsmeters en interactieve voortgangsringen.
Voor een volledige cirkel zijn startAngle = 0 en endAngle = .pi * 2 voldoende. Voor het maken van een sector (als onderdeel van een cirkeldiagram) gebruikt u addArc gevolgd door addLine(to:) naar het midden en close(). UIBezierPath heeft geen ingebouwde addCircle-methode — een cirkel wordt gemaakt via init(ovalIn:) met een vierkante rechthoek of via addArc met een volledige hoek.
De methode addArc(withCenter:radius:startAngle:endAngle:clockwise:) voert automatisch move(to:) uit naar het beginpunt van de boog als de huidige positie hiermee niet overeenkomt. Als de huidige positie anders is, wordt een rechte lijn getrokken tussen deze en het begin van de boog. Dit gedrag verschilt van werken met Core Graphics, waar een expliciete move(to:) vóór elke nieuwe contour vereist is.
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() vult het binnengebied van het pad met de huidige fillColor of de kleur die in de grafische context is ingesteld via setFill(). Voor paden met zelfkruisingen wordt de vulregel bepaald door de eigenschap usesEvenOddFillRule. Indien true, wordt de even-oneven regel toegepast: een punt wordt als binnen de vorm beschouwd als een straal ervan de contour een oneven aantal keren snijdt.
stroke() tekent de contour van het pad met de huidige instellingen van lineWidth, lineCapStyle en lineJoinStyle. lineCapStyle bepaalt de vorm van de uiteinden van open segmenten: .butt (rechte snede), .round (halfrond), .square (vierkant met uitsteeksel). lineJoinStyle bepaalt de vorm van verbindingshoeken: .miter (scherp), .round (afgerond), .bevel (afgesneden).
Voor stippellijnen wordt de eigenschap setLineDash(_:count:phase:) gebruikt. Deze neemt een reeks lengtes van afwisselende streepjes en spaties, het aantal elementen en de beginfase. De visualisatie van de stippellijn vindt plaats in de rasterisatiefase van het pad — complexe patronen verhogen de geometrische complexiteit van de contour niet. CAShapeLayer ondersteunt animatie van de eigenschap strokeEnd voor het effect van het “tekenen” van een lijn van begin tot eind.
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()
}
Laten we een aangepaste voortgangsindicator in de vorm van een ring maken met UIBezierPath. De ring wordt gebouwd uit twee bogen met dezelfde straal maar verschillende omlijningskleur. De eerste boog is een volledige grijze cirkel (achtergrond), de tweede is een segment dat de voortgang weergeeft. Voor animatie worden CAShapeLayer en CABasicAnimation gebruikt.
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
}
}
In dit voorbeeld wordt UIBezierPath gebruikt om een ronde contour te maken, die vervolgens via de eigenschap cgPath aan CAShapeLayer wordt doorgegeven. De animatie van strokeEnd van 0 tot 1 visualiseert het vullen van de ring. Deze benadering wordt gebruikt in laadindicatoren, fitnesstrackers en voortgangswidgets. De methode layoutSubviews garandeert herbouw van het pad bij wijziging van de View-afmetingen.
lineCap = .round voegt afgeronde uiteinden toe aan de boog, wat de indicator een netter uiterlijk geeft. De eigenschap strokeEnd is een animeerbare eigenschap van CAShapeLayer die niet vereist dat de hele contour in elk frame opnieuw wordt getekend. De animatie wordt volledig op de GPU uitgevoerd via Core Animation, wat 60 FPS garandeert zonder CPU-belasting.
Veelgestelde vragen
UIBezierPath — objectgeoriënteerde verpakking van CGPath met ingebouwde fill()- en stroke()-methoden. CGPath is een onveranderlijk C Core Graphics-object dat expliciet tekenen via CGContext vereist. UIBezierPath is handiger voor UIKit, CGPath is efficiënter voor hergebruik.
Gebruik init(roundedRect:byRoundingCorners:cornerRadii:) met de parameter .topLeft en .topRight voor roundedRect. Dit is de enige UIBezierPath-methode die selectieve hoekafronding mogelijk maakt zonder een complex samengesteld pad te maken.
De eigenschap cgPath retourneert een onveranderlijke CGPathRef die kan worden doorgegeven aan CAShapeLayer of gebruikt met verschillende kleuren en diktes. Wijzigingen aan UIBezierPath (verplaatsen van punten) hebben geen invloed op eerder verkregen cgPath tot expliciete bijwerking.
Controleer usesEvenOddFillRule — als de contour zelfkruisingen heeft, kan de even-oneven regel gebieden ongevuld laten. Stel usesEvenOddFillRule = false in voor de standaard non-zero winding vulregel.
Gebruik CABasicAnimation met het sleutelpad “path” op CAShapeLayer. Beide padtoestanden moeten hetzelfde aantal segmenten en controlepunten bevatten — anders zal de animatie schokkerig zijn of niet werken.
Samenvatting
We 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