UIViewPropertyAnimatorの基本まとめ②

さて、前回に引き続き、UIViewPropertyAnimatorについて、
調べたことをまとめていきたいと思います。

UIViewPropertyAnimatorを用いた基本的なアニメーションの実装方法につきましては、
前回の[UIViewPropertyAnimatorの基本まとめ①](http://qiita.com/TsukasaHasegawa/items/4b112babb48c7a9b6de4)をご参照ください。

前回は、UIViewPropertyAnimatorを使用してアニメーションを設定する方法について、
基本的な部分を網羅的にまとめましたが、

今後は、
・UITimingCurveProviderの具体的な動き
・アニメーションをReverseする方法
・アニメーションを何度も実行できるようにする方法
などについてまとめていこうという展望を持っています。

よろしければ、お付き合いください。

<img width="1108" alt="スクリーンショット_2017-01-17_22_39_34.png" src="https://qiita-image-store.s3.amazonaws.com/0/135729/ae599b26-f4b6-fc2e-57ea-a9b3173d54c9.png">

今回は、ベジエ曲線をより深く理解するために、
UICubicTimingParametersについて、まとめていきます。

#UICubicTimingParameters

[UIViewPropertyAnimatorの基本まとめ①](http://qiita.com/TsukasaHasegawa/items/4b112babb48c7a9b6de4)でも、軽く触れましたが、
UICubicTimingParametersは、
UIViewAnimationCurveを使用して生成することもできます。

ですが、ここではベジエ曲線を用いた生成方法について見ていきます。

実装する際は、以下のように記入するんでしたね。

````swift:ViewController.swift
// bezier曲線による速度制御
bezierAnimator = UIViewPropertyAnimator(duration: 2.0, controlPoint1: CGPoint(x: 0.1, y: 0.5), controlPoint2: CGPoint(x:0.5, y:0.2)){
    self.circle.center.y += 200
}
````

また、以下のように、UICubicTimingParametersのインスタンスを生成して、
UIViewPropertyAnimatorに組み込む書き方も可能です。

````swift:ViewController.swift
//cubicTimingParameters
var cubic = UICubicTimingParameters(controlPoint1: CGPoint(x:0.1, y:0.5), controlPoint2: CGPoint(x:0.5, y:0.2))

// UIViewPropertyAnimator
animator = UIViewPropertyAnimator(duration: 2.0, timingParameters: cubic){
    self.circle.center.y += 200
}
````

本当にざっくりな説明なのですが、
弧①・・・(0.0, 0.0)、controlPoint1、controlPoint2の3点により描画される弧
弧②・・・controlPoint1、controlPoint2、(1.0, 1.0)の3点により描画される弧

弧①と弧②をたどりながら、(0.0, 0.0)から(1.0, 1.0)に向けて描画された曲線が、アニメーションの速度の加減の状況を示している。

ということなんです。（下の画像をご覧いただけると、イメージしやすいかと・・・。）

<img width="458" alt="スクリーンショット 2017-01-29 22.25.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/135729/987ab1aa-1c88-165a-5e94-3d8ab27733f5.png">

上の画像を見ると、アニメーション開始直後とアニメーションの終了間際の角度が急で、
中間の角度がなだらかになっているのがお分かりいただけると思います。

すなわち、上の画像では、

**[開始] → めっちゃ加速 → なだらかに減速 → なだらかに加速 → めっちゃ加速 → [終了]**

という流れになります。

わかりにくいっ！！！


ということで、百聞は一見に如かず。

##controlPointの座標を色々変更してみる

実際に言葉だけで理解するのはとても難しいと思います。（筆者にとってだけかもしれませんが・・・。）

そんな時には、とにかく手を動かして
組んだプログラムがどう動くかを見てみるのが１番かと思います！！

ということで、
実際にcontrolPointの値に様々な数値を設定して、
動きの変化を観察致しました。φ(●_<)

controlPointの座標を色々と変えて動きを見ていて、
ベジエ曲線を理解する上で、3つを基本形として押さえておくことが重要なのではないかと思いました。

その3つを、筆者の独断と偏見で分類致しました。
もしよろしければ、皆様のご理解の一助にでもなれば幸いです。

###● **0110型** - 「急 → 緩 → 急」
まずは、controlPoint1(x: 0.0, y: 1.0), controlPoint2(x: 1.0, y: 0.0)

座標の値から「0110型」と名付けました。（安直ですみません・・・orz）

・UIViewPropertyAnimatorで設定

````swift:ViewController.swift
bezierAnimator = UIViewPropertyAnimator(duration: 2.0, controlPoint1: CGPoint(x: 0.0, y: 1.0), controlPoint2: CGPoint(x:1.0, y:0.0)){
    self.circle.center.y += 200
}
````

・UICubicTimingParametersで設定

````swift:ViewController.swift
//cubicTimingParameters
var cubic = UICubicTimingParameters(controlPoint1: CGPoint(x:0.0, y:1.0.), controlPoint2: CGPoint(x:1.0, y:0.0))
````

「0110型」で描画される曲線は、以下のような感じです。

<img width="584" alt="名称未設定.png" src="https://qiita-image-store.s3.amazonaws.com/0/135729/fea26393-54a4-dbf3-62d9-48b5d2ac0ee4.png">

速度の変化を図にすると、以下のようになります。

|| 開始直後 | 中間① |中間②| 終了間際 |
|:-----:|:-----:|:-----:|:-----:|:-----:|
|緩急|急|緩|緩|急|
|加減速|加速| 減速 | 減速 | 加速  |

上記の図のような速度の変化をつけたい場合には、「0110型」を応用して実装することが可能です。

実際の動作は以下のようになります。

![b_gif_0110.gif](https://qiita-image-store.s3.amazonaws.com/0/135729/2d426f25-c7e8-b2bc-b140-d68b0f1a9f01.gif)



###● **1001型** - 「緩 → 急 → 緩」
続いて、controlPoint1(1.0, 0.0), controlPoint2(0.0, 1.0)
「1001型」ですね。

・UIViewPropertyAnimatorで設定

````swift:ViewController.swift
bezierAnimator = UIViewPropertyAnimator(duration: 2.0, controlPoint1: CGPoint(x: 1.0, y: 0.0), controlPoint2: CGPoint(x:0.0, y:1.0)){
    self.circle.center.y += 200
}
````

・UICubicTimingParametersで設定

````swift:ViewController.swift
//cubicTimingParameters
var cubic = UICubicTimingParameters(controlPoint1: CGPoint(x:1.0, y:0.0.), controlPoint2: CGPoint(x:0.0, y:1.0))
````

「1001型」で描画される曲線は、以下のような感じです。

<img width="574" alt="名称未設定_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/135729/f07bb53e-fed2-4526-8e98-90adea792fe2.png">

速度の変化を図にすると、以下のようになります。

|| 開始直後 | 中間① |中間②| 終了間際 |
|:-----:|:-----:|:-----:|:-----:|:-----:|
|緩急|緩|急|急|緩|
|加減速|加速|加速|減速|減速|

上記の図のような速度の変化をつけたい場合には、「0110型」を応用して実装することが可能です。

実際の動作は以下のようになります。

![b_gif_1001.gif](https://qiita-image-store.s3.amazonaws.com/0/135729/84ffcff7-8a6a-9441-eb21-42bf494376e7.gif)



###● **5555型**
最後に、controlPoint1(0.5, 0.5), controlPoint2(0.5, 0.5)
「5555型」です。

・UIViewPropertyAnimatorで設定

````swift:ViewController.swift
bezierAnimator = UIViewPropertyAnimator(duration: 2.0, controlPoint1: CGPoint(x: 0.5, y: 0.5), controlPoint2: CGPoint(x:0.5, y:0.5)){
    self.circle.center.y += 200
}
````

・UICubicTimingParametersで設定

````swift:ViewController.swift
//cubicTimingParameters
var cubic = UICubicTimingParameters(controlPoint1: CGPoint(x:0.5, y:0.5), controlPoint2: CGPoint(x:0.5, y:0.5))
````

![b_gif_5555.gif](https://qiita-image-store.s3.amazonaws.com/0/135729/fe67ac1d-f2f9-5132-f6e2-3a11044d0700.gif)

これは(0.0, 0.0)と(1.0, 1.0)を結ぶ線が直線になるので、
UIViewAnimationCurveの.linearと同じく、全体の速度が等しくなります。

ちなみに、5555でなくとも、4つの座標の値が全て同じであれば全体の速度は等しくなります。

###● **3つを基本形として捉えることで、応用が効く！**

3つの型に分類して整理できたことは以下の2点です

**①ベジエ曲線を使って設定できる速度の変化の種類は大きく分けて「0110型」と「1001型」の2種類**
**②2つのControlPointのX軸同士の差、Y軸同士の差が大きいほど緩急が激しくなる**

この2点を頭に入れておけば、XとYの値を設定しながら、
自分に必要な速度変化を実装することが可能です！！

UICubicTimingParametersのベジエ曲線はとっつき難いですが、
理解できるともの凄く便利ですし、利用の幅も広がります(*´∀`)♪

### **ちなみに・・・**

・今回はベジエ曲線を理解するための便宜上、3つの基本形に分類をしましたが、実際には、**1.0以上の値を座標に設定**したり、**マイナスの値を設定**したりすることも可能です。

なので、より柔軟に思った通りのアニメーションの速度変化を実装できます！！
より深く勉強して、また皆様に情報を共有できればと思いますが、
次の機会に持ち越します。

#最後に
ベジエ曲線は、数学が苦手な筆者にとって非常に理解するのが難しかったですが、
筆者と同じく、「数学が苦手でベジエ曲線なんてサッパリです・・・。」という方の理解の一助にでもなれば幸いです。

次回は、UISpringTimingParametersを中心にまとめていきたいと思います。

最後までお付き合いいただき、誠にありがとうございました。