Viewを常に右回転させたい

# 回転方向は最短

iOSで`transform`を使ってViewを回転させる場合、回転方向を指定することができない（指定するパラメタが無い）ことはご存知だろう。
回転の方向は、OSが現在の角度から指定された角度へ最短距離（角度）で移動できる方向に決まっているようだ。

以下、時計の針のような図形(View)を用いて説明する。

図形の最初の位置を0時とする。ここから3時の方向へ回転させると、**右**回転（**時計**回り）で回転する。

<table>
<tr><td colspan=3>
<b>view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 90)</b>
</td></tr>
<tr><td style="text-align: center">0時<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/dc3a4158-2ee5-7114-037a-7d9c3d34bac6.png"></td><td><b>→</b></td><td style="text-align: center">3時<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/e8ddea88-36d4-d600-5044-039a18cb0f13.png"></td></tr>
</table>

次に、3時の位置から、11時へ回転させると、**左**回転（**反時計**回り）で回転する。つまり、移動距離が短い（回転させる角度が小さい）方向に回転する。

<table>
<tr><td colspan=3>
<b>view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 330)</b>
</td></tr>
<tr><td style="text-align: center">3時<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/1fd2da9f-527a-371a-6ae0-d9e342a90486.png"></td><td><b>→</b></td></td><td style="text-align: center">11時<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/82f859bf-ede7-2e4e-4fca-fc1a9454ee26.png"></td></tr>
</table>

実験した結果、<i>回転させる角度が180度未満の方向に回転し、3時から9時のように丁度180度の場合は右回りとなった。</i>

なお、`CGAffineTransform`メソッドの`rotationAngle`引数で指定する角度は、相対角度ではなく絶対角度である。

# 常に右回転させたい

では、常に右回転したい場合、どのようにすればよいのか？

『<b><i>角度の小さい方へ回転する</i></b>』特性を利用して、必ず右回りになるような（180度未満の）中継点を設定すればよい。具体的には、3時から11時へ右回転したい場合は、$(330-90)/2+90=$210度を中継してから330度に移動すれば右回転となる。90度**→**210度**→**330度

<table>
<tr><td colspan=3>
<b>view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 210)<br>
view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 330)</b>
</td></tr>
<tr><td style="text-align: center">3時<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/fe467610-ff2f-21c7-e8df-7adc5df36cde.png"></td><td><b>→</b></td></td><td style="text-align: center">11時<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/82f859bf-ede7-2e4e-4fca-fc1a9454ee26.png"></td></tr>
</table>


## 関数化

常に右回転させる処理を関数化すると以下のようになる。
角度の指定方法として度数とラジアンの両方に対応しておく。


```swift
func clockwiseRotate(_ view: UIView, degree: CGFloat) {
    clockwiseRotate(view, radian: degree * .pi / 180)
}
func clockwiseRotate(_ view: UIView, radian: CGFloat) {
    var now = atan2(view.transform.b, view.transform.a)
    if now < 0 { now += .pi * 2 }
    let transit = (radian < now) ? ((radian + .pi * 2) - now) / 2 + now : (radian - now) / 2 + now
    view.transform = CGAffineTransform(rotationAngle: transit)
    view.transform = CGAffineTransform(rotationAngle: radian)
}
```

```swift:使い方
clockwiseRotate(view, degree: 90.0)   // 現在の角度(0時)から90度(3時)へ回転
clockwiseRotate(view, degree: 330.0)  // 現在の角度(3時)から330度(11時)へ回転
```

この関数のポイントは、viewの現在の角度から目的の角度までの中継角度を求めるところで、
・変数`now`にviewの現在の角度を求める。負数になる場合があるので$2\pi$を足して正数化。
・変数`transit`に中継する角度を求める。


# ちなみに

回転方向を確認するためには、アニメーションでビューの変化を可視化する必要がある。回転後のビューを見せるだけなら、回転方向など意味がないので。

```swift:アニメーションでビューの変化を可視化
clockwiseRotate(view, degree: 90)
UIView.animate(withDuration: 1.0, delay: 0.0, options: [], animations: {
    clockwiseRotate(view, degree: 330)
})
```

<br><br><br>


# 右回転の例

次々にランダムな時刻を（常に右回りで）表示してみた。いかがであろうか。

![w1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283293/8701395b-8078-e343-1d0d-eb17aa477d8d.gif)





### 以上