Core Animation: basisbeginselen, CALayer en animatie in iOS

Auteur: IT Sectr Gepubliceerd: 2026-03-01 Leestijd: 8 min

Core Animation is een low-level animatieframework van Apple dat op CALayer-niveau werkt en het renderen van inhoud op de GPU verzorgt. Core Animation vormt de basis van alle animaties in iOS en macOS: UIKit, AppKit, SceneKit en SpriteKit zijn erop gebouwd. Het artikel legt de architectuur van CALayer, CABasicAnimation, CATransaction en praktische technieken uit.

Belangrijkste punten

  • CALayer de basisklasse van Core Animation voor het beheren van inhoudsweergave op de GPU
  • CABasicAnimation eenvoudige animatie van een CALayer-eigenschap van fromValue naar toValue
  • CATransaction groepering van animaties in een transactie met gedeelde duration en completion
  • CAAnimation abstracte basisklasse waarvan CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup overerven
  • Render server apart proces (backboardd) dat animatieframes op de GPU interpoleert

Wat is Core Animation?

Core Animation is een grafisch framework van Apple dat verscheen in Mac OS X 10.5 Leopard (2007) en werd overgezet naar iOS vanaf de eerste versie van iPhone OS (2007). Core Animation beheert de compositie, animatie en weergave van lagen (CALayer) op de GPU. Elke UIView in iOS heeft een ingebouwde CALayer (view.layer) waarlangs alle weergave plaatsvindt.

Core Animation werkt volgens het principe van implicit animation: sommige wijzigingen van CALayer-eigenschappen worden automatisch geanimeerd (animeert CABasicAnimation voor position, bounds, opacity, backgroundColor). Implicit-animaties gebruiken standaard CATransaction met een duur van 0.25 seconden en de easeInOut-curve.

Volgens gegevens van Apple WWDC 2024 verwerkt Core Animation tot 120 FPS op ProMotion-apparaten, met Metal voor GPU-rendering. De grootte van een typische laag in het geheugen is 4 bytes per pixel (RGBA) + overhead ~100 bytes per laag. Aanbevolen wordt niet meer dan 1000 lagen per scherm voor stabiele 60 FPS.

CALayer-architectuur

CALayer de basis van Core Animation. Elke CALayer bevat bitmap-inhoud (of een verwijzing naar een GPU-textuur) en definieert de geometrie (bounds, position, anchorPoint, transform, cornerRadius, borderWidth, shadow). De laag verwerkt geen aanraakgebeurtenissen daarvoor zorgt UIView/UIScrollView. Lagen vormen een hiërarchie (layer tree) die de view-hiërarchie weerspiegelt.

Core Animation ondersteunt drie laagbomen: model layer tree (werkelijke eigenschappen), presentation layer tree (huidige weergave tijdens animatie) en render tree (gegevens voor de GPU). Presentation layer wordt gebruikt om tussenliggende animatiewaarden in realtime uit te lezen.

Typen CALayer

CALayer heeft gespecialiseerde subklassen: CAShapeLayer (vectorafbeeldingen), CAGradientLayer (verloop), CATextLayer (tekst), CATiledLayer (grote afbeeldingen verdeeld in tegels), CAEAGLLayer/MetalLayer (OpenGL/Metal). CAShapeLayer is het populairst voor aangepaste animatie dankzij ondersteuning voor CGPath en animatie van strokeStart/strokeEnd.

CABasicAnimation basisanimatie van eigenschappen

CABasicAnimation is een subklasse van CAAnimation die één CALayer-eigenschap animeert van de beginwaarde (fromValue) naar de eindwaarde (toValue) of relatieve verandering (byValue). De animatie wordt aan de laag toegevoegd via de methode layer.add(animation, forKey:) en wordt uitgevoerd in de render server zonder tussenkomst van de applicatie op elk frame.

De sleutel (keyPath) is een tekenreeks die naar de eigenschap verwijst: opacity, position, bounds, transform.rotation.z, cornerRadius, shadowOpacity enz. Core Animation ondersteunt 60+ animeerbare keyPath's. Voor aangepaste eigenschappen worden CATransaction en presentation layer gebruikt.

swift
import QuartzCore

// CABasicAnimation voor opacity en 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. Animatie van doorzichtigheid
    let fadeAnim = CABasicAnimation(keyPath: "opacity")
    fadeAnim.fromValue = 1.0
    fadeAnim.toValue = 0.2
    fadeAnim.duration = 2.0
    fadeAnim.autoreverses = true
    fadeAnim.repeatCount = .infinity

    // 2. Animatie van afronding van hoeken
    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")
}

// Animatie van position met 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 // model layer bijwerken
}

Belangrijk: CABasicAnimation is een tijdelijke weergave (presentation layer). Na afloop van de animatie keert de laag terug naar de oorspronkelijke waarden van de model layer. Om de eindtoestand vast te zetten, stelt u isRemovedOnCompletion = false, fillMode = .forwards in en werkt u de model layer bij naar de eindwaarden.

