CAAnimation — abstrakcyjna klasa bazowa Core Animation, definiująca wspólny interfejs dla wszystkich typów animacji: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition. Artykuł wyjaśnia hierarchię klas, kluczowe właściwości, grupowanie animacji i praktyczne przykłady w Swift.
Najważniejsze
CAAnimation — abstrakcyjna klasa Core Animation, definiująca wspólny interfejs dla wszystkich animacji. Implementuje protokół CAMediaTiming (czas, powtórzenia, automatyczne odwrócenie) i CAMediaTimingFillMode (zachowanie przed/po animacji). CAAnimation nie może być instancjonowana bezpośrednio — użyj jednej z podklas: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition lub CAAnimation (przez animationForKeyPath).
Każda CAAnimation jest dodawana do CALayer przez metodę add(_:forKey:). Parametr forKey to unikalny identyfikator animacji na warstwie. Ten sam keyPath może mieć tylko jedną aktywną animację. Aby zastąpić animację, użyj removeAnimation(forKey:) przed dodaniem nowej.
Według Apple, CAAnimation to „tymczasowa” (temporary) zmiana warstwy. Po zakończeniu animacji presentation layer wraca do wartości model layer, jeśli nie ustawiono fillMode i isRemovedOnCompletion.
Core Animation udostępnia cztery główne podklasy CAAnimation, każda dla swojego scenariusza animacji. Zrozumienie hierarchii pomaga wybrać odpowiedni typ dla zadania.
| Klasa | Przeznaczenie | Kluczowe cechy |
|---|---|---|
| CABasicAnimation | Animacja jednej właściwości od A do B | fromValue, toValue, byValue, keyPath |
| CAKeyframeAnimation | Animacja po kilku klatkach kluczowych | values, keyTimes, path, calculationMode |
| CAAnimationGroup | Grupowanie wielu animacji | animations tablica, jednolity duration |
| CATransition | Przejście między stanami warstwy | type (fade/push/moveIn/reveal), subtype, startProgress |
CABasicAnimation — najprostsza i najpopularniejsza podklasa. CAKeyframeAnimation jest używana do złożonych trajektorii (np. ruch po krzywej Béziera). CAAnimationGroup uruchamia wiele animacji równolegle. CATransition — gotowe przejście między obrazami lub stanami zawartości.
Protokół CAMediaTiming — fundamentalna część CAAnimation. Określa podstawowe właściwości czasowe: duration (czas trwania), repeatCount (liczba powtórzeń), repeatDuration (całkowity czas powtórzeń), autoreverses (powrót do początku), beginTime (czas startu względem rodzica), timeOffset (przesunięcie w obrębie jednego cyklu), speed (prędkość odtwarzania).
Właściwość fillMode (CAMediaTimingFillMode) określa wyświetlanie warstwy przed (backwards) i po (forwards) animacji. Wartości: removed (domyślnie — powrót do model layer), forwards (pozostaje w stanie końcowym), backwards (wyświetla stan początkowy przed startem), both (łączy oba zachowania). fillMode działa tylko gdy isRemovedOnCompletion = false.
CAAnimation dziedziczy CAMediaTiming i może być zagnieżdżona w animacji nadrzędnej (CAAnimationGroup). W tym przypadku beginTime jest obliczany względem początku rodzica, a duration jest ograniczone przez rodzicielskie. Speed = 2.0 przyspiesza animację dwukrotnie.
CAAnimationGroup łączy wiele CAAnimation w jedną grupę. Wszystkie animacje podrzędne uruchamiają się równolegle, jeśli nie ustawiono beginTime dla każdej. Grupa ma własny duration, który ogranicza maksymalny czas trwania animacji podrzędnych. timingFunction grupy jest stosowany jako wartość domyślna, jeśli animacja podrzędna nie ustawiła własnej.
CAKeyframeAnimation animuje właściwość przez wiele klatek kluczowych, określonych tablicą values. Parametr keyTimes (tablica NSNumber od 0 do 1) określa znaczniki czasowe dla każdej klatki. calculationMode określa interpolację: linear, discrete (bez interpolacji), paced (jednostajna prędkość), cubic (krzywa sklejana), cubicPaced.
import QuartzCore
// CAAnimationGroup — kombinacja animacji
func complexLayerAnimation(_ layer: CALayer) {
let fade = CABasicAnimation(keyPath: "opacity")
fade.fromValue = 1.0
fade.toValue = 0.3
let scale = CABasicAnimation(keyPath: "transform.scale")
scale.fromValue = 1.0
scale.toValue = 1.5
let rotate = CABasicAnimation(keyPath: "transform.rotation.z")
rotate.fromValue = 0
rotate.toValue = Double.pi * 2
let group = CAAnimationGroup()
group.animations = [fade, scale, rotate]
group.duration = 2.0
group.repeatCount = .infinity
group.autoreverses = true
layer.add(group, forKey: "pulse")
}
// CAKeyframeAnimation — ruch po trajektorii
func animateAlongPath(_ layer: CALayer) {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: 0))
path.addCurve(
to: CGPoint(x: 200, y: 300),
controlPoint1: CGPoint(x: 100, y: 0),
controlPoint2: CGPoint(x: 100, y: 300)
)
let anim = CAKeyframeAnimation(keyPath: "position")
anim.path = path.cgPath
anim.duration = 1.5
anim.calculationMode = .cubicPaced
anim.rotationMode = .auto
anim.fillMode = .forwards
anim.isRemovedOnCompletion = false
layer.add(anim, forKey: "pathAnim")
layer.position = CGPoint(x: 200, y: 300)
}
// CAKeyframeAnimation z niestandardowymi wartościami
func bounceAnimation(_ layer: CALayer) {
let bounce = CAKeyframeAnimation(keyPath: "position.y")
bounce.values = [0, -50, 0, -25, 0, -10, 0]
bounce.keyTimes = [0, 0.15, 0.3, 0.45, 0.6, 0.8, 1.0]
bounce.duration = 0.8
bounce.timingFunction = CAMediaTimingFunction(name: .easeOut)
bounce.isAdditive = true // względem bieżącej pozycji
layer.add(bounce, forKey: nil)
}CAAnimationGroup wykonuje fade, scale i rotate równolegle z duration 2.0. CAKeyframeAnimation z path i calculationMode = .cubicPaced zapewnia jednostajny ruch wzdłuż krzywej Béziera z automatycznym obrotem (rotationMode = .auto). bounceAnimation używa isAdditive do względnego przesunięcia.
Pełny przykład CAAnimation dla złożonej animacji warstwy z użyciem CATransition do zmiany zawartości i CAAnimationGroup do pulsacji.
import UIKit
import QuartzCore
class AnimationDemoView: UIView {
private let demoLayer = CALayer()
private var currentColor: CGColor = UIColor.systemBlue.cgColor
override func layoutSubviews() {
super.layoutSubviews()
demoLayer.frame = CGRect(x: bounds.midX - 40, y: bounds.midY - 40,
width: 80, height: 80)
demoLayer.backgroundColor = currentColor
demoLayer.cornerRadius = 12
layer.addSublayer(demoLayer)
}
func animateTransition() {
// CATransition — przejście między stanami
let transition = CATransition()
transition.type = .fade
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
demoLayer.add(transition, forKey: nil)
// Zmieniamy zawartość przez transakcję
currentColor = currentColor == UIColor.systemBlue.cgColor
? UIColor.systemRed.cgColor
: UIColor.systemBlue.cgColor
demoLayer.backgroundColor = currentColor
}
func startPulse() {
let scaleUp = CABasicAnimation(keyPath: "transform.scale")
scaleUp.fromValue = 1.0
scaleUp.toValue = 1.3
let fadeOut = CABasicAnimation(keyPath: "opacity")
fadeOut.fromValue = 1.0
fadeOut.toValue = 0.6
let glow = CABasicAnimation(keyPath: "shadowOpacity")
glow.fromValue = 0.0
glow.toValue = 0.8
let group = CAAnimationGroup()
group.animations = [scaleUp, fadeOut, glow]
group.duration = 1.2
group.autoreverses = true
group.repeatCount = .infinity
group.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
demoLayer.add(group, forKey: "pulse")
}
func stopAnimations() {
demoLayer.removeAllAnimations()
demoLayer.transform = CATransform3DIdentity
demoLayer.opacity = 1.0
demoLayer.shadowOpacity = 0.0
}
}CATransition z type: .fade tworzy płynne przejście między dwoma stanami backgroundColor. CAAnimationGroup łączy scale, opacity i shadowOpacity dla efektu pulsacji. removeAllAnimations() resetuje wszystkie animacje i przywraca warstwę do początkowych wartości model layer.
Często zadawane pytania
CABasicAnimation animuje właściwość od wartości początkowej (fromValue) do końcowej (toValue) z jednostajną interpolacją. CAKeyframeAnimation pozwala określić tablicę wartości pośrednich (values) i znaczników czasowych (keyTimes) dla nieliniowej animacji klatkowej, w tym ruch po krzywej przez path.
CAAnimationGroup jest potrzebny, gdy wiele animacji ma być wykonywanych równolegle z gwarancją synchronizacji: grupowy duration ogranicza wszystkie animacje podrzędne. Używaj grupy do łącznych efektów: skalowanie + zmiana przezroczystości + obrót jednocześnie.
fillMode określa wyświetlanie warstwy przed (backwards) i po (forwards) animacji. Wartość .forwards pozostawia warstwę w stanie końcowym po zakończeniu animacji (wymaga isRemovedOnCompletion = false). .both łączy backwards (stan początkowy przed startem) i forwards.
CAAnimation — to obiekt animacji (instrukcja), który jest dodawany do CALayer przez layer.add(animation, forKey:). Animacja istnieje jako oddzielny obiekt, może być ponownie użyta (z kopiowaniem) i zarządzana przez CAMediaTiming. Warstwa może mieć wiele animacji z różnymi kluczami.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również