UIBezierPath — μια κλάση από το UIKit που ενσωματώνει μια διανυσματική διαδρομή για 2D γραφικά στο iOS. Συνδυάζει τη γεωμετρική περιγραφή του περιγράμματος με δυνατότητες σχεδίασης, επιτρέποντας τη δημιουργία γραμμών, καμπυλών Bézier, τόξων και ορθογωνίων. Σε αντίθεση με το CGPath, το UIBezierPath περιέχει δικές του μεθόδους σχεδίασης απευθείας στο τρέχον γραφικό περιβάλλον. Σύμφωνα με το Apple Developer Documentation, 2026, το UIBezierPath υποστηρίζει όλες τις τυπικές λειτουργίες του Quartz 2D σε ένα αντικειμενοστραφές περιτύλιγμα.
Κύρια σημεία
UIBezierPath — μια κλάση του πλαισίου UIKit, που κληρονομεί το NSObject και υλοποιεί τα NSCopying, NSSecureCoding. Παρέχει ένα υψηλού επιπέδου Objective-C/Swift API για την κατασκευή και σχεδίαση διανυσματικών περιγραμμάτων. Εσωτερικά, το UIBezierPath αποθηκεύει μια αναφορά σε CGPathRef — ένα αντικείμενο Core Graphics, αλλά προσθέτει βολικές μεθόδους για σχεδίαση, αλλαγή γεωμετρίας και διαχείριση στυλ.
Το κύριο πλεονέκτημα του UIBezierPath έναντι της άμεσης χρήσης του CGPath είναι οι ενσωματωμένες μέθοδοι σχεδίασης. Η κλήση fill() ή stroke() σε ένα στιγμιότυπο UIBezierPath διαμορφώνει αυτόματα το περιβάλλον και σχεδιάζει τη διαδρομή. Η κλάση υποστηρίζει επίσης τις ιδιότητες lineWidth, lineCapStyle, lineJoinStyle, miterLimit και flatness, επιτρέποντας τη διαχείριση της εμφάνισης χωρίς ξεχωριστό αντικείμενο αποθήκευσης στυλ.
Το UIBezierPath χρησιμοποιείται στις περισσότερες εφαρμογές iOS για προσαρμοσμένη σχεδίαση εντός του UIView: από απλά εικονίδια έως σύνθετα κινούμενα γραφήματα. Η μέθοδος draw(_:) της κλάσης UIView είναι το κύριο σημείο όπου οι προγραμματιστές δημιουργούν και σχεδιάζουν UIBezierPath. Η κλάση είναι πλήρως συμβατή με το Core Animation και μπορεί να χρησιμοποιηθεί για κινούμενη σχεδίαση της διαδρομής μέσω CAShapeLayer και CABasicAnimation.
Η μέθοδος move(to:) μετακινεί το σημείο έναρξης της διαδρομής στις δεδομένες συντεταγμένες χωρίς σχεδίαση. Αυτή είναι υποχρεωτική κλήση πριν από την κατασκευή οποιουδήποτε τμήματος. Η addLine(to:) προσθέτει ένα ευθύγραμμο τμήμα από την τρέχουσα θέση στο καθορισμένο σημείο. Για το κλείσιμο του περιγράμματος χρησιμοποιείται η μέθοδος close(), η οποία σχεδιάζει μια γραμμή από το τελευταίο σημείο στο πρώτο σημείο του τελευταίου move(to:).
Το UIBezierPath παρέχει αρκετούς βολικούς αρχικοποιητές για έτοιμα σχήματα. Το init(rect:) δημιουργεί ένα ορθογώνιο, το init(roundedRect:cornerRadius:) — ένα ορθογώνιο με στρογγυλεμένες γωνίες. Η παράμετρος UIRectCorner επιτρέπει τη στρογγυλοποίηση μόνο επιλεγμένων γωνιών, για παράδειγμα topLeft και bottomRight, αφήνοντας τις υπόλοιπες ευθείες. Αυτό χρησιμοποιείται ευρέως για τη δημιουργία προσαρμοσμένων κουμπιών και καρτών.
Το init(ovalIn:) δημιουργεί μια έλλειψη εγγεγραμμένη στο δεδομένο ορθογώνιο. Εάν το ορθογώνιο είναι τετράγωνο, η έλλειψη μετατρέπεται σε κύκλο. Το init(roundedRect:byRoundingCorners:cornerRadii:) — η πιο ευέλικτη παραλλαγή, που επιτρέπει τον ορισμό διαφορετικών ακτίνων για κάθε γωνία. Αυτός ο αρχικοποιητής εμφανίστηκε στο iOS 6 και παραμένει το πρότυπο για τη δημιουργία στρογγυλεμένων δοχείων.
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:) προσθέτει μια τετραγωνική καμπύλη Bézier με ένα σημείο ελέγχου. Αυτός ο τύπος καμπύλης χρησιμοποιείται για απλές ομαλές κάμψεις όταν απαιτείται ελαχιστοποίηση των υπολογισμών. Η τετραγωνική καμπύλη είναι πάντα παραβολή και βρίσκεται εγγυημένα εντός του τριγώνου που σχηματίζεται από τα σημεία έναρξης, ελέγχου και τέλους.
Η addCurve(to:controlPoint1:controlPoint2:) προσθέτει μια κυβική καμπύλη Bézier με δύο σημεία ελέγχου. Οι κυβικές καμπύλες χρησιμοποιούνται σε όλους τους σύγχρονους επεξεργαστές διανυσμάτων και τις γραμματοσειρές TrueType. Δύο σημεία ελέγχου παρέχουν περισσότερους βαθμούς ελευθερίας για ακριβή έλεγχο του σχήματος της καμπύλης. Αυτή η μέθοδος συνιστάται για την κατασκευή οργανικών και σύνθετων περιγραμμάτων.
Κατά την κατασκευή καμπυλών είναι σημαντικό να τηρείται η αρχή της συνέχειας — η ομαλότητα της καμπύλης στο σημείο σύνδεσης των τμημάτων. Για συνέχεια C1 (εφαπτομένη), το σημείο ελέγχου της επόμενης καμπύλης πρέπει να βρίσκεται στην ίδια ευθεία με το σημείο ελέγχου της προηγούμενης. Για συνέχεια C2 (καμπυλότητα) απαιτείται πιο σύνθετη ευθυγράμμιση, η οποία εξασφαλίζεται αυτόματα στο CAShapeLayer κατά την κινούμενη σχεδίαση μεταξύ δύο UIBezierPath με τον ίδιο αριθμό σημείων ελέγχου.
| Μέθοδος | Τύπος | Σημεία ελέγχου | Βαθμός |
|---|---|---|---|
| addQuadCurve | Τετραγωνική Bézier | 1 | 2 |
| addCurve | Κυβική Bézier | 2 | 3 |
| addArc | Τόξο | — | — |
Η addArc(withCenter:radius:startAngle:endAngle:clockwise:) προσθέτει ένα τόξο κύκλου με δεδομένες παραμέτρους. Οι γωνίες καθορίζονται σε ακτίνια σε σχέση με το κέντρο του κύκλου. Η μηδενική γωνία αντιστοιχεί στην κατεύθυνση προς τα δεξιά (3 η ώρα στο ρολόι). Η παράμετρος clockwise καθορίζει την κατεύθυνση: true — δεξιόστροφα, false — αριστερόστροφα. Τα τόξα είναι απαραίτητα για κυκλικά διαγράμματα, ταχύμετρα και διαδραστικούς δακτυλίους προόδου.
Για έναν πλήρη κύκλο αρκούν startAngle = 0 και endAngle = .pi * 2. Για τη δημιουργία ενός τομέα (ως μέρος ενός κυκλικού διαγράμματος) χρησιμοποιήστε addArc ακολουθούμενο από addLine(to:) στο κέντρο και close(). Το UIBezierPath δεν έχει ενσωματωμένη μέθοδο addCircle — ο κύκλος δημιουργείται μέσω init(ovalIn:) με τετράγωνο ορθογώνιο ή μέσω addArc με πλήρη γωνία.
Η μέθοδος addArc(withCenter:radius:startAngle:endAngle:clockwise:) εκτελεί αυτόματα move(to:) στο σημείο έναρξης του τόξου εάν η τρέχουσα θέση δεν συμπίπτει με αυτό. Εάν η τρέχουσα θέση είναι διαφορετική, σχεδιάζεται μια ευθεία γραμμή μεταξύ αυτής και της αρχής του τόξου. Αυτή η συμπεριφορά διαφέρει από την εργασία με το Core Graphics, όπου απαιτείται ρητό move(to:) πριν από κάθε νέο περίγραμμα.
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() γεμίζει την εσωτερική περιοχή της διαδρομής με το τρέχον χρώμα fillColor ή το χρώμα που ορίστηκε στο γραφικό περιβάλλον μέσω setFill(). Για διαδρομές με αυτο-τομές, ο κανόνας γεμίσματος καθορίζεται από την ιδιότητα usesEvenOddFillRule. Εάν είναι true, εφαρμόζεται ο κανόνας even-odd: ένα σημείο θεωρείται εντός του σχήματος εάν μια ακτίνα από αυτό τέμνει το περίγραμμα περιττό αριθμό φορών.
Η stroke() σχεδιάζει το περίγραμμα της διαδρομής με τις τρέχουσες ρυθμίσεις lineWidth, lineCapStyle και lineJoinStyle. Η lineCapStyle καθορίζει το σχήμα των άκρων ανοικτών τμημάτων: .butt (ευθεία τομή), .round (ημικυκλικό), .square (τετράγωνο με προεξοχή). Η lineJoinStyle καθορίζει το σχήμα των γωνιών ενώσεων: .miter (κοφτερή), .round (στρογγυλεμένη), .bevel (κομμένη).
Για διακεκομμένες γραμμές χρησιμοποιείται η ιδιότητα setLineDash(_:count:phase:). Δέχεται έναν πίνακα μηκών εναλλασσόμενων παύλων και κενών, τον αριθμό στοιχείων και την αρχική φάση. Η οπτικοποίηση της διακεκομμένης γραμμής γίνεται στο στάδιο ραστεροποίησης της διαδρομής — τα σύνθετα μοτίβα δεν αυξάνουν τη γεωμετρική πολυπλοκότητα του περιγράμματος. Το CAShapeLayer υποστηρίζει κινούμενη σχεδίαση της ιδιότητας strokeEnd για το εφέ “σχεδίασης” της γραμμής από την αρχή έως το τέλος.
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()
}
Ας δημιουργήσουμε έναν προσαρμοσμένο δείκτη προόδου σε σχήμα δακτυλίου χρησιμοποιώντας UIBezierPath. Ο δακτύλιος κατασκευάζεται από δύο τόξα ίδιας ακτίνας αλλά διαφορετικού χρώματος περιγράμματος. Το πρώτο τόξο είναι ένας πλήρης γκρι κύκλος (φόντο), το δεύτερο είναι ένα τμήμα που δείχνει την πρόοδο. Για κινούμενη σχεδίαση χρησιμοποιούνται CAShapeLayer και 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
}
}
Σε αυτό το παράδειγμα, το UIBezierPath χρησιμοποιείται για τη δημιουργία ενός κυκλικού περιγράμματος, το οποίο στη συνέχεια μεταβιβάζεται στο CAShapeLayer μέσω της ιδιότητας cgPath. Η κινούμενη σχεδίαση του strokeEnd από 0 έως 1 οπτικοποιεί το γέμισμα του δακτυλίου. Αυτή η προσέγγιση χρησιμοποιείται σε δείκτες φόρτωσης, ιχνηλάτες γυμναστικής και widget προόδου. Η μέθοδος layoutSubviews εγγυάται την ανακατασκευή της διαδρομής κατά την αλλαγή μεγεθών του View.
Το lineCap = .round προσθέτει στρογγυλεμένα άκρα στο τόξο, δίνοντας στον δείκτη μια πιο τακτοποιημένη εμφάνιση. Η ιδιότητα strokeEnd είναι μια ιδιότητα του CAShapeLayer που μπορεί να κινηθεί και δεν απαιτεί επανασχεδίαση ολόκληρου του περιγράμματος σε κάθε καρέ. Η κινούμενη σχεδίαση εκτελείται εξ ολοκλήρου στη GPU μέσω του Core Animation, εξασφαλίζοντας 60 FPS χωρίς φόρτο CPU.
Συχνές Ερωτήσεις
UIBezierPath — αντικειμενοστραφές περιτύλιγμα του CGPath που περιέχει ενσωματωμένες μεθόδους fill() και stroke(). Το CGPath είναι ένα μη τροποποιήσιμο αντικείμενο C Core Graphics που απαιτεί ρητή σχεδίαση μέσω CGContext. Το UIBezierPath είναι πιο βολικό για UIKit, το CGPath είναι πιο αποδοτικό για επαναχρησιμοποίηση.
Χρησιμοποιήστε το init(roundedRect:byRoundingCorners:cornerRadii:) με την παράμετρο .topLeft και .topRight για το roundedRect. Αυτή είναι η μόνη μέθοδος UIBezierPath που επιτρέπει επιλεκτική στρογγυλοποίηση γωνιών χωρίς δημιουργία σύνθετης σύνθετης διαδρομής.
Η ιδιότητα cgPath επιστρέφει ένα αμετάβλητο CGPathRef που μπορεί να μεταβιβαστεί στο CAShapeLayer ή να χρησιμοποιηθεί με διαφορετικά χρώματα και πάχη. Οι τροποποιήσεις του UIBezierPath (μετακίνηση σημείων) δεν επηρεάζουν το προηγουμένως ληφθέν cgPath μέχρι ρητής ενημέρωσης.
Ελέγξτε το usesEvenOddFillRule — εάν το περίγραμμα έχει αυτο-τομές, ο κανόνας even-odd μπορεί να αφήσει περιοχές αγέμιστες. Ορίστε usesEvenOddFillRule = false για τον τυπικό κανόνα γεμίσματος non-zero winding.
Χρησιμοποιήστε το CABasicAnimation με το κλειδί διαδρομής “path” στο CAShapeLayer. Και οι δύο καταστάσεις διαδρομής πρέπει να περιέχουν τον ίδιο αριθμό τμημάτων και σημείων ελέγχου — διαφορετικά η κινούμενη σχεδίαση θα είναι τραυματική ή δεν θα λειτουργήσει.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης