Core Animation: základy, CALayer a animace v iOS

Autor: IT Sectr Publikováno: 2026-03-01 Doba čtení: 8 min

Core Animation je nízkoúrovňový animační framework Apple, pracující na úrovni CALayer a zajišťující vykreslování obsahu na GPU. Core Animation je základem všech animací v iOS a macOS: UIKit, AppKit, SceneKit a SpriteKit jsou postaveny na něm. Článek vysvětluje architekturu CALayer, CABasicAnimation, CATransaction a praktické techniky.

Hlavní body

  • CALayer základní třída Core Animation pro správu zobrazení obsahu na GPU
  • CABasicAnimation jednoduchá animace jedné vlastnosti CALayer od fromValue do toValue
  • CATransaction seskupení animací do jedné transakce se společnými duration a completion
  • CAAnimation abstraktní základní třída, ze které dědí CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup
  • Render server samostatný proces (backboardd) interpolující snímky animace na GPU

Co je Core Animation?

Core Animation je grafický framework Apple, který se objevil v Mac OS X 10.5 Leopard (2007) a byl portován na iOS od první verze iPhone OS (2007). Core Animation spravuje kompozici, animaci a vykreslování vrstev (CALayer) na GPU. Každý UIView v iOS má vestavěný CALayer (view.layer), přes který probíhá veškeré vykreslování.

Core Animation pracuje na principu implicit animation: některé změny vlastností CALayer jsou animovány automaticky (animuje CABasicAnimation pro position, bounds, opacity, backgroundColor). Implicit-animace standardně používají CATransaction s délkou 0.25 sekundy a křivkou easeInOut.

Podle dat Apple WWDC 2024 zpracovává Core Animation až 120 FPS na zařízeních s ProMotion, využívajících Metal pro GPU vykreslování. Velikost typické vrstvy v paměti je 4 bajty na pixel (RGBA) + režie ~100 bajtů na vrstvu. Pro stabilních 60 FPS se doporučuje maximálně 1000 vrstev na obrazovku.

Architektura CALayer

CALayer základ Core Animation. Každý CALayer obsahuje bitmapový obsah (nebo odkaz na GPU texturu) a definuje geometrii (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). Vrstva nezpracovává dotykové události o to se stará UIView/UIScrollView. Vrstvy tvoří hierarchii (layer tree) zrcadlící hierarchii pohledů.

Core Animation podporuje tři stromy vrstev: model layer tree (skutečné vlastnosti), presentation layer tree (aktuální zobrazení během animace) a render tree (data pro GPU). Presentation layer se používá pro čtení průběžných hodnot animace v reálném čase.

Typy CALayer

CALayer má specializované podtřídy: CAShapeLayer (vektorová grafika), CAGradientLayer (gradient), CATextLayer (text), CATiledLayer (velké obrázky rozdělené na dlaždice), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer je nejoblíbenější pro vlastní animace díky podpoře CGPath a animace strokeStart/strokeEnd.

CABasicAnimation základní animace vlastností

CABasicAnimation je podtřída CAAnimation animující jednu vlastnost CALayer od počáteční hodnoty (fromValue) do konečné hodnoty (toValue) nebo relativní změny (byValue). Animace je přidána k vrstvě metodou layer.add(animation, forKey:) a provádí se v render serveru bez účasti aplikace na každém snímku.

Klíč (keyPath) je řetězec ukazující na vlastnost: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity atd. Core Animation podporuje 60+ animovatelných keyPath. Pro vlastní vlastnosti se používají CATransaction a presentation layer.

swift
import QuartzCore

// CABasicAnimation pro opacity a cornerRadius
func animateLayer() {
    let layer = CALayer()
    layer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
    layer.backgroundColor = UIColor.systemBlue.cgColor
    view.layer.addSublayer(layer)

    // 1. Animace průhlednosti
    let fadeAnim = CABasicAnimation(keyPath: "opacity")
    fadeAnim.fromValue = 1.0
    fadeAnim.toValue = 0.2
    fadeAnim.duration = 2.0
    fadeAnim.autoreverses = true
    fadeAnim.repeatCount = .infinity

    // 2. Animace zaoblení rohů
    let cornerAnim = CABasicAnimation(keyPath: "cornerRadius")
    cornerAnim.fromValue = 0
    cornerAnim.toValue = 50
    cornerAnim.duration = 2.0
    cornerAnim.autoreverses = true
    cornerAnim.repeatCount = .infinity

    layer.add(fadeAnim, forKey: "fade")
    layer.add(cornerAnim, forKey: "corner")
}

// Animace position s ease-in-out
func moveLayer(_ layer: CALayer, to point: CGPoint) {
    let anim = CABasicAnimation(keyPath: "position")
    anim.fromValue = NSValue(cgPoint: layer.position)
    anim.toValue = NSValue(cgPoint: point)
    anim.duration = 0.6
    anim.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
    anim.isRemovedOnCompletion = false
    anim.fillMode = .forwards
    layer.add(anim, forKey: "move")
    layer.position = point // aktualizujeme model layer
}

Důležité: CABasicAnimation je dočasné zobrazení (presentation layer). Po dokončení animace se vrstva vrátí k původním hodnotám model layer. Pro upevnění konečného stavu nastavte isRemovedOnCompletion = false, fillMode = .forwards a aktualizujte model layer na konečné hodnoty.

CATransaction seskupení animací

