iOS
animation
WWDC
Swift
ios10

iOS10からのAnimationがいい感じ!

More than 1 year has passed since last update.

WWDC16で、iOS10から使えるアニメーションに関する新しい発表がありました。

動的なアニメーションの追加や、一時停止など、柔軟にいろんな事ができるようになっていたので、紹介したいと思います!


従来のアニメーション

まず、従来のアニメーションは、こんな感じで書いていたかと思います。


UIView.animateWithDuration(2.0, delay: 0, options: .CurveEaseInOut, animations: {

// animation

}) { _ in

// completion

}

まず、こちらのメソッドも、Swift3からはこんな感じに変わります!


UIView.animate(withDuration: 2.0, delay: 0, options: [.curveEaseIn, .curveEaseOut], animations: {

}) { _ in

}


  • メソッド名はシンプルになって、第一引数も外部名が表記するようになっています。


  • UIViewAnimationOptionslowerCamelCaseになっている


  • curveEaseInOutが無かったのですが、それを実現するには、このようにするんですかね、、??

ただ、これも、動的にいろんな操作をするには向いていません。

だからといって、CoreAnimationも分かりづらかったり、beginFromCurrentStateというoptionの挙動もわかりづらい、、、

そこで登場したのが、 UIViewPropertyAnimatorです!こちらのクラスを使うと、アニメーションに対していろんな柔軟な対応ができるようになっています!


UIViewPropertyAnimator

ざっと、このような感じで使います!


let timing = UICubicTimingParameters(animationCurve: .easeInOut)
let animator = UIViewPropertyAnimator(duration: 2.0, timingParameters: timing)

animator.addAnimations {
// animation
}

animator.startAnimation()

animator.pauseAnimation()

なんだか、いろいろできそうな予感がします。


@IBAction func handlePan(recognizer: UIPanGestureRecognizer) {

let translation = recognizer.translation(in: self.view)
let translatedCenterY = view.center.y + translation.y
let progress = translatedCenterY / self.view.bounds.size.height

animator.fractionComplete = progress
}

このように、ユーザのジェスチャに応じてアニメーションの進行を操作することもできます。


UIViewPropertyAnimator周りのクラス図

Screen Shot 2016-06-22 at 11.32.31.png


  • UIViewAnimatingとUIViewImplicitlyというプロトコルに準拠しています。

  • UITimingCurveProviderというプロトコルに準拠したオブジェクトを受け取って、アニメーションのタイミングを調整します。


UIViewAnimatingプロトコル

アニメーションのフローを制御するメソッドやプロパティが定義されている。


メソッド


  • func startAnimation()


  • func pauseAnimation()


    • アニメーションの一時停止


    • AnimatingStateactiveのまま




  • func stopAnimation(_ withoutFinishing: Bool)


    • アニメーションを現在のポジションで終了させたい時に利用する

    • 引数にtrueを渡すと直接inactiveのステートに変化する

    • 引数にfalseを渡すと、stoppedステートに変化し、終了させるにはfinishAnimationメソッドを呼ぶ




  • func finishAnimation(at: UIViewAnimatingPosition)



    • stoppedステートの時にこのメソッドを呼んでアニメーションを終了させる


    • stoppedステートに遷移する前にこのメソッドを呼ぶとエラーになる。


    • inactiveステートに遷移する




プロパティ



  • var fractionComplete: CGFloat


    • アニメーションの完了度合いのパーセンテージ

    • 0.0 - 1.0の値をとる

    • この値を操作することにより、アニメーションをインテラクティブに操作できる




  • var isReversed: Bool


    • このプロパティを操作することによってアニメーションの方向を操作できる




  • var state: UIViewAnimatingState

    Enumで


    • inactive

    • active

    • stopped



の3つの値を持つ

- var isRunning: Bool

- アニメーションが進行中かどうか


UIViewImplicitlyAnimatingプロトコル

アニメーションのカスタマイズに関するメソッドが定義されている


メソッド



  • func addAnimations(() -> Void)


    • アニメーションを定義する




  • func addAnimations(() -> Void, delayFactor: CGFloat)


    • 元々のアニメーションに対して、途中から別のアニメーションを開始する場合などに利用する


    • delayFactorには0.0 - 1.0の値を入れる

    • 例えば、0.7を入れたら、元々のアニメーションの7割が終了した時点で、追加のアニメーションが開始される




  • func addCompletion((UIViewAnimatingPosition) -> Void)


    • アニメーションが終了したときの処理を記述する

    UIViewAnimatingPositionはEnumで、

    - end

    - start

    - current

    の3つの値がある




  • func continueAnimation(withTimingParameters: UITimingCurveProvider?, durationFactor: CGFloat)


    • pauseしているアニメーションに対して、タイミングや、durationを変更して再開したい場合に利用する


    • durationFactorの値と、元々のdurationを掛けた値が最終的なdurationになる




UICubicTimingParameters

アニメーションのタイミングを定義するクラス


イニシャライズ


  • init()

  • init(animationCurve: UIViewAnimationCurve)

UIViewAnimationCurveには

- case easeInOut // slow at beginning and end

- case easeIn // slow at beginning
- case easeOut // slow at end
- case linear

の4つが定義されている



  • init(controlPoint1: CGPoint, controlPoint2: CGPoint)


    • 2つの点を定義することにより、3次ベジェ曲線を定義する



cubic.png


UISpringTimingParameters

このクラスのオブジェクトをUIViewPropertyAnimatorに渡す事によってバネのような動きのアニメーションを実現できる


イニシャライズ


  • init()


  • init(dampingRatio: CGFloat)


    • 減衰比を渡す

    • 0.0 - 1.0の値を取り、小さいほど揺れが大きくなる




  • init(dampingRatio: CGFloat, initialVelocity: CGVector)


    • 上記のに加え、初期の方向と速度を渡すことができる




  • init(mass: CGFloat, stiffness: CGFloat, damping: CGFloat, initialVelocity: CGVector)



    • massは質量


    • stiffnessはバネの硬さ??


    • dampingは減衰の強さ??


    • initialVelocityは初期の方向と速度



間違っていたら教えてください。正直、うまい値の渡し方がわかりません笑

Jun-22-2016 17-08-52.gif

このクラスをうまく使うと、このようなアニメーションが実現できるようです!

すごい!!!


UIViewControllerAnimatedTransitioning

UIViewPropetyAnimatorを用いたアニメーションは画面遷移にも使えるようです!!


func animateTransition(_ transitionContext: UIViewControllerContextTransitioning) {

self.interruptibleAnimator(forTransition: transitionContext)?.startAnimation(
}

func interruptibleAnimator(forTransition transitionContext: UIViewControllerContextTransitioning?) -> UIViewImplicitlyAnimating? {

let timing = UICubicTimingParameters(animationCurve: .easeInOut)
let animator = UIViewPropertyAnimator(duration: 2.0, timingParameters: timing)

animator.addAnimations {
// animation
}

return animator
}

のように、新しく追加されたinterruptibleAnimatorメソッドでUIViewPropertyAnimatorのオブジェクトを返して、従来使っていたanimateTransitionメソッドでアニメーションを開始してあげる、という流れです。


まとめ


  • なんだか気持ち良いアニメーションが作りたくなった

  • iOS10からの対応なので、半年後とか1年後くらいまで使えない!


  • セッション動画はこちらです!!