CAAnimation は、すべてのアニメーションタイプに共通のインターフェースを定義するCore Animationの抽象基底クラスです:CABasicAnimation、CAKeyframeAnimation、CAAnimationGroup、CATransition。この記事では、クラス階層、主要プロパティ、アニメーションのグループ化、Swiftの実践例について説明します。
重要なポイント
CAAnimation は、すべてのアニメーションに共通のインターフェースを定義するCore Animationの抽象クラスです。これはCAMediaTimingプロトコル(duration、repeat、autoreverse)およびCAMediaTimingFillMode(アニメーション前後の動作)を実装しています。CAAnimationを直接インスタンス化することはできません。代わりにサブクラスのいずれかを使用します:CABasicAnimation、CAKeyframeAnimation、CAAnimationGroup、CATransition、またはCAAnimation(animationForKeyPath経由)。
各CAAnimationはadd(_:forKey:)メソッドを使用してCALayerに追加されます。forKeyパラメーターは、レイヤー上のアニメーションの一意の識別子です。1つのkeyPathには1つのアクティブなアニメーションしか持てません。アニメーションを置き換えるには、新しいものを追加する前にremoveAnimation(forKey:)を使用します。
Appleによると、CAAnimationはレイヤーの「一時的な」変更です。アニメーション完了後、fillModeとisRemovedOnCompletionが設定されていない場合、プレゼンテーションレイヤーはモデルレイヤーの値に戻ります。
Core Animationは4つの主要なCAAnimationサブクラスを提供しており、それぞれが独自のアニメーションシナリオに対応しています。階層を理解することで、タスクに適したタイプを選択できます。
| クラス | 目的 | 主要機能 |
|---|---|---|
| CABasicAnimation | 1つのプロパティを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(1サイクル内のオフセット)、speed(再生速度)。
fillModeプロパティ(CAMediaTimingFillMode)は、アニメーション前(backwards)および後(forwards)のレイヤー表示を決定します。値:removed(デフォルト — モデルレイヤーに戻る)、forwards(最終状態を維持)、backwards(開始前に初期状態を表示)、both(両方の動作を組み合わせる)。fillModeはisRemovedOnCompletion = falseの場合にのみ機能します。
CAAnimationはCAMediaTimingを継承し、親アニメーション(CAAnimationGroup)にネストできます。この場合、beginTimeは親の開始を基準に計算され、durationは親のdurationによって制限されます。Speed = 2.0でアニメーション速度が2倍になります。
CAAnimationGroupは、複数のCAAnimationインスタンスを1つのグループに結合します。各アニメーションにbeginTimeが設定されていない限り、すべての子アニメーションは並列に開始されます。グループには独自のdurationがあり、子アニメーションの最大期間を制限します。グループのtimingFunctionは、子アニメーションが独自に設定しない場合のデフォルト値として使用されます。
CAKeyframeAnimationは、値の配列で定義された複数のキーフレームにわたってプロパティをアニメーションします。keyTimesパラメーター(0から1のNSNumberの配列)は各フレームのタイムスタンプを定義します。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は、duration 2.0でfade、scale、rotateを並列実行します。pathとcalculationMode = .cubicPacedを使用したCAKeyframeAnimationは、自動回転(rotationMode = .auto)を伴うベジェ曲線に沿った均一な動きを提供します。bounceAnimationは相対オフセットにisAdditiveを使用します。
コンテンツ切り替えにCATransition、パルス効果にCAAnimationGroupを使用した、複雑なレイヤーアニメーションの完全なCAAnimationの例です。
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
}
}type: .fadeのCATransitionは、2つのbackgroundColor状態間のスムーズなトランジションを作成します。CAAnimationGroupは、scale、opacity、shadowOpacityを組み合わせてパルス効果を実現します。removeAllAnimations()はすべてのアニメーションをキャンセルし、レイヤーを元のモデルレイヤー値に戻します。
よくある質問
CABasicAnimationは、均一な補間でプロパティを初期値(fromValue)から最終値(toValue)にアニメーションします。CAKeyframeAnimationでは、非線形キーフレームアニメーションのために中間値(values)とタイムスタンプ(keyTimes)の配列を指定でき、pathによる曲線ベースの移動も含みます。
CAAnimationGroupは、複数のアニメーションを同期保証付きで並列実行する必要がある場合に必要です。グループのdurationがすべての子アニメーションを制限します。グループを使用して複合効果(拡大縮小+透明度変更+回転の同時実行)を実現します。
fillModeは、アニメーション前(backwards)および後(forwards)のレイヤー表示を決定します。.forwardsはアニメーション完了後にレイヤーを最終状態に保ちます(isRemovedOnCompletion = falseが必要)。.bothはbackwards(開始前の初期状態)とforwardsを組み合わせます。
CAAnimationは、layer.add(animation, forKey:)を介してCALayerに追加されるアニメーションオブジェクト(命令)です。アニメーションは個別のオブジェクトとして存在し、再利用可能で(コピーして)、CAMediaTimingを通じて管理されます。1つのレイヤーは異なるキーを持つ複数のアニメーションを持つことができます。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。