CAAnimation — ключевые понятия, CAAnimationGroup и анимации слоев

Автор: IT Sectr Опубликовано: 2026-03-01 Время чтения: 8 мин

CAAnimation — абстрактный базовый класс Core Animation, определяющий общий интерфейс для всех типов анимаций: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition. Статья объясняет иерархию классов, ключевые свойства, группировку анимаций и практические примеры на Swift.

Главное

  • CAAnimation — абстрактный базовый класс Core Animation, от которого наследуются CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition
  • CAAnimationGroup — параллельное выполнение нескольких анимаций с общим duration и timingFunction
  • CAKeyframeAnimation — анимация по ключевым кадрам с массивами значений и временных меток
  • CAMediaTiming — протокол управления временем: duration, repeatCount, autoreverses, timeOffset
  • CATransition — предопределённые переходы между состояниями слоя (fade, push, moveIn, reveal)

Что такое CAAnimation?

CAAnimation — абстрактный класс Core Animation, определяющий общий интерфейс для всех анимаций. Он реализует протокол CAMediaTiming (время, повтор, автоповорот) и CAMediaTimingFillMode (поведение до/после анимации). CAAnimation нельзя инстанциировать напрямую — используйте один из подклассов: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition или CAAnimation (через animationForKeyPath).

Каждая CAAnimation добавляется к CALayer через метод add(_:forKey:). Параметр forKey — уникальный идентификатор анимации на слое. Один и тот же keyPath может иметь только одну активную анимацию. Для замены анимации используйте removeAnimation(forKey:) перед добавлением новой.

По данным Apple, CAAnimation — это «временное» (temporary) изменение слоя. После завершения анимации presentation layer возвращается к значениям model layer, если не заданы fillMode и isRemovedOnCompletion.

Иерархия классов CAAnimation

Core Animation предоставляет четыре основных подкласса CAAnimation, каждый для своего сценария анимации. Понимание иерархии помогает выбрать правильный тип для задачи.

КлассНазначениеКлючевые особенности
CABasicAnimationАнимация одного свойства от A до BfromValue, toValue, byValue, keyPath
CAKeyframeAnimationАнимация по нескольким ключевым кадрамvalues, keyTimes, path, calculationMode
CAAnimationGroupГруппировка нескольких анимацийanimations массив, единый duration
CATransitionПереход между состояниями слояtype (fade/push/moveIn/reveal), subtype, startProgress

CABasicAnimation — самый простой и популярный подкласс. CAKeyframeAnimation используется для сложных траекторий (например, движение по кривой Безье). CAAnimationGroup запускает несколько анимаций параллельно. CATransition — готовый переход между изображениями или состояниями контента.

CAMediaTiming — управление временем

Протокол 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 и CAKeyframeAnimation

CAAnimationGroup объединяет несколько CAAnimation в одну группу. Все дочерние анимации запускаются параллельно, если не задан beginTime для каждой. Группа имеет собственный duration, который ограничивает максимальную длительность дочерних анимаций. timingFunction группы применяется как значение по умолчанию, если дочерняя анимация не задала свой.

CAKeyframeAnimation анимирует свойство по нескольким ключевым кадрам, заданным массивом values. Параметр keyTimes (массив NSNumber от 0 до 1) определяет временные метки для каждого кадра. calculationMode задаёт интерполяцию: linear, discrete (без интерполяции), paced (равномерная скорость), cubic (сплайн), cubicPaced.

swift
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 для относительного смещения.

Примеры кода на Swift

Полный пример CAAnimation для комплексной анимации слоя с использованием CATransition для смены контента и CAAnimationGroup для пульсации.

swift
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 и CAKeyframeAnimation?

CABasicAnimation анимирует свойство от начального (fromValue) до конечного (toValue) значения с равномерной интерполяцией. CAKeyframeAnimation позволяет задать массив промежуточных значений (values) и временных меток (keyTimes) для нелинейной анимации по ключевым кадрам, включая движение по кривой через path.

Когда использовать CAAnimationGroup?

CAAnimationGroup нужен, когда несколько анимаций должны выполняться параллельно с гарантией синхронизации: групповой duration ограничивает все дочерние анимации. Используйте group для комбинированных эффектов: масштабирование + изменение прозрачности + вращение одновременно.

Что такое fillMode в CAAnimation?

fillMode определяет отображение слоя до (backwards) и после (forwards) анимации. Значение .forwards оставляет слой в конечном состоянии после завершения анимации (требует isRemovedOnCompletion = false). .both комбинирует backwards (начальное состояние до старта) и forwards.

Как отличить CAAnimation от CALayer анимации?

CAAnimation — это объект анимации (инструкция), который добавляется к CALayer через layer.add(animation, forKey:). Анимация существует как отдельный объект, может быть переиспользована (с копированием) и управляется через CAMediaTiming. Слой может иметь множество анимаций с разными ключами.

Итоги

  • CAAnimation — абстрактный базовый класс Core Animation с реализацией CAMediaTiming и CAMediaTimingFillMode
  • Иерархия классов — CABasicAnimation (одно свойство), CAKeyframeAnimation (множество кадров), CAAnimationGroup (группировка), CATransition (переходы)
  • CAMediaTiming — протокол с duration, repeatCount, autoreverses, beginTime, timeOffset, speed, fillMode
  • CAAnimationGroup — параллельное выполнение анимаций с единым duration и timingFunction
  • CAKeyframeAnimation — анимация по values/keyTimes или path (кривая Безье) с calculationMode
  • CATransition — предопределённые типы: fade, push, moveIn, reveal с возможностью настройки subtype
  • Управление — layer.add(animation, forKey:), removeAnimation(forKey:), removeAllAnimations()

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также