CAAnimation — абстрактен базов клас на Core Animation, който дефинира общ интерфейс за всички типове анимации: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition. Статията обяснява йерархията на класовете, ключовите свойства, групирането на анимации и практически примери в Swift.
Основни
CAAnimation — абстрактен клас Core Animation, който дефинира общ интерфейс за всички анимации. Той имплементира протокола CAMediaTiming (време, повторение, автоматично връщане) и CAMediaTimingFillMode (поведение преди/след анимация). CAAnimation не може да бъде инстанцииран директно — използвайте един от подкласовете: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition или CAAnimation (чрез animationForKeyPath).
Всяка CAAnimation се добавя към CALayer чрез метода add(_:forKey:). Параметърът forKey е уникален идентификатор на анимацията върху слоя. Един и същ keyPath може да има само една активна анимация. За да замените анимация, използвайте removeAnimation(forKey:) преди добавяне на нова.
Според Apple, CAAnimation е временна промяна на слоя. След завършване на анимацията presentation layer се връща към стойностите на model layer, ако не са зададени fillMode и isRemovedOnCompletion.
Core Animation предоставя четири основни подкласа на CAAnimation, всеки за свой собствен сценарий на анимация. Разбирането на йерархията помага да изберете правилния тип за задачата.
| Клас | Предназначение | Ключови характеристики |
|---|---|---|
| CABasicAnimation | Анимация на едно свойство от A до B | fromValue, toValue, byValue, keyPath |
| CAKeyframeAnimation | Анимация по множество ключови кадри | values, keyTimes, path, calculationMode |
| CAAnimationGroup | Групиране на множество анимации | масив animations, единен duration |
| CATransition | Преход между състояния на слоя | type (fade/push/moveIn/reveal), subtype, startProgress |
CABasicAnimation — най-простият и популярен подклас. CAKeyframeAnimation се използва за сложни траектории (напр. движение по крива на Безие). CAAnimationGroup стартира множество анимации паралелно. CATransition — готов преход между изображения или състояния на съдържание.
Протоколът CAMediaTiming — фундаментална част от CAAnimation. Той дефинира основните времеви свойства: duration (продължителност), repeatCount (брой повторения), repeatDuration (обща продължителност на повторенията), autoreverses (връщане към началото), beginTime (начално време спрямо родителя), timeOffset (отместване в рамките на един цикъл), speed (скорост на възпроизвеждане).
Свойството fillMode (CAMediaTimingFillMode) определя показването на слоя преди (backwards) и след (forwards) анимация. Стойности: removed (по подразбиране — връщане към model layer), forwards (остава в крайно състояние), backwards (показва начално състояние преди старт), both (комбинира двете поведения). fillMode работи само с isRemovedOnCompletion = false.
CAAnimation наследява CAMediaTiming и може да бъде вложена в родителска анимация (CAAnimationGroup). В този случай beginTime се изчислява спрямо началото на родителя, а duration се ограничава от родителя. Speed = 2.0 ускорява анимацията два пъти.
CAAnimationGroup комбинира множество CAAnimation в една група. Всички дъщерни анимации стартират паралелно, ако не е зададено beginTime за всяка. Групата има свой собствен duration, който ограничава максималната продължителност на дъщерните анимации. timingFunction на групата се прилага като стойност по подразбиране, ако дъщерната анимация не е задала своя.
CAKeyframeAnimation анимира свойство през множество ключови кадри, дефинирани от масива values. Параметърът keyTimes (масив NSNumber от 0 до 1) определя времевите отпечатъци за всеки кадър. calculationMode определя интерполацията: linear, discrete (без интерполация), paced (равномерна скорост), cubic (сплайн), cubicPaced.
import QuartzCore
// CAAnimationGroup — комбинация от анимации
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 — движение по траектория
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 с персонализирани стойности
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 // спрямо текущата позиция
layer.add(bounce, forKey: nil)
}CAAnimationGroup изпълнява fade, scale и rotate паралелно с duration 2.0. CAKeyframeAnimation с path и calculationMode = .cubicPaced осигурява равномерно движение по крива на Безие с автоматично завъртане (rotationMode = .auto). bounceAnimation използва isAdditive за относително отместване.
Пълен пример за CAAnimation за комплексна анимация на слой с използване на CATransition за смяна на съдържание и CAAnimationGroup за пулсация.
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 — преход между състояния
let transition = CATransition()
transition.type = .fade
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
demoLayer.add(transition, forKey: nil)
// Променяме съдържанието чрез транзакция
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 с type: .fade създава плавен преход между две състояния на backgroundColor. CAAnimationGroup комбинира scale, opacity и shadowOpacity за ефекта на пулсация. removeAllAnimations() нулира всички анимации и връща слоя към първоначалните стойности на model layer.
Често задавани въпроси
CABasicAnimation анимира свойство от начална (fromValue) до крайна (toValue) стойност с равномерна интерполация. CAKeyframeAnimation ви позволява да зададете масив от междинни стойности (values) и времеви отпечатъци (keyTimes) за нелинейна кадрова анимация, включително движение по крива чрез path.
CAAnimationGroup е необходим, когато множество анимации трябва да се изпълняват паралелно с гаранция за синхронизация: group duration ограничава всички дъщерни анимации. Използвайте групата за комбинирани ефекти: мащабиране + промяна на прозрачност + завъртане едновременно.
fillMode определя показването на слоя преди (backwards) и след (forwards) анимация. Стойността .forwards оставя слоя в крайно състояние след завършване на анимацията (изисква isRemovedOnCompletion = false). .both комбинира backwards (начално състояние преди старт) и forwards.
CAAnimation е обект на анимация (инструкция), който се добавя към CALayer чрез layer.add(animation, forKey:). Анимацията съществува като отделен обект, може да бъде използвана повторно (с копиране) и се управлява чрез CAMediaTiming. Слоят може да има множество анимации с различни ключове.
Резюме
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също