CATransaction je mechanismus pro seskupování Core Animation animací do jedné transakce. CATransaction.begin() a CATransaction.commit() definují hranice transakce. Uvnitř transakce lze nastavit společné parametry: duration, timingFunction, completionBlock, disableActions. CATransaction je základem implicit-animací CALayer.

Implicit animation funguje, když je vlastnost CALayer změněna mimo blok animace: layer.opacity = 0.5. Core Animation automaticky vytvoří CABasicAnimation s duration z aktuálního CATransaction (výchozí 0.25 s). Pro vypnutí implicit-animace použijte CATransaction.setDisableActions(true).

swift
// CATransaction seskupení a dokončení
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // Všechny změny uvnitř transakce jsou animovány s duration 1.5
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// Vypnutí implicit-animace
func updateWithoutAnimation() {
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.frame = newFrame // bez animace
    CATransaction.commit()
}

// Animace vlastností CAShapeLayer
func animateProgress(percentage: CGFloat) {
    CATransaction.begin()
    CATransaction.setAnimationDuration(0.8)
    CATransaction.setCompletionBlock {
        print("Progress updated to (percentage)%")
    }
    progressLayer.strokeEnd = percentage / 100.0
    CATransaction.commit()
}

Příklady kódu ve Swift

Core Animation se integruje s UIKit přes vrstvu UIView. Níže uvedený příklad demonstruje animaci CAShapeLayer kruhový ukazatel průběhu s animací délky oblouku a rotací vrstvy přes CABasicAnimation.

swift
import UIKit
import QuartzCore

class CircularProgressView: UIView {

    private let progressLayer = CAShapeLayer()

    override func layoutSubviews() {
        super.layoutSubviews()

        let path = UIBezierPath(
            arcCenter: CGPoint(x: bounds.midX, y: bounds.midY),
            radius: bounds.width / 2 - 10,
            startAngle: -.pi / 2,
            endAngle: 3 * .pi / 2,
            clockwise: true
        )

        progressLayer.path = path.cgPath
        progressLayer.strokeColor = UIColor.systemBlue.cgColor
        progressLayer.lineWidth = 8
        progressLayer.fillColor = nil
        progressLayer.strokeEnd = 0
        progressLayer.lineCap = .round
        layer.addSublayer(progressLayer)
    }

    func setProgress(_ value: CGFloat, animated: Bool = true) {
        if animated {
            CATransaction.begin()
            CATransaction.setAnimationDuration(0.6)
            CATransaction.setAnimationTimingFunction(
                CAMediaTimingFunction(name: .easeOut)
            )
            progressLayer.strokeEnd = min(max(value, 0), 1)
            CATransaction.commit()
        } else {
            progressLayer.strokeEnd = value
        }
    }
}

CAShapeLayer animuje vlastnost strokeEnd od 0 do 1, čímž vytváří efekt „naplnění“ kruhového ukazatele průběhu. CATransaction s délkou 0.6 a easeOut činí animaci plynulou. layer.lineCap = .round přidává zaoblené konce čáry pro úhlednější vzhled.

Často kladené otázky

Jaký je rozdíl mezi Core Animation a UIView.animate?

Core Animation pracuje na úrovni CALayer a je řízena přes CABasicAnimation, CATransaction. UIView.animate je vysokoúrovňový obal nad Core Animation, automaticky vytvářející CABasicAnimation pro vlastnosti UIView. Core Animation poskytuje větší kontrolu: keyPath, timingFunction, fillMode, seskupení přes CATransaction.

Co je implicit animation v Core Animation?

Implicit animation je automatická animace při změně animovatelné vlastnosti CALayer mimo blok animace. Například layer.opacity = 0.5 vytvoří CABasicAnimation s délkou 0.25 s. Implicit-animace jsou řízeny přes CATransaction a vypínají se přes setDisableActions(true).

Jak animovat vlastní vlastnost CALayer?

Pro vlastní vlastnosti implementujte action(forKey:) v CALayer a vraťte CAAnimation. Nebo použijte CALayer.display() pro ruční vykreslování s animací přes CADisplayLink. Pro vlastnosti podporující CABasicAnimation stačí uvést keyPath jako řetězec.

Proč je CALayer efektivnější než UIView pro animaci?

CALayer je lehčí než UIView: nemá obsluhy událostí (touches, gesta), neúčastní se Auto Layout a nepodporuje accessibility. Typický CALayer zabírá ~100 bajtů oproti ~300+ u UIView. Core Animation zpracovává vrstvy v render serveru na GPU bez blokování main thread.

Shrnutí

  • Core Animation nízkoúrovňový Apple framework pro animaci CALayer s vykreslováním na GPU
  • CALayer základní třída s 60+ animovatelnými vlastnostmi, podporuje CAShapeLayer, CAGradientLayer, CATextLayer
  • CABasicAnimation animace jedné vlastnosti s fromValue/toValue, přidána přes layer.add(animation, forKey:)
  • CATransaction seskupení animací se společnými duration, timingFunction, completionBlock
  • Implicit animation automatická animace při změně vlastností CALayer (délka 0.25 s)
  • Presentation layer aktuální stav vrstvy během animace, používá se pro čtení průběžných hodnot
  • Výkon až 120 FPS na ProMotion, až 1000 vrstev při 60 FPS, 4 bajty/pixel

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í.

Prodiskutovat projekt

Přečtěte si také