CATransaction groeperen van animaties

CATransaction is een mechanisme voor het groeperen van Core Animation-animaties in een enkele transactie. CATransaction.begin() en CATransaction.commit() bepalen de grenzen van de transactie. Binnen de transactie kunnen gemeenschappelijke parameters worden ingesteld: duration, timingFunction, completionBlock, disableActions. CATransaction vormt de basis van implicit-animaties van CALayer.

Implicit animation werkt wanneer een CALayer-eigenschap buiten het animatieblok wordt gewijzigd: layer.opacity = 0.5. Core Animation maakt automatisch CABasicAnimation met duration uit de huidige CATransaction (standaard 0.25 s). Gebruik CATransaction.setDisableActions(true) om implicit-animatie uit te schakelen.

swift
// CATransaction groepering en voltooiing
func groupedAnimation() {
    CATransaction.begin()
    CATransaction.setAnimationDuration(1.5)
    CATransaction.setAnimationTimingFunction(
        CAMediaTimingFunction(name: .easeOut)
    )
    CATransaction.setCompletionBlock {
        print("All animations completed")
    }

    // Alle wijzigingen binnen de transactie worden geanimeerd met duration 1.5
    layer1.opacity = 0.3
    layer2.position = CGPoint(x: 200, y: 300)
    layer3.backgroundColor = UIColor.systemRed.cgColor

    CATransaction.commit()
}

// Uitschakelen van implicit-animatie
func updateWithoutAnimation() {
    CATransaction.begin()
    CATransaction.setDisableActions(true)
    layer.frame = newFrame // zonder animatie
    CATransaction.commit()
}

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

Codevoorbeelden in Swift

Core Animation integreert met UIKit via de UIView-laag. Het onderstaande voorbeeld demonstreert animatie van CAShapeLayer een cirkelvormige voortgangsbalk met animatie van de booglengte en rotatie van de laag via 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 animeert de eigenschap strokeEnd van 0 tot 1, waardoor het effect van het „vullen“ van de cirkelvormige voortgangsbalk ontstaat. CATransaction met een duur van 0.6 en easeOut maakt de animatie vloeiend. layer.lineCap = .round voegt afgeronde uiteinden toe aan de lijn voor een nettere uitstraling.

Veelgestelde vragen

Wat is het verschil tussen Core Animation en UIView.animate?

Core Animation werkt op CALayer-niveau en wordt beheerd via CABasicAnimation, CATransaction. UIView.animate is een wrapper op hoog niveau boven Core Animation die automatisch CABasicAnimation maakt voor UIView-eigenschappen. Core Animation biedt meer controle: keyPath, timingFunction, fillMode, groepering via CATransaction.

Wat is implicit animation in Core Animation?

Implicit animation is automatische animatie bij het wijzigen van een animeerbare CALayer-eigenschap buiten het animatieblok. Bijvoorbeeld layer.opacity = 0.5 maakt CABasicAnimation met een duur van 0.25 s. Implicit-animaties worden beheerd via CATransaction en uitgeschakeld via setDisableActions(true).

Hoe animeer je een aangepaste CALayer-eigenschap?

Implementeer voor aangepaste eigenschappen action(forKey:) in CALayer en retourneer CAAnimation. Of gebruik CALayer.display() voor handmatig renderen met animatie via CADisplayLink. Voor eigenschappen die CABasicAnimation ondersteunen, volstaat het om keyPath als tekenreeks op te geven.

Waarom is CALayer efficiënter dan UIView voor animatie?

CALayer is lichter dan UIView: het heeft geen gebeurtenisafhandelaars (touches, gebaren), neemt niet deel aan Auto Layout en ondersteunt geen accessibility. Een typische CALayer neemt ~100 bytes in beslag versus ~300+ voor UIView. Core Animation verwerkt lagen in de render server op de GPU zonder de main thread te blokkeren.

Samenvatting

  • Core Animation low-level Apple-framework voor CALayer-animatie met weergave op de GPU
  • CALayer basisklasse met 60+ animeerbare eigenschappen, ondersteunt CAShapeLayer, CAGradientLayer, CATextLayer
  • CABasicAnimation animatie van één eigenschap met fromValue/toValue, toegevoegd via layer.add(animation, forKey:)
  • CATransaction groepering van animaties met gedeelde duration, timingFunction, completionBlock
  • Implicit animation automatische animatie bij wijziging van CALayer-eigenschappen (duur 0.25 s)
  • Presentation layer huidige staat van de laag tijdens animatie, gebruikt voor het uitlezen van tussenliggende waarden
  • Prestaties tot 120 FPS op ProMotion, tot 1000 lagen bij 60 FPS, 4 bytes/pixel

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook