[Swift]画面内の縁を等速で周り続ける図形

Swiftで下のようなアニメーションを作ったってだけです。
![rectMoveAround.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298379/8cc7a779-91eb-1348-2fbc-73f9b432b9fe.gif)
Storyboardは使わずに、図形はコードから生成してます。
Swift初心者が、作っていくうちに図形の基本とかアニメーションの基本とかちょっと分かってきたので、解説しようと思います。

#コード
```moveAround.swift
import UIKit

class ViewController: UIViewController {

    var screenWidth: CGFloat = 0
    var screenHeight: CGFloat = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()

        //画面のサイズ取得
        screenWidth = self.view.bounds.width
        screenHeight = self.view.bounds.height

        //図形（正方形）生成
        let rect = UIView.init()
        let rectColor = UIColor.blue
        rect.backgroundColor = rectColor
        self.view.addSubview(rect)
        
        moveAround(fig: rect, figSize: 20.0)
    }
    
    //関数
    //図形と（図形は正方形なので）図形の一辺の長さを引数として入力
    func moveAround(fig: UIView, figSize: CGFloat) {
        //一辺を動く時間
        let widthDuration: Double = 1.0
        let heightDuration: Double = widthDuration * Double(screenHeight/screenWidth)

        //初期位置を左上にセット
        fig.frame = CGRect(x: 0, y: 0, width: figSize, height: figSize)

        //アニメーション
        UIView.animate(withDuration: widthDuration, delay: 0, options:[.curveLinear], animations: {
                fig.center.x += (self.screenWidth-figSize)
            }, completion: { finished in
                UIView.animate(withDuration: heightDuration, delay: 0, options: [.curveLinear], animations: {
                        fig.center.y += (self.screenHeight-figSize)
                    }, completion: { finished in
                        UIView.animate(withDuration: widthDuration, delay: 0, options:[.curveLinear], animations: {
                                fig.center.x -= (self.screenWidth-figSize)
                            }, completion: { finished in
                                UIView.animate(withDuration: heightDuration, delay: 0, options: [.curveLinear], animations: {
                                        fig.center.y -= (self.screenHeight-figSize)
                                    }, completion: { finished in
                                        self.moveAround(fig: fig, figSize: figSize)
                                    })
                            })
                    })
            })
    }

}
```
#解説
一つ一つなるべく丁寧に解説していきます。
割と初心者さん向けに書きます。非初心者さんは変なところあったら指摘お願いします。
##画面サイズ取得
まず、画面の縁を動いているので、画面のサイズを取ります。
下のようなコードでとれます。

```getDisplaySize.swift
let screenWidth = self.view.bounds.width
let screenHeight = self.view.bounds.height
```

今回は関数内でも使いたかったので、viewDidLoad()の外で定義してから、中で取ってます。
もっとすっきりしたやり方あったら教えて欲しいですm(_ _)m

##図形生成
今回は正方形を生成してますが、長方形ももちろんできます。
他の図形の生成の仕方は、最後の参考文献にでも他の方の記事を載せるので、そちらで見てみてください。

```makeFigure.swift
//View生成
let figure = UIView.init()
//初期位置とサイズを設定
figure.frame = CGRect(x: 0, y: 0, width: figSize, height: figSize)
//色を設定
let color = UIColor.blue
figure.backgroundColor = color
//画面に表示
self.view.addSubview(figure)
```

CGRectのところを変えることで、他の図形も生成できそうです。

##移動時間（速度）計算
次は関数moveAround()の中です。
関数の引数は、UIView（図形）と図形（正方形）の一辺の長さにしています。

まずは移動時間（速度）を計算します。

```calcDuration.swift
let widthDuration: Double = 1.0
let heightDuration: Double = widthDuration * Double(screenHeight/screenWidth)
```

縦も横も等速になるように計算しています。

##アニメーション
最後にメインとなるアニメーション部分です。
下記がアニメーションの基本文法です。

```animation.swift
UIView.animate(withDuration:[時間], delay:[遅延], options:[オプション], animations:{
    //アニメーション部分
})
```

僕は先ほど計算した時間と、`opition:`に`[.curveLiner]`を入れています。
これは、等速で動かすためのオプションです。
他にも色々あるのですが、この記事では省略します（最後の参考文献に記事を載せます）。

```myAnimation.swift
UIView.animate(withDuration: widthDuration, delay: 0, options:[.curveLinear], animations: {
    //一番目のアニメーション
    //図形のx座標を+方向に画面端まで移動
    fig.center.x += (self.screenWidth-figSize)
}, completion: { finished in
    UIView.animate(withDuration: heightDuration, delay: 0, options: [.curveLinear], animations: {
        //2番目のアニメーション
        //図形のy座標を+方向に画面端まで移動
        fig.center.y += (self.screenHeight-figSize)
    }, ...
```

アニメーションの書き方も他に色々あります。
もちろん移動だけでなく大きさを変えたりもできます（例によって参考文献に記事を載せます）。

連続して他のアニメーショをつけたい場合は、時間やオプションなどの要素に`completion: { finished in }`を加えて、その中にまたアニメーションのコードを書きます。

今回のアニメーションは繰り返し周り続けたいので、4辺全部のアニメーションを終えた後、5つ目のアニメーションとして`self.moveAround(fig: fig, figSize: figSize)`で再び関数を呼び出しています。

#参考文献
図形の生成

- [[swift]UIBezierPathを使った図形の描画 - SUPERSPFTWARE](http://tokyo.supersoftware.co.jp/technology/8011)
- [[iPhone] iOSアプリで図形を描画するにはUIBezierPathを使う - iOSアプリ開発](https://i-app-tec.com/ios/uibezierpath.html)

アニメーション

 - [iOSアプリ開発でアニメーションするなら押さえておきたい基礎 - Qiita](https://qiita.com/hachinobu/items/57d4c305c907805b4a53)
 - [連続したUIViewアニメーションをリピートさせる - Qiita](https://qiita.com/ika_tarou/items/5b30a546d03671db475b)