CAAnimation é uma classe base abstrata do Core Animation que define a interface comum para todos os tipos de animações: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition. O artigo explica a hierarquia de classes, as propriedades-chave, a agrupamento de animações e exemplos práticos em Swift.
Principais conclusões
CAAnimation é uma classe abstrata do Core Animation que define a interface comum para todas as animações. Ela implementa o protocolo CAMediaTiming (duração, repetição, autoreverso) e CAMediaTimingFillMode (comportamento antes/após a animação). CAAnimation não pode ser instanciada diretamente — use uma de suas subclasses: CABasicAnimation, CAKeyframeAnimation, CAAnimationGroup, CATransition ou CAAnimation (via animationForKeyPath).
Cada CAAnimation é adicionada a um CALayer através do método add(_:forKey:). O parâmetro forKey é um identificador único de animação na camada. Um mesmo keyPath pode ter apenas uma animação ativa. Para substituir uma animação, use removeAnimation(forKey:) antes de adicionar uma nova.
Segundo a Apple, CAAnimation é uma alteração "temporária" da camada. Após a conclusão da animação, a camada de apresentação retorna aos valores da camada modelo se fillMode e isRemovedOnCompletion não estiverem definidos.
O Core Animation fornece quatro subclasses principais de CAAnimation, cada uma para seu próprio cenário de animação. Compreender a hierarquia ajuda a escolher o tipo correto para a tarefa.
| Classe | Propósito | Características principais |
|---|---|---|
| CABasicAnimation | Anima uma propriedade de A para B | fromValue, toValue, byValue, keyPath |
| CAKeyframeAnimation | Animação por vários quadros-chave | values, keyTimes, path, calculationMode |
| CAAnimationGroup | Agrupa múltiplas animações | array animations, duration único |
| CATransition | Transição entre estados de camada | type (fade/push/moveIn/reveal), subtype, startProgress |
CABasicAnimation é a subclasse mais simples e popular. CAKeyframeAnimation é usada para trajetórias complexas (por exemplo, movimento ao longo de uma curva Bezier). CAAnimationGroup executa múltiplas animações em paralelo. CATransition é uma transição pronta entre imagens ou estados de conteúdo.
O protocolo CAMediaTiming é uma parte fundamental do CAAnimation. Ele define as propriedades básicas de tempo: duration, repeatCount, repeatDuration, autoreverses, beginTime (tempo de início relativo ao pai), timeOffset (deslocamento dentro de um ciclo), speed (taxa de reprodução).
A propriedade fillMode (CAMediaTimingFillMode) determina a exibição da camada antes (backwards) e depois (forwards) da animação. Valores: removed (padrão — retorna à camada modelo), forwards (permanece no estado final), backwards (mostra o estado inicial antes do início), both (combina ambos os comportamentos). fillMode funciona apenas quando isRemovedOnCompletion = false.
CAAnimation herda CAMediaTiming e pode ser aninhada em uma animação pai (CAAnimationGroup). Neste caso, beginTime é calculado em relação ao início do pai, e duration é limitada pela duração do pai. Speed = 2.0 dobra a velocidade da animação.
CAAnimationGroup combina múltiplas instâncias de CAAnimation em um único grupo. Todas as animações filhas são iniciadas em paralelo a menos que beginTime seja definido para cada uma. O grupo tem seu próprio duration, que limita a duração máxima das animações filhas. O timingFunction do grupo é usado como valor padrão se uma animação filha não definir o seu próprio.
CAKeyframeAnimation anima uma propriedade através de vários quadros-chave, definidos por um array de values. O parâmetro keyTimes (array de NSNumber de 0 a 1) define os marcos de tempo para cada quadro. calculationMode especifica a interpolação: linear, discrete (sem interpolação), paced (velocidade uniforme), cubic (spline), cubicPaced.
import QuartzCore
// CAAnimationGroup — combinação de animações
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 — movimento por trajetória
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 com valores personalizados
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 // relativo à posição atual
layer.add(bounce, forKey: nil)
}CAAnimationGroup executa fade, scale e rotate em paralelo com duração de 2.0. CAKeyframeAnimation com path e calculationMode = .cubicPaced fornece movimento uniforme ao longo de uma curva Bezier com rotação automática (rotationMode = .auto). bounceAnimation usa isAdditive para deslocamento relativo.
Um exemplo completo de CAAnimation para animação complexa de camadas usando CATransition para troca de conteúdo e CAAnimationGroup para efeitos de pulsação.
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 — transição entre estados
let transition = CATransition()
transition.type = .fade
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
demoLayer.add(transition, forKey: nil)
// Alterando conteúdo via transação
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 com type: .fade cria uma transição suave entre dois estados de backgroundColor. CAAnimationGroup combina scale, opacity e shadowOpacity para um efeito de pulsação. removeAllAnimations() cancela todas as animações e retorna a camada aos seus valores originais da camada modelo.
Perguntas frequentes
CABasicAnimation anima uma propriedade de um valor inicial (fromValue) a um valor final (toValue) com interpolação uniforme. CAKeyframeAnimation permite especificar um array de valores intermediários (values) e marcos de tempo (keyTimes) para animação não linear por quadros-chave, incluindo movimento baseado em curvas através de path.
CAAnimationGroup é necessário quando múltiplas animações devem ser executadas em paralelo com sincronização garantida: a duração do grupo limita todas as animações filhas. Use group para efeitos combinados: escala + alteração de opacidade + rotação simultaneamente.
fillMode determina a exibição da camada antes (backwards) e depois (forwards) da animação. O valor .forwards mantém a camada no estado final após a conclusão da animação (requer isRemovedOnCompletion = false). .both combina backwards (estado inicial antes do início) e forwards.
CAAnimation é um objeto de animação (instrução) que é adicionado a um CALayer através de layer.add(animation, forKey:). A animação existe como um objeto separado, pode ser reutilizada (com cópia) e é gerenciada através de CAMediaTiming. Uma camada pode ter múltiplas animações com diferentes chaves.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também