CAShapeLayer — је подкласа CALayer-а намењена хардверском рендеровању векторских контура на GPU-у. За разлику од основног CALayer-а, који ради са растерским сликама преко contents, CAShapeLayer рендерује произвољне облике задате кроз CGPath без креирања засебног offscreen бафера. Према Apple QuartzCore Documentation, 2025, CAShapeLayer користи хардверско убрзање за заглађивање ивица и подржава анимацију path, strokeStart и strokeEnd. Ово је стандардни алат за креирање икона, индикатора напретка и маски у iOS-у.
Главно
CAShapeLayer — је специјализовани слој за рендеровање векторске графике, представљен у iOS 3.0. За разлику од CALayer-а, који чува растерску слику, CAShapeLayer чува математички опис контуре — CGPath — и рендерује је директно на GPU-у. Ово омогућава скалирање облика без губитка квалитета и анимирање његових својстава без прецртавања садржаја.
Архитектонски, CAShapeLayer наслеђује све могућности CALayer-а: сенке, границе, трансформације, маске. Али додаје специфична својства за рад са контурама: path, fillColor, strokeColor, lineWidth, lineCap, lineJoin, miterLimit, strokeStart, strokeEnd и fillRule. Свако од ових својстава може бити анимирано кроз CABasicAnimation.
Према Apple Documentation, CAShapeLayer користи хардверско убрзање при рендеровању. За разлику од цртања кроз Core Graphics у drawRect:, где CPU рендерује контуру у растерском контексту, CAShapeLayer шаље команде директно на GPU преко Metal-а. Резултат — веће перформансе, посебно током анимације.
CAShapeLayer је посебно користан за елементе интерфејса који мењају облик као одговор на радње корисника: индикатори напретка, графикони, иконе таб-бара, маске за анимацију појављивања садржаја.
Процес рендеровања CAShapeLayer-а се разликује од основног CALayer-а. Уместо чувања растерског бафера са пикселима, CAShapeLayer шаље GPU-у опис темена контуре — скуп тачака, Безијеових кривих и сегмената. GPU растеризује ову контуру у једном пролазу, примењујући боју попуне и контуре у фази фрагментног шејдера.
Овај приступ даје две предности: скалирање без губитка квалитета (векторска графика остаје оштра при било којој резолуцији) и ефикасну анимацију — при промени path GPU прерачунава само измењене пикселе, не цео екран.
path — централно својство CAShapeLayer-а, које прима CGPath. Контура може садржати линије, лукове, Безијеове криве и правоугаонике. Креира се кроз UIBezierPath у Swift-у или CGPath у Core Graphics-у. Пример: UIBezierPath(roundedRect: rect, cornerRadius: 16).cgPath креира заобљени правоугаоник.
Својство lineDashPattern омогућава креирање испрекиданих линија. Прима низ бројева: [6, 3] значи 6 тачака црте и 3 тачке размака. lineDashPhase поставља померај шаблона и може се анимирати за ефекат покретне испрекидане линије.
Избор између CAShapeLayer и основног CALayer-а зависи од типа садржаја. Ако је елемент правоугаона област са позадином, границом и сенком — довољан је CALayer. Ако елемент има произвољан облик, захтева анимацију контуре или скалирање без губитка квалитета — CAShapeLayer је пожељнији.
Перформансе се такође разликују. CALayer са cornerRadius и masksToBounds ствара offscreen бафер за обрезивање садржаја, што додаје 2–5 ms по кадру. CAShapeLayer не захтева offscreen бафер — обрезивање се врши на нивоу теменог шејдера. За елементе са сложеном маском, CAShapeLayer може бити 2–3 пута бржи.
Комбиновање CAShapeLayer-а са другим слојевима је уобичајен образац. На пример, CAGradientLayer користи CAShapeLayer као маску за креирање облика са градијентном попуном. Овај приступ даје и векторски квалитет и градијентну попуну без губитка перформанси.
Анимација path — једна од најмоћнијих могућности CAShapeLayer-а. Ако обе контуре (почетна и крајња) имају исти број контролних тачака и сегмената, Core Animation врши глатку интерполацију између њих. Резултат — ефекат морфинга једног облика у други.
Услов компатибилности path: почетни и крајњи UIBezierPath морају имати исту структуру — број позива moveTo, addLine, addCurve и addQuadCurve мора да се поклапа. Ако се структура разликује, анимација ће бити тренутна, без интерполације.
Према Apple WWDC 2024, комбинација strokeStart и strokeEnd је најчешће коришћени образац анимације CAShapeLayer-а. Анимација strokeEnd од 0.0 до 1.0 ствара ефекат цртања контуре од почетка до краја. Користи се у индикаторима учитавања, анимацијама појављивања графикона и прилагођеним транзицијама између екрана.
За стварање ефекта пулсирања, анимирај истовремено strokeEnd и opacity са различитим timing функцијама. За ефекат покретне испрекидане линије, анимирај lineDashPhase уз фиксни lineDashPattern. Оба трика се реализују кроз CABasicAnimation без учешћа CPU-а.
CAShapeLayer се често користи као mask за друге слојеве. На пример, за анимацију појављивања садржаја: на почетку mask.path је правоугаоник нулте величине, крајњи — пуна величина. Core Animation интерполира path, и садржај се открива глатко.
Овај образац се користи у iOS-у за анимацију размотавања картица, појављивања модалних прозора и транзиција између view controller-а. За разлику од анимације alpha, анимација кроз маску CAShapeLayer-а даје природнији ефекат појављивања са произвољним обликом.
Први пример — креирање кружног индикатора напретка са анимацијом strokeEnd. Ово је стандардни UI елемент који демонстрира основне могућности 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
}
// Анимирај до 75%
progressLayer.animateStrokeEnd(to: 0.75, duration: 1.5)
Други пример — анимација морфинга између круга и квадрата. Оба UIBezierPath имају компатибилну структуру:
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")
Трећи пример — маска са CAShapeLayer-ом за анимацију појављивања садржаја. Маска се шири од центра ка ивицама:
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
}
Често постављана питања
drawRect користи CPU за рендеровање у растерском контексту — споро је за анимације. CAShapeLayer рендерује контуру на GPU-у, што даје 60 FPS при анимацији path, strokeEnd и трансформација. Поред тога, CAShapeLayer не захтева прецртавање при промени величине — облик се скалира векторски.
Глатка анимација path захтева исту структуру почетног и крајњег UIBezierPath-а. Број позива moveTo, addLine, addCurve мора да се поклапа. Користи UIBezierPath са истим бројем сегмената за почетни и крајњи облик.
Постави lineDashPattern — низ бројева који наизменично одређују дужину црте и размака. На пример, [8, 4] ствара црте од 8pt са размацима од 4pt. За покретну испрекидану линију, анимирај lineDashPhase кроз CABasicAnimation са линеарном timing функцијом.
Да, ово је један од основних сценарија. Додели CAShapeLayer својству mask било ког CALayer-а, укључујући CAGradientLayer и друге подкласе. Анимација path маске ствара ефекат глатког појављивања садржаја кроз облик произвољне форме.
Креирај CAGradientLayer и постави његов mask = CAShapeLayer са жељеним path-ем. Градијент ће бити видљив само унутар контуре маске. Овај образац комбинује предности векторског облика CAShapeLayer-а и градијентне попуне CAGradientLayer-а.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође