[iOS10] UIViewPropertyAnimatorによるアニメーション
1 はじめに
iOS 10 で新しく追加されたUIViewPropertyAnimatorによって、アニメーションロジックを簡単に記述することが可能になりました。
今回は、この記述要領について、覚書として纏めてみました。
なお、UIViewPropertyAnimatorについては、既に、ここDevelopers.IOで紹介されていますので、クラス構造や、全機能の体系については、下記を御覧ください。
[iOS 10][UIKit] 新しく加わった動的なアニメーション実装の方法とその周辺解説
2 Initializing a Property Animator
(1) 最も単純なアニメーション
ビューの中心位置を変更するアニメーションです。
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){ kao.center = endPoint } animator.startAnimation()
上記の例では、パラメータにduration:(アニメーションの持続時間)及びcurve:(アニメーションカーブ)が指定されていますが、cueve:には、次の4つ(UIViewAnimationCurve列挙型)が指定可能です。
- .liner (直線)
- .easeIn (初めゆっくり)
- .easeInOut (初めと終わりがゆっくり)
- .easeOut (終わりゆっくり)
(2) 3次ベジェ曲線
先の例では、アニメーションカーブをUIViewAnimationCurveで指定しましたが、2点指定によるベジェ曲線で指定することも可能です。
let animator = UIViewPropertyAnimator(duration: 2.0, controlPoint1: CGPoint(x: 0.1,y: 0.5), controlPoint2: CGPoint(x: 0.5, y:0.2), animations: { kao.center = endPoint }) animator.startAnimation()
(3) スプリングエフェクト
dampingRatioで0〜1の減衰値を指定することで、スプリングエフェクトを定義できます。
let animator = UIViewPropertyAnimator(duration: 2.0, dampingRatio: 0.3, animations: { kao.center = endPoint }) animator.startAnimation()
3 UIViewAnimating
(1) UIViewAnimatingState
UIViewPropertyAnimatorの継承元である、UIViewAnimatingでは、startAnimation()、pauseAnimation()、stopAnimation(_:)などのメソッドによってステータスを変更します。
ステータスには、以下の3つがあります。 * Inactive (非アクティブ) * Active(アクティブ) * Stopped(停止)
API Reference UIViewAnimatingより
(2) fractionComplete
fractionCompleteは、アニメーションの進行具合を0〜1で表現しています。 そして、これは、セッターとして利用することも可能です。
下記の例は、スライダーによって、アニメーションの進行具合を変更している様子です。アニメーションを開始していないので、ステータスは非アクティブのままです。
var animator:UIViewPropertyAnimator?
animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){ kao.center = endPoint }
@IBAction func sliderValueChanged(_ sender: UISlider) { self.animator?.fractionComplete = CGFloat(sender.value) }
(3) isReversed
isReversedというプロパティをセットすることで、アニメーションはリバースします。 下記の例は、アニメーションが開始され、アクティブ状態のものをリバースしています。
var animator:UIViewPropertyAnimator?
animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){ kao.center = endPoint } animator?.startAnimation()
@IBAction func tapReverseButton(_ sender: Any) { animator?.isReversed = (animator?.isReversed)! ? false : true }
4 Modifying Animations
(1) 追加
UIViewPropertyAnimatorは、UIViewImplicitlyAnimatingプロトコルを採用しており、簡単にアニメーションを追加することが可能です。
下記は、addAnimations(_:)による初期化時の追加です。
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){ kao.center = endPoint } animator.addAnimations{ kao.alpha = 0.0 } animator.startAnimation()
(2) 遅延指定
addAnimations(_:delayFactor:)では、追加するアニメーションの開始時期を遅らせることも可能です。 次の例は、alpha値の変化開始を全体の90%のアニメーションが進行した以降に指定しています。
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){ kao.center = endPoint } animator.addAnimations({ kao.alpha = 0.0 }, delayFactor: 0.9) animator.startAnimation()
(3) 終了後
addCompletion(_:)は、アニメーション終了後の変化を指定します。
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .linear){ kao.center = endPoint } animator.addCompletion {_ in kao.bounds = CGRect(x: 0, y: 0, width: 70, height: 70) } animator.startAnimation()
アニメーションの追加は、初期化時に限らず、実行中のアニメーションにも可能です。 この場合、残り時間をアニメーションの継続時間として直ちに実行されます。
5 UITimingCurveProvider
UIViewPropertyAnimatorのタイミング指定で使用されるUITimingCurveProviderとしてUISpringTimingParametersが利用可能です。
これを使用するとバネのようなアニメーションが簡単に作成できます。
@IBOutlet weak var kao: UIImageView! var animator:UIViewPropertyAnimator? var startPosition:CGPoint?
override func viewDidLoad() { super.viewDidLoad() self.startPosition = self.kao.center self.kao.isUserInteractionEnabled = true self.kao.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.dragKao))) }
func dragKao(gesture: UIPanGestureRecognizer) { // ImageViewの相対位置 let translation = gesture.translation(in: self.view) // View内での絶対位置 var position: CGPoint = CGPoint(x: translation.x + self.startPosition!.x, y: translation.y + self.startPosition!.y) switch gesture.state { case .began: if animator != nil && animator!.isRunning { animator!.stopAnimation(false) } kao.center = position case .changed: kao.center = position case .ended: let v = gesture.velocity(in: kao) let velocity = CGVector(dx: v.x / 500, dy: v.y / 500) let springParameters = UISpringTimingParameters(mass: 30, stiffness: 800, damping: 100, initialVelocity: velocity) animator = UIViewPropertyAnimator(duration: 0.0, timingParameters: springParameters) animator!.addAnimations({ self.kao.center = self.view.center }) animator!.startAnimation() default: break }
6 最後に
UIViewPropertyAnimatorを使用すると、アニメーションの組み合わせが、非常にシンプルに記述できるように感じました。 なんとかUITimingCurveProviderを使いこなして、自由にアニメーションを作れるようになりたいと思います。
7 参考資料
iOS10からのAnimationがいい感じ!
Designing Animations with UIViewPropertyAnimator in iOS 10 and Swift 3