CAShapeLayer ist eine Unterklasse von CALayer, die für das hardwarebeschleunigte Rendern von Vektorpfaden auf der GPU entwickelt wurde. Im Gegensatz zu CALayer, das mit Rasterbildern über contents arbeitet, rendert CAShapeLayer beliebige Formen, die über CGPath definiert werden, ohne einen separaten Offscreen-Puffer zu erstellen. Laut Apple QuartzCore Documentation, 2025 verwendet CAShapeLayer Hardwarebeschleunigung für Kantenglättung und unterstützt Animation von path, strokeStart und strokeEnd. Es ist ein Standardwerkzeug zum Erstellen von Symbolen, Fortschrittsanzeigen und Masken in iOS.
Wichtige Punkte
CAShapeLayer ist eine spezialisierte Ebene zum Rendern von Vektorgrafiken, eingeführt in iOS 3.0. Im Gegensatz zu CALayer, das ein Rasterbild speichert, speichert CAShapeLayer eine mathematische Beschreibung eines Pfades — CGPath — und rendert ihn direkt auf der GPU. Dies ermöglicht das Skalieren der Form ohne Qualitätsverlust und das Animieren ihrer Eigenschaften ohne Neuzeichnen des Inhalts.
Architektonisch erbt CAShapeLayer alle Fähigkeiten von CALayer: Schatten, Rahmen, Transformationen, Masken. Es fügt jedoch spezifische Eigenschaften für die Arbeit mit Pfaden hinzu: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd und fillRule. Jede dieser Eigenschaften kann über CABasicAnimation animiert werden.
Laut Apple Documentation verwendet CAShapeLayer Hardwarebeschleunigung für das Rendern. Im Gegensatz zum Zeichnen über Core Graphics in drawRect:, wo die CPU den Pfad in einen Rasterkontext rendert, sendet CAShapeLayer Befehle direkt über Metal an die GPU. Das Ergebnis ist eine höhere Leistung, insbesondere während der Animation.
CAShapeLayer ist besonders nützlich für Oberflächenelemente, die ihre Form als Reaktion auf Benutzeraktionen ändern: Fortschrittsanzeigen, Diagramme, Tableistensymbole, Masken für Einblendanimationen.
Der Renderprozess von CAShapeLayer unterscheidet sich von dem von CALayer. Anstatt einen Rasterpuffer mit Pixeln zu speichern, übergibt CAShapeLayer eine Scheitelpunktbeschreibung des Pfades an die GPU — eine Sammlung von Punkten, Bezier-Kurven und Liniensegmenten. Die GPU rastert diesen Pfad in einem Durchgang, wobei sie Füll- und Strichfarben auf der Fragment-Shader-Stufe anwendet.
Dieser Ansatz bietet zwei Vorteile: Skalierung ohne Qualitätsverlust (Vektorgrafiken bleiben bei jeder Auflösung scharf) und effiziente Animation — wenn sich der Pfad ändert, berechnet die GPU nur die geänderten Pixel neu, nicht den gesamten Bildschirm.
path — die zentrale Eigenschaft von CAShapeLayer, die einen CGPath akzeptiert. Der Pfad kann Linien, Bögen, Bezier-Kurven und Rechtecke enthalten. Er wird über UIBezierPath in Swift oder CGPath in Core Graphics erstellt. Beispiel: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath erstellt ein abgerundetes Rechteck.
Die Eigenschaft lineDashPattern ermöglicht das Erstellen gestrichelter Linien. Sie akzeptiert ein Zahlenarray: [6, 3] bedeutet 6 Punkte Strich und 3 Punkte Lücke. lineDashPhase legt den Muster-Offset fest und kann für einen bewegten Stricheffekt animiert werden.
Die Wahl zwischen CAShapeLayer und CALayer hängt von der Art des Inhalts ab. Wenn das Element ein rechteckiger Bereich mit Hintergrund, Rahmen und Schatten ist — ist CALayer ausreichend. Wenn das Element eine beliebige Form hat, Pfadanimation oder verlustfreie Skalierung erfordert — ist CAShapeLayer vorzuziehen.
Die Leistung unterscheidet sich ebenfalls. CALayer mit cornerRadius und masksToBounds erstellt einen Offscreen-Puffer zum Beschneiden von Inhalten, was 2–5 ms pro Frame hinzufügt. CAShapeLayer benötigt keinen Offscreen-Puffer — die Beschneidung erfolgt auf der Vertex-Shader-Ebene. Für Elemente mit komplexen Masken kann CAShapeLayer 2–3 mal schneller sein.
CAShapeLayer mit anderen Ebenen zu kombinieren, ist ein gängiges Muster. Zum Beispiel verwendet CAGradientLayer CAShapeLayer als Maske, um eine Form mit Verlaufsfüllung zu erstellen. Dieser Ansatz bietet sowohl Vektorqualität als auch Verlaufsfüllung ohne Leistungseinbußen.
Pfadanimation ist eine der leistungsstärksten Funktionen von CAShapeLayer. Wenn beide Pfade (Anfangs- und Endpfad) die gleiche Anzahl von Kontrollpunkten und Segmenten haben, führt Core Animation eine sanfte Interpolation zwischen ihnen durch. Das Ergebnis ist ein Morphing-Effekt von einer Form zur anderen.
Pfadkompatibilitätsbedingung: Der Anfangs- und End-UIBezierPath müssen die gleiche Struktur haben — die Anzahl der moveTo-, addLine-, addCurve- und addQuadCurve-Aufrufe muss übereinstimmen. Wenn die Struktur unterschiedlich ist, erfolgt die Animation sofort ohne Interpolation.
Laut Apple WWDC 2024 ist die Kombination von strokeStart und strokeEnd das am häufigsten verwendete CAShapeLayer-Animationsmuster. Das Animieren von strokeEnd von 0.0 bis 1.0 erzeugt einen Pfadzeichnungseffekt von Anfang bis Ende. Dies wird in Ladeanzeigen, Diagramm-Einblendeanimationen und benutzerdefinierten Bildschirmübergängen verwendet.
Um einen Pulseffekt zu erzeugen, animieren Sie strokeEnd und opacity gleichzeitig mit verschiedenen Timing-Funktionen. Für einen Ameiseneffekt animieren Sie lineDashPhase mit einem festen lineDashPattern. Beide Techniken werden über CABasicAnimation ohne CPU-Beteiligung implementiert.
CAShapeLayer wird oft als Maske für andere Ebenen verwendet. Zum Beispiel für Einblendanimationen: Anfangs ist mask.path ein Rechteck der Größe Null, das Endstück ist die volle Größe. Core Animation interpoliert den Pfad und der Inhalt erscheint sanft.
Dieses Muster wird in iOS für Kartenausklappanimationen, modale Fensterpräsentationen und View-Controller-Übergänge verwendet. Im Gegensatz zur Alpha-Animation bietet die CAShapeLayer-Maskenanimation einen natürlicheren Einblendungseffekt mit beliebigen Formen.
Das erste Beispiel — Erstellen einer kreisförmigen Fortschrittsanzeige mit strokeEnd-Animation. Dies ist ein standardmäßiges UI-Element, das die wichtigsten Funktionen von CAShapeLayer demonstriert:
func createProgressIndicator(in view: UIView) -> CAShapeLayer {
let circlePath = UIBezierPath(
arcCenter: CGPoint(x: 50, y: 50),
radius: 40,
startAngle: -.pi / 2,
endAngle: 3 * .pi / 2,
clockwise: true
)
let trackLayer = CAShapeLayer()
trackLayer.path = circlePath.cgPath
trackLayer.strokeColor = UIColor.systemGray5.cgColor
trackLayer.fillColor = nil
trackLayer.lineWidth = 8
view.layer.addSublayer(trackLayer)
let progressLayer = CAShapeLayer()
progressLayer.path = circlePath.cgPath
progressLayer.strokeColor = UIColor.systemBlue.cgColor
progressLayer.fillColor = nil
progressLayer.lineWidth = 8
progressLayer.lineCap = .round
progressLayer.strokeEnd = 0
view.layer.addSublayer(progressLayer)
return progressLayer
}
// Auf 75% animieren
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
Das zweite Beispiel — Morphing-Animation zwischen einem Kreis und einem Quadrat. Beide UIBezierPath haben eine kompatible Struktur:
let morphLayer = CAShapeLayer()
morphLayer.fillColor = UIColor.systemPurple.cgColor
morphLayer.frame = rect
let circlePath = UIBezierPath(roundedRect: rect, cornerRadius: rect.width / 2)
let squarePath = UIBezierPath(roundedRect: rect, cornerRadius: 0)
morphLayer.path = circlePath.cgPath
let morphAnimation = CABasicAnimation(keyPath: "path")
morphAnimation.toValue = squarePath.cgPath
morphAnimation.duration = 0.6
morphAnimation.autoreverses = true
morphAnimation.repeatCount = .infinity
morphLayer.add(morphAnimation, forKey: "morph")
Das dritte Beispiel — eine CAShapeLayer-Maske für die Einblendanimation von Inhalten. Die Maske expandiert von der Mitte zu den Rändern:
func revealContent(_ view: UIView) {
let maskLayer = CAShapeLayer()
let size = view.bounds.size.width * 1.5
let center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
let initialPath = UIBezierPath(arcCenter: center, radius: 0, startAngle: 0, endAngle: .pi * 2, clockwise: true)
let finalPath = UIBezierPath(arcCenter: center, radius: size, startAngle: 0, endAngle: .pi * 2, clockwise: true)
maskLayer.path = initialPath.cgPath
view.layer.mask = maskLayer
let animation = CABasicAnimation(keyPath: "path")
animation.toValue = finalPath.cgPath
animation.duration = 0.4
animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
maskLayer.add(animation, forKey: "reveal")
maskLayer.path = finalPath.cgPath
}
Häufig gestellte Fragen
drawRect verwendet die CPU zum Rendern in einen Rasterkontext — das ist langsam für Animationen. CAShapeLayer rendert den Pfad auf der GPU und liefert 60 FPS bei path-, strokeEnd- und Transform-Animationen. Außerdem erfordert CAShapeLayer kein Neuzeichnen bei Größenänderung — die Form skaliert vektoriell.
Eine flüssige Pfadanimation erfordert identische Struktur des Anfangs- und End-UIBezierPath. Die Anzahl der moveTo-, addLine-, addCurve-Aufrufe muss übereinstimmen. Verwenden Sie UIBezierPath mit der gleichen Anzahl von Segmenten für die Anfangs- und Endform.
Setzen Sie lineDashPattern — ein Array von Zahlen, die Strich- und Lückenlängen abwechseln. Zum Beispiel erstellt [8, 4] 8pt-Striche mit 4pt-Lücken. Für einen Ameiseneffekt animieren Sie lineDashPhase über CABasicAnimation mit einer linearen Timing-Funktion.
Ja, dies ist einer der Hauptanwendungsfälle. Weisen Sie CAShapeLayer der mask-Eigenschaft eines beliebigen CALayer zu, einschließlich CAGradientLayer und anderer Unterklassen. Das Animieren des Maskenpfads erzeugt einen sanften Einblendungseffekt des Inhalts durch eine beliebige Form.
Erstellen Sie einen CAGradientLayer und setzen Sie seinen mask = CAShapeLayer mit dem gewünschten Pfad. Der Verlauf ist nur innerhalb des Maskenpfads sichtbar. Dieses Muster kombiniert die Vorteile der Vektorform von CAShapeLayer und der Verlaufsfüllung von CAGradientLayer.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch