はじめに
CoreAnimationを使って少し凝ったアニメーション等を実装する時に、毎回おまじないのようにfillModeを設定していたのですが、それについて少し調べたので書いていきたいと思います
fillModeとは
アニメーションの終了時の動作を決めるためのプロパティだと理解しています
fillModeの種類と役割
- removed:
アニメーションが終了したら削除する。デフォルトでremovedが設定されています - forwards:
アニメーションが終了時は最後の状態を保持する - backwards:
アニメーションが終了時は最初の状態で固定する - both:
forwardsとbothの両方を適用したもの
実際に動きを見てみる
ベースとなるコード
backgroundColorをgreenにしただけのUIViewがあります。
let animatedView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 100)))
animatedView.backgroundColor = .green
animatedViewをCoreAnimationを使って、origin.xを200に、backgroundColorをblueにアニメーションさせます
let translateAnimation = CABasicAnimation(keyPath: "transform.translation.x")
translateAnimation.beginTime = CACurrentMediaTime() + 0.5
translateAnimation.duration = 1.0
translateAnimation.fromValue = CATransform3DIdentity
translateAnimation.toValue = 200
translateAnimation.isRemovedOnCompletion = false
let backgroundAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.backgroundColor))
backgroundAnimation.beginTime = CACurrentMediaTime() + 0.5
backgroundAnimation.duration = 1.0
backgroundAnimation.fromValue = UIColor.green.cgColor
backgroundAnimation.toValue = UIColor.blue.cgColor
backgroundAnimation.isRemovedOnCompletion = false
animatedView.layer.add(backgroundAnimation, forKey: nil)
animatedView.layer.add(translateAnimation, forKey: nil)
※アニメーションがわかりやすくなるようにisRemovedOnCompletionをfalseにしています
これらにfillModeを設定して挙動を違いを見ていきます。
.removedの時
fillModeのデフォルト値が.removedなので、先程のコードのままでも同じ挙動になります。
...
+translateAnimation.fillMode = .removed
...
+backgroundAnimation.fillMode = .removed
...
アニメーションが終わった時、アニメーションが削除されて初期状態に戻っているのがわかります。
.forwardsの時
両方のfillModeを.forwardsに設定します。
...
+translateAnimation.fillMode = .forwards
...
+backgroundAnimation.fillMode = .forwards
...
アニメーションが終わった時、最後の状態を保持し続けているのがわかります。
.backwardsの時
両方の.fillModeをbackwardsに設定します。
...
+translateAnimation.fillMode = .backwards
...
+backgroundAnimation.fillMode = .backwards
...
.removedの時と同じ挙動になってしまいました。わかりづらいので、translateAnimationのfillModeだけ.forwardsにして見たいと思います。
...
-translateAnimation.fillMode = .backwards
+translateAnimation.fillMode = .forward
...
+backgroundAnimation.fillMode = .backwards
...
最後のbackgroundの状態がgreenになっている通り、アニメーションが終わった時、最初の状態を保持しているのがわかります。
.bothの時
両方のfillModeに.bothを設定します。
...
+translateAnimation.fillMode = .both
...
+backgroundAnimation.fillMode = .both
...
見かけでは .forwardsと一緒ですが、連続で何回もアニメーションすると違いがわかります。
.bothを連続でアニメーションさせた時
.forwardを連続でアニメーションさせた時
.bothだといい感じになっていますね。
最後に
基本的には、isRemovedOnCompletion = falseと.fillMode = .forwardsの組み合わせで使うことがほとんどだと思いますが、他にもこんなプロパティがあるよ、という紹介でした。