0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Viewを常に右回転させたい

Posted at

回転方向は最短

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

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

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

view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 90)
0時
3時

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

view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 330)
3時
11時

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

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

常に右回転させたい

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

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

view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 210)
view.transform = CGAffineTransform(rotationAngle: .pi / 180 * 330)
3時
11時

関数化

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

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)
}
使い方
clockwiseRotate(view, degree: 90.0)   // 現在の角度(0時)から90度(3時)へ回転
clockwiseRotate(view, degree: 330.0)  // 現在の角度(3時)から330度(11時)へ回転

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

ちなみに

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

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




右回転の例

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

w1.gif

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?