CAShapeLayer — är en underklass av CALayer som är utformad för hårdvarurendering av vektorkonturer på GPU. Till skillnad från grundläggande CALayer som arbetar med rasterbilder via contents, renderar CAShapeLayer godtyckliga former som definieras via CGPath utan att skapa en separat offscreen-buffer. Enligt Apple QuartzCore Documentation, 2025 använder CAShapeLayer hårdvaruacceleration för kantutjämning och stöder animering av path, strokeStart och strokeEnd. Det är ett standardverktyg för att skapa ikoner, förloppsindikatorer och masker i iOS.
Huvudpunkter
CAShapeLayer — är ett specialiserat lager för rendering av vektorgrafik, introducerat i iOS 3.0. Till skillnad från CALayer som lagrar en rasterbild, lagrar CAShapeLayer den matematiska beskrivningen av konturen — CGPath — och renderar den direkt på GPU. Detta gör att formen kan skalas utan kvalitetsförlust och dess egenskaper animeras utan att innehållet renderas om.
Arkitektoniskt ärver CAShapeLayer alla funktioner från CALayer: skuggor, kanter, transformationer, masker. Men det lägger till specifika egenskaper för arbete med konturer: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd och fillRule. Var och en av dessa egenskaper kan animeras via CABasicAnimation.
Enligt Apple Documentation använder CAShapeLayer hårdvaruacceleration vid rendering. Till skillnad från ritning via Core Graphics i drawRect:, där CPU renderar konturen i ett rastersammanhang, skickar CAShapeLayer kommandon direkt till GPU via Metal. Resultat — högre prestanda, särskilt under animering.
CAShapeLayer är särskilt användbar för gränssnittselement som ändrar form som svar på användaråtgärder: förloppsindikatorer, diagram, tab-bar-ikoner, masker för animering av innehållsvisning.
Renderingsprocessen för CAShapeLayer skiljer sig från grundläggande CALayer. Istället för att lagra en rasterbuffer med pixlar, skickar CAShapeLayer GPU en vertexbeskrivning av konturen — en uppsättning punkter, Bezier-kurvor och segment. GPU rasteriserar konturen i ett enda pass, applicerar fyllnings- och konturfärgen i fragment-shader-steget.
Denna metod ger två fördelar: skalning utan kvalitetsförlust (vektorgrafik förblir skarp i alla upplösningar) och effektiv animering — när path ändras beräknar GPU endast de ändrade pixlarna, inte hela skärmen.
path — den centrala egenskapen för CAShapeLayer som tar emot CGPath. Konturen kan innehålla linjer, bågar, Bezier-kurvor och rektanglar. Skapas via UIBezierPath i Swift eller CGPath i Core Graphics. Exempel: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath skapar en rundad rektangel.
Egenskapen lineDashPattern gör det möjligt att skapa streckade linjer. Tar emot en matris med tal: [6, 3] betyder 6 punkter linje och 3 punkter mellanrum. lineDashPhase anger mönsterförskjutning och kan animeras för effekt av en rörlig streckad linje.
Valet mellan CAShapeLayer och grundläggande CALayer beror på innehållstypen. Om elementet är ett rektangulärt område med bakgrund, kant och skugga — räcker CALayer. Om elementet har en godtycklig form, kräver konturanimering eller skalning utan kvalitetsförlust — är CAShapeLayer att föredra.
Prestandan skiljer sig också. CALayer med cornerRadius och masksToBounds skapar en offscreen-buffer för beskärning av innehåll, vilket lägger till 2–5 ms per bildruta. CAShapeLayer kräver ingen offscreen-buffer — beskärning sker på vertex-shader-nivå. För element med komplex mask kan CAShapeLayer vara 2–3 gånger snabbare.
Att kombinera CAShapeLayer med andra lager är ett vanligt mönster. Till exempel använder CAGradientLayer CAShapeLayer som mask för att skapa en form med gradientfyllning. Denna metod ger både vektorkvalitet och gradientfyllning utan prestandaförlust.
Path-animering — en av de mest kraftfulla funktionerna i CAShapeLayer. Om båda konturerna (start och slut) har samma antal kontrollpunkter och segment, utför Core Animation en smidig interpolation mellan dem. Resultat — effekten av att en form omvandlas till en annan.
Villkor för path-kompatibilitet: start- och slut-UIBezierPath måste ha samma struktur — antalet anrop till moveTo, addLine, addCurve och addQuadCurve måste matcha. Om strukturen skiljer sig kommer animeringen att vara omedelbar, utan interpolation.
Enligt Apple WWDC 2024 är kombinationen av strokeStart och strokeEnd det mest använda animeringsmönstret för CAShapeLayer. Animering av strokeEnd från 0.0 till 1.0 skapar effekten av att rita konturen från början till slut. Det används i laddningsindikatorer, animeringar av diagramvisning och anpassade övergångar mellan skärmar.
För att skapa en pulserande effekt, animera strokeEnd och opacity samtidigt med olika timingfunktioner. För effekten av en rörlig streckad linje, animera lineDashPhase med fast lineDashPattern. Båda teknikerna implementeras via CABasicAnimation utan CPU-deltagande.
CAShapeLayer används ofta som mask för andra lager. Till exempel för animering av innehållsvisning: i början är mask.path en rektangel med noll storlek, i slutet — full storlek. Core Animation interpolerar path och innehållet avslöjas smidigt.
Detta mönster används i iOS för animering av kortutvikning, visning av modala fönster och övergångar mellan view controllers. Till skillnad från alpha-animering ger animering via en CAShapeLayer-mask en mer naturlig visningseffekt med godtycklig form.
Första exemplet — skapa en cirkulär förloppsindikator med strokeEnd-animering. Detta är ett standard UI-element som visar de viktigaste funktionerna i CAShapeLayer:
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
}
// Animera till 75%
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
Andra exemplet — omvandlingsanimering mellan cirkel och kvadrat. Båda UIBezierPath har en kompatibel 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")
Tredje exemplet — mask med CAShapeLayer för animering av innehållsvisning. Masken expanderar från mitten till kanterna:
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
}
Vanliga frågor
drawRect använder CPU för rendering i ett rastersammanhang — det är långsamt för animationer. CAShapeLayer renderar konturen på GPU, vilket ger 60 FPS vid animering av path, strokeEnd och transformationer. Dessutom kräver CAShapeLayer ingen omrendering vid storleksändring — formen skalas vektoriellt.
Smidig path-animering kräver samma struktur för start- och slut-UIBezierPath. Antalet anrop till moveTo, addLine, addCurve måste matcha. Använd UIBezierPath med samma antal segment för start- och slutformen.
Ställ in lineDashPattern — en matris med tal som växelvis anger längden på linje och mellanrum. Till exempel skapar [8, 4] linjer på 8pt med mellanrum på 4pt. För en rörlig streckad linje, animera lineDashPhase via CABasicAnimation med en linjär timingfunktion.
Ja, det är ett av huvudalternativen. Tilldela CAShapeLayer till egenskapen mask för valfri CALayer, inklusive CAGradientLayer och andra underklasser. Animering av maskens path skapar en smidig visningseffekt av innehåll genom en godtycklig form.
Skapa en CAGradientLayer och ställ in dess mask = CAShapeLayer med önskad path. Gradienten syns endast inom maskens kontur. Detta mönster kombinerar fördelarna med CAShapeLayer vektorform och CAGradientLayer gradientfyllning.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också