[Swift]四角く線が進んでいくアニメーション


はじめに

こんな感じのやつを作ります。

サンプル

コード

とりあえずこれをそのままぺッと貼り付けて、シュミレータで確認してみてください!
上のアニメーションと同じものができるはずです。

class ViewController: UIViewController {


    override func viewDidLoad() {
        super.viewDidLoad()

        // グレーの線を作る
        let backLayer = CAShapeLayer()
        backLayer.path = CGPath(rect: CGRect(x: 100, y: 300, width: 200, height: 200), transform: nil)
        backLayer.lineWidth = 20
        backLayer.fillColor = UIColor.clear.cgColor
        backLayer.strokeColor = UIColor.systemGray6.cgColor
        view.layer.addSublayer(backLayer)

               // 赤色の線を作る
        let layer = CAShapeLayer()
        layer.path = CGPath(rect: CGRect(x: 100, y: 300, width: 200, height: 200), transform: nil)
        layer.lineWidth = 5
        layer.fillColor = UIColor.clear.cgColor
        layer.strokeColor = UIColor.red.cgColor
        view.layer.addSublayer(layer)
               
               // 赤色の線にアニメーションをつける
        let circularProgressAnimation = CABasicAnimation(keyPath: "strokeEnd")
        circularProgressAnimation.duration = TimeInterval(5)
        circularProgressAnimation.fromValue = 0
        circularProgressAnimation.toValue = 1.0
        circularProgressAnimation.fillMode = .forwards
        circularProgressAnimation.isRemovedOnCompletion = false
        layer.add(circularProgressAnimation, forKey: "")

    }

}

pathの作成(CAShapeLayer)

まず以下のコードで線をどこに、どんな大きさで設置するかを決めます。
今回は四角形のpathを作っていますが、CGPathのイニシャライザには形を円にしたりできるものもあります。

backLayer.path = CGPath(rect: CGRect(x: 100, y: 300, width: 200, height: 200), transform: nil)

このように変更するとグレーのpathが円になると思います。
赤色の線の方にもこの設定をすることで、円を描くように、赤色の線が進んでいきます。

backLayer.path = CGPath(roundedRect: CGRect(x: 100, y: 300, width: 200, height: 200), cornerWidth: 100, cornerHeight: 100, transform: nil)

残りのlineWidthなどはおそらくわかると思うので割愛します。

線の先の形

赤色の線の方で以下のコードを追加して、もう一度ビルドしてみてください。

layer.lineCap = .round

これを追加することで、アニメーションをするときの赤線の角が丸くなったと思います。
わかりづらい方は
以下のアニメーションの時間を5から10とかにしてみるとわかりやすいかもしれません!

circularProgressAnimation.duration = TimeInterval(5)

アニメーション(CABasicAnimation)

次にアニメーションに関する説明です。
①アニメーションの種類を選択
keyPathによってアニメーションの種類を変えれるみたいです。
例えば"strokeEnd"を"opacity"に変えてみると、赤色の線が徐々に濃くなるようなアニメーションになるはずです。

let circularProgressAnimation = CABasicAnimation(keyPath: "strokeEnd")

その他のkeyPathについては、appleのドキュメントをどうぞ。
https://developer.apple.com/documentation/quartzcore/cabasicanimation

②アニメーションの時間を設定
以下のコードでアニメーションの時間を設定できます

circularProgressAnimation.duration = TimeInterval(5)

③アニメーションの開始、と終わりを選択
fromValueとtoValueに値を入れることで開始と、終わりの位置を決められます。
例えば、以下のように設定すると、すでに半分赤い線が描かれた状態のところからスタートし、一周した位置でアニメーションが終わります。色々値を入れてどんな動きをするか確かめてみてください。0から1の範囲で値を設定できるみたいです。

circularProgressAnimation.fromValue = 0.5
circularProgressAnimation.toValue = 1.0

④その他
以下のコードについてですが、fillModeを.backwardにしたらアニメーションが逆になると思っていましたが、なりませんでした。isRemovedOnCompletionに関してもtrueにしてもアニメーション後に消えることはありませんでした。よくわかりません...

circularProgressAnimation.fillMode = .forwards
circularProgressAnimation.isRemovedOnCompletion = false

おわりに

いかがだったでしょうか。
今回のアニメションは左上の角開始、終了だったのですが、UIBezierPathを使うと、別のところを開始地点にすることもできそうです。UIBezierPathについても勉強してみまーす。