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 — це «тимчасова» зміна шару. Після завершення анімації шар представлення повертається до значень модельного шару, якщо не задані 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 (за замовчуванням — повернення до модельного шару), 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() скидає всі анімації та повертає шар до вихідних значень модельного шару.
Часто задавані питання
CABasicAnimation анімує властивість від початкового (fromValue) до кінцевого (toValue) значення з рівномірною інтерполяцією. CAKeyframeAnimation дозволяє задати масив проміжних значень (values) та часових позначок (keyTimes) для нелінійної анімації за ключовими кадрами, включаючи рух по кривій через path.
CAAnimationGroup потрібен, коли кілька анімацій повинні виконуватися паралельно з гарантією синхронізації: груповий duration обмежує всі дочірні анімації. Використовуйте group для комбінованих ефектів: масштабування + зміна прозорості + обертання одночасно.
fillMode визначає відображення шару до (backwards) та після (forwards) анімації. Значення .forwards залишає шар у кінцевому стані після завершення анімації (вимагає isRemovedOnCompletion = false). .both комбінує backwards (початковий стан до старту) та forwards.
CAAnimation — це об'єкт анімації (інструкція), який додається до CALayer через layer.add(animation, forKey:). Анімація існує як окремий об'єкт, може бути перевикористана (з копіюванням) і керується через CAMediaTiming. Шар може мати безліч анімацій з різними ключами.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також