CAShapeLayer — je podtřída CALayer určená pro hardwarové vykreslování vektorových obrysů na GPU. Na rozdíl od základního CALayer, který pracuje s rastrovými obrázky přes contents, CAShapeLayer vykresluje libovolné tvary zadané přes CGPath bez vytváření samostatného offscreen bufferu. Podle Apple QuartzCore Documentation, 2025 používá CAShapeLayer hardwarovou akceleraci pro vyhlazování hran a podporuje animaci path, strokeStart a strokeEnd. Je to standardní nástroj pro vytváření ikon, indikátorů průběhu a masek v iOS.
Hlavní body
CAShapeLayer — je specializovaná vrstva pro vykreslování vektorové grafiky, představená v iOS 3.0. Na rozdíl od CALayer, který ukládá rastrový obrázek, CAShapeLayer ukládá matematický popis obrysu — CGPath — a vykresluje jej přímo na GPU. To umožňuje škálování tvaru bez ztráty kvality a animaci jeho vlastností bez překreslování obsahu.
Architektonicky CAShapeLayer dědí všechny schopnosti CALayer: stíny, okraje, transformace, masky. Přidává však specifické vlastnosti pro práci s obrysy: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd a fillRule. Každá z těchto vlastností může být animována pomocí CABasicAnimation.
Podle Apple Documentation používá CAShapeLayer hardwarovou akceleraci při vykreslování. Na rozdíl od kreslení přes Core Graphics v drawRect:, kde CPU vykresluje obrys v rastrovém kontextu, CAShapeLayer posílá příkazy přímo na GPU přes Metal. Výsledek — vyšší výkon, zejména během animace.
CAShapeLayer je zvláště užitečný pro prvky rozhraní, které mění tvar v reakci na akce uživatele: indikátory průběhu, grafy, ikony tab-bar, masky pro animaci zobrazení obsahu.
Proces vykreslování CAShapeLayer se liší od základního CALayer. Místo ukládání rastrového bufferu s pixely posílá CAShapeLayer GPU popis vrcholů obrysu — sadu bodů, Bézierových křivek a segmentů. GPU tento obrys rasterizuje v jednom průchodu, aplikuje barvu výplně a obrysu ve fázi fragment shaderu.
Tento přístup poskytuje dvě výhody: škálování bez ztráty kvality (vektorová grafika zůstává ostrá při jakémkoli rozlišení) a efektivní animaci — při změně path GPU přepočítává pouze změněné pixely, ne celou obrazovku.
path — centrální vlastnost CAShapeLayer, přijímající CGPath. Obrys může obsahovat čáry, oblouky, Bézierovy křivky a obdélníky. Vytváří se přes UIBezierPath ve Swift nebo CGPath v Core Graphics. Příklad: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath vytváří zaoblený obdélník.
Vlastnost lineDashPattern umožňuje vytváření přerušovaných čar. Přijímá pole čísel: [6, 3] znamená 6 bodů čáry a 3 body mezery. lineDashPhase nastavuje posun vzoru a může být animována pro efekt pohybující se přerušované čáry.
Volba mezi CAShapeLayer a základním CALayer závisí na typu obsahu. Pokud je prvek obdélníková oblast s pozadím, okrajem a stínem — stačí CALayer. Pokud má prvek libovolný tvar, vyžaduje animaci obrysu nebo škálování bez ztráty kvality — CAShapeLayer je vhodnější.
Výkon se také liší. CALayer s cornerRadius a masksToBounds vytváří offscreen buffer pro ořezávání obsahu, což přidává 2–5 ms na snímek. CAShapeLayer nevyžaduje offscreen buffer — ořezávání probíhá na úrovni vertex shaderu. Pro prvky se složitou maskou může být CAShapeLayer 2–3krát rychlejší.
Kombinování CAShapeLayer s jinými vrstvami je běžný vzor. Například CAGradientLayer používá CAShapeLayer jako masku pro vytvoření tvaru s přechodovou výplní. Tento přístup poskytuje jak vektorovou kvalitu, tak přechodovou výplň bez ztráty výkonu.
Animace path — jedna z nejsilnějších schopností CAShapeLayer. Pokud mají oba obrysy (počáteční a koncový) stejný počet řídicích bodů a segmentů, Core Animation provádí plynulou interpolaci mezi nimi. Výsledek — efekt morfingu jednoho tvaru do druhého.
Podmínka kompatibility path: počáteční a koncový UIBezierPath musí mít stejnou strukturu — počet volání moveTo, addLine, addCurve a addQuadCurve se musí shodovat. Pokud se struktura liší, animace bude okamžitá, bez interpolace.
Podle Apple WWDC 2024 je kombinace strokeStart a strokeEnd nejčastěji používaným vzorem animace CAShapeLayer. Animace strokeEnd od 0.0 do 1.0 vytváří efekt kreslení obrysu od začátku do konce. Používá se v indikátorech načítání, animacích zobrazení grafů a vlastních přechodech mezi obrazovkami.
Pro vytvoření pulzujícího efektu animujte současně strokeEnd a opacity s různými časovacími funkcemi. Pro efekt pohybující se přerušované čáry animujte lineDashPhase s pevným lineDashPattern. Obě techniky jsou implementovány přes CABasicAnimation bez účasti CPU.
CAShapeLayer se často používá jako mask pro jiné vrstvy. Například pro animaci zobrazení obsahu: na začátku je mask.path obdélník nulové velikosti, na konci — plná velikost. Core Animation interpoluje path a obsah se plynule odhalí.
Tento vzor se používá v iOS pro animaci rozbalování karet, zobrazování modálních oken a přechodů mezi view controllery. Na rozdíl od animace alpha poskytuje animace přes masku CAShapeLayer přirozenější efekt zobrazení s libovolným tvarem.
První příklad — vytvoření kruhového indikátoru průběhu s animací strokeEnd. Toto je standardní prvek UI, který demonstruje hlavní schopnosti 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
}
// Animovat na 75%
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
Druhý příklad — animace morfingu mezi kruhem a čtvercem. Oba UIBezierPath mají kompatibilní strukturu:
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")
Třetí příklad — maska s CAShapeLayer pro animaci zobrazení obsahu. Maska se rozšiřuje od středu k okrajům:
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
}
Často kladené otázky
drawRect používá CPU pro vykreslování v rastrovém kontextu — je pomalé pro animace. CAShapeLayer vykresluje obrys na GPU, což poskytuje 60 FPS při animaci path, strokeEnd a transformací. Kromě toho CAShapeLayer nevyžaduje překreslení při změně velikosti — tvar se škáluje vektorově.
Plynulá animace path vyžaduje stejnou strukturu počátečního a koncového UIBezierPath. Počet volání moveTo, addLine, addCurve se musí shodovat. Použijte UIBezierPath se stejným počtem segmentů pro počáteční a koncový tvar.
Nastavte lineDashPattern — pole čísel střídavě určujících délku čáry a mezery. Například [8, 4] vytváří čáry 8pt s mezerami 4pt. Pro pohybující se přerušovanou čáru animujte lineDashPhase přes CABasicAnimation s lineární časovací funkcí.
Ano, to je jeden z hlavních scénářů. Přiřaďte CAShapeLayer vlastnosti mask libovolného CALayer, včetně CAGradientLayer a dalších podtříd. Animace path masky vytváří efekt plynulého zobrazení obsahu přes tvar libovolné formy.
Vytvořte CAGradientLayer a nastavte jeho mask = CAShapeLayer s požadovaným path. Přechod bude viditelný pouze uvnitř obrysu masky. Tento vzor kombinuje výhody vektorového tvaru CAShapeLayer s přechodovou výplní CAGradientLayer.
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é