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
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 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.
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 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.
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 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.
// 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()
}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.
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
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.
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).
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.
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
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.
Lees ook