1. KEN-chan

    Posted

    KEN-chan
Changes in title
+iOS10からのAnimationがいい感じ!
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,227 @@
+
+WWDC16で、iOS10から使えるアニメーションに関する新しい発表がありました。
+動的なアニメーションの追加や、一時停止など、柔軟にいろんな事ができるようになっていたので、紹介したいと思います!
+
+## 従来のアニメーション
+
+
+まず、従来のアニメーションは、こんな感じで書いていたかと思います。
+
+```swift
+
+UIView.animateWithDuration(2.0, delay: 0, options: .CurveEaseInOut, animations: {
+
+ // animation
+
+}) { _ in
+
+ // completion
+
+}
+```
+
+まず、こちらのメソッドも、Swift3からはこんな感じに変わります!
+
+```swift
+
+UIView.animate(withDuration: 2.0, delay: 0, options: [.curveEaseIn, .curveEaseOut], animations: {
+
+}) { _ in
+
+}
+```
+
+- メソッド名はシンプルになって、第一引数も外部名が表記するようになっています。
+- `UIViewAnimationOptions`が`lowerCamelCase`になっている
+- `curveEaseInOut`が無かったのですが、それを実現するには、このようにするんですかね、、??
+
+ただ、これも、動的にいろんな操作をするには向いていません。
+
+だからといって、`CoreAnimation`も分かりづらかったり、`beginFromCurrentState`というoptionの挙動もわかりづらい、、、
+
+そこで登場したのが、 **UIViewPropertyAnimator**です!こちらのクラスを使うと、アニメーションに対していろんな柔軟な対応ができるようになっています!
+
+## UIViewPropertyAnimator
+
+ざっと、このような感じで使います!
+
+```swift
+
+let timing = UICubicTimingParameters(animationCurve: .easeInOut)
+let animator = UIViewPropertyAnimator(duration: 2.0, timingParameters: timing)
+
+animator.addAnimations {
+ // animation
+}
+
+animator.startAnimation()
+
+animator.pauseAnimation()
+```
+なんだか、いろいろできそうな予感がします。
+
+```swift
+
+@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](https://qiita-image-store.s3.amazonaws.com/0/54826/b527f24d-5c39-78f0-b671-f285bafb38d6.png "Screen Shot 2016-06-22 at 11.32.31.png")
+
+- UIViewAnimatingとUIViewImplicitlyというプロトコルに準拠しています。
+- UITimingCurveProviderというプロトコルに準拠したオブジェクトを受け取って、アニメーションのタイミングを調整します。
+
+## UIViewAnimatingプロトコル
+アニメーションのフローを制御するメソッドやプロパティが定義されている。
+
+### メソッド
+
+- `func startAnimation()`
+- `func pauseAnimation()`
+ - アニメーションの一時停止
+ - `AnimatingState`は`active`のまま
+- `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](https://qiita-image-store.s3.amazonaws.com/0/54826/7bb41db2-ce14-74d8-44b7-3c6a0593214a.png "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`は初期の方向と速度
+
+間違っていたら教えてください。正直、うまい値の渡し方がわかりません笑
+
+## UIViewControllerAnimatedTransitioning
+
+`UIViewPropetyAnimator`を用いたアニメーションは画面遷移にも使えるようです!!
+
+```swift
+
+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年後くらいまで使えない!
+
+