CAShapeLayer — a CALayer egy alosztálya, amely vektoros kontúrok hardveres megjelenítésére szolgál a GPU-n. Ellentétben az alap CALayer-rel, amely raszterképekkel dolgozik a contents-en keresztül, a CAShapeLayer a CGPath-en keresztül megadott tetszőleges alakzatokat jelenít meg külön offscreen buffer létrehozása nélkül. A Apple QuartzCore Documentation, 2025 szerint a CAShapeLayer hardveres gyorsítást használ az élek simításához és támogatja a path, strokeStart és strokeEnd animációját. Ez a szabványos eszköz ikonok, folyamatjelzők és maszkok létrehozására iOS-ben.
Főbb pontok
CAShapeLayer — egy specializált réteg vektorgrafika megjelenítésére, amely az iOS 3.0-ban került bevezetésre. Ellentétben a CALayer-rel, amely raszterképet tárol, a CAShapeLayer a kontúr matematikai leírását — CGPath — tárolja, és közvetlenül a GPU-n jeleníti meg. Ez lehetővé teszi az alakzat méretezését minőségveszteség nélkül és tulajdonságainak animálását a tartalom újrarajzolása nélkül.
Architekturálisan a CAShapeLayer örökli a CALayer összes képességét: árnyékok, határok, transzformációk, maszkok. De specifikus tulajdonságokat ad hozzá a kontúrokkal való munkához: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd és fillRule. Ezen tulajdonságok mindegyike animálható a CABasicAnimation segítségével.
A Apple Documentation szerint a CAShapeLayer hardveres gyorsítást használ a megjelenítés során. Ellentétben a Core Graphics segítségével történő rajzolással a drawRect:-ben, ahol a CPU raszterkontextusban jeleníti meg a kontúrt, a CAShapeLayer közvetlenül a GPU-nak küld parancsokat a Metal-on keresztül. Eredmény — magasabb teljesítmény, különösen animáció közben.
A CAShapeLayer különösen hasznos azokhoz a felületi elemekhez, amelyek a felhasználói műveletekre reagálva változtatják alakjukat: folyamatjelzők, grafikonok, tab-bar ikonok, maszkok a tartalom megjelenésének animálásához.
A CAShapeLayer megjelenítési folyamata eltér az alap CALayer-től. Ahelyett, hogy raszterbuffert tárolna pixelekkel, a CAShapeLayer a kontúr csúcsleírását küldi a GPU-nak — pontok, Bezier-görbék és szegmensek halmazát. A GPU ezt a kontúrt egyetlen menetben raszterizálja, alkalmazva a kitöltés és a vonal színét a fragment shader fázisában.
Ez a megközelítés két előnyt kínál: méretezés minőségveszteség nélkül (a vektorgrafika bármilyen felbontásban éles marad) és hatékony animáció — a path változásakor a GPU csak a megváltozott pixeleket számolja újra, nem a teljes képernyőt.
path — a CAShapeLayer központi tulajdonsága, amely CGPath-et fogad. A kontúr tartalmazhat vonalakat, íveket, Bezier-görbéket és téglalapokat. Swift-ben UIBezierPath-en vagy Core Graphics-ben CGPath-en keresztül hozható létre. Példa: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath lekerekített téglalapot hoz létre.
A lineDashPattern tulajdonság lehetővé teszi szaggatott vonalak létrehozását. Számok tömbjét fogadja: [6, 3] 6 pont vonalat és 3 pont szóközt jelent. A lineDashPhase a minta eltolását állítja be és animálható a mozgó szaggatott vonal effektusához.
A választás a CAShapeLayer és az alap CALayer között a tartalom típusától függ. Ha az elem egy téglalap alakú terület háttérrel, határral és árnyékkal — a CALayer elegendő. Ha az elem tetszőleges alakú, kontúr animációt vagy minőségveszteség nélküli méretezést igényel — a CAShapeLayer előnyösebb.
A teljesítmény is eltér. A cornerRadius és masksToBounds tulajdonságokkal rendelkező CALayer offscreen buffert hoz létre a tartalom levágásához, ami képkockánként 2–5 ms-ot ad hozzá. A CAShapeLayer nem igényel offscreen buffert — a levágás a vertex shader szintjén történik. Összetett maszkkal rendelkező elemeknél a CAShapeLayer 2–3-szor gyorsabb lehet.
A CAShapeLayer kombinálása más rétegekkel gyakori minta. Például a CAGradientLayer a CAShapeLayer-t használja maszkként egy gradientes kitöltésű alakzat létrehozásához. Ez a megközelítés mind vektoros minőséget, mind gradientes kitöltést biztosít teljesítményveszteség nélkül.
Path animáció — a CAShapeLayer egyik legerősebb képessége. Ha mindkét kontúr (kezdeti és végső) azonos számú vezérlőponttal és szegmenssel rendelkezik, a Core Animation sima interpolációt végez közöttük. Eredmény — az egyik alakzat átalakulásának effektusa a másikba.
A path kompatibilitás feltétele: a kezdeti és végső UIBezierPath azonos szerkezetű kell legyen — a moveTo, addLine, addCurve és addQuadCurve hívások számának egyeznie kell. Ha a szerkezet eltér, az animáció azonnali, interpoláció nélkül történik.
A Apple WWDC 2024 szerint a strokeStart és strokeEnd kombinációja a leggyakrabban használt CAShapeLayer animációs minta. A strokeEnd animációja 0.0-tól 1.0-ig a kontúr elejétől a végéig történő rajzolásának effektusát hozza létre. Ezt használják betöltésjelzőkben, grafikonok megjelenési animációiban és egyéni átmenetekben a képernyők között.
Pulzáló effektus létrehozásához animáld egyszerre a strokeEnd és opacity tulajdonságokat különböző időzítési függvényekkel. A mozgó szaggatott vonal effektusához animáld a lineDashPhase-t fix lineDashPattern mellett. Mindkét technika CABasicAnimation segítségével valósítható meg CPU részvétel nélkül.
A CAShapeLayer gyakran használatos maskként más rétegekhez. Például a tartalom megjelenésének animálásához: kezdetben a mask.path egy nulla méretű téglalap, a végén — teljes méret. A Core Animation interpolálja a path-ot, és a tartalom simán feltárul.
Ezt a mintát iOS-ben használják kártyák kinyílásának, modális ablakok megjelenésének és view controller-ek közötti átmenetek animálására. Az alpha animációval ellentétben a CAShapeLayer maszkon keresztüli animáció természetesebb megjelenési effektust biztosít tetszőleges alakzattal.
Első példa — kör alakú folyamatjelző létrehozása strokeEnd animációval. Ez egy szabványos UI elem, amely bemutatja a CAShapeLayer fő képességeit:
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
}
// Animáció 75%-ig
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
Második példa — animált átalakulás kör és négyzet között. Mindkét UIBezierPath kompatibilis szerkezettel rendelkezik:
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")
Harmadik példa — maszk CAShapeLayer-rel a tartalom megjelenésének animálásához. A maszk a középponttól a szélek felé terjed:
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
}
Gyakran Ismételt Kérdések
drawRect a CPU-t használja a megjelenítéshez raszterkontextusban — ez lassú az animációkhoz. A CAShapeLayer a kontúrt a GPU-n jeleníti meg, ami 60 FPS-t biztosít a path, strokeEnd és transzformációs animációknál. Ezenkívül a CAShapeLayer nem igényel újrarajzolást méretváltozáskor — az alakzat vektorosan méreteződik.
A sima path animáció megköveteli a kezdeti és végső UIBezierPath azonos szerkezetét. A moveTo, addLine, addCurve hívások számának egyeznie kell. Használj azonos számú szegmensű UIBezierPath-et a kezdeti és végső alakzathoz.
Állítsd be a lineDashPattern tulajdonságot — egy számokból álló tömböt, amely felváltva határozza meg a vonal és a szóköz hosszát. Például a [8, 4] 8pt vonalakat hoz létre 4pt szóközökkel. Mozgó szaggatott vonalhoz animáld a lineDashPhase-t CABasicAnimation segítségével lineáris időzítési függvénnyel.
Igen, ez az egyik fő forgatókönyv. Rendeld hozzá a CAShapeLayer-t bármely CALayer mask tulajdonságához, beleértve a CAGradientLayer-t és más alosztályokat. A maszk path animációja a tartalom sima megjelenésének effektusát hozza létre tetszőleges alakzaton keresztül.
Hozz létre egy CAGradientLayer-t és állítsd be a mask tulajdonságát = CAShapeLayer a kívánt path-pal. A gradiens csak a maszk kontúrján belül lesz látható. Ez a minta egyesíti a CAShapeLayer vektoralakzatának előnyeit a CAGradientLayer gradientes kitöltésével.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is