1. KEN-chan

    No comment

    KEN-chan
Changes in body
Source | HTML | Preview
@@ -1,232 +1,233 @@
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`は初期の方向と速度
間違っていたら教えてください。正直、うまい値の渡し方がわかりません笑
![Jun-22-2016 17-08-52.gif](https://qiita-image-store.s3.amazonaws.com/0/54826/8729fb60-4ebd-2263-ccb2-75472322d8de.gif "Jun-22-2016 17-08-52.gif")
このクラスをうまく使うと、このようなアニメーションが実現できるようです!
すごい!!!
## 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年後くらいまで使えない!
+- [セッション動画](https://developer.apple.com/videos/play/wwdc2016/216/)はこちらです!!