[Swift5]線を描く-静止、アニメーション

#1.はじめに
Swiftで線を引きたいけどUIBezierPath？CAShapeLayer？？なんて方のために、直感的に線を引けるクラスを作ってみました。
基本的な部分しか実装していないのでお好みで改変してもらえばいいかなと思います。

#2.ソースコード
今回のソースコードはこんな感じ。

```Swift:LineView.swift

class LineView: UIView {
    
    var pointList : [CGPoint]!
    var lineWidth : CGFloat! = 1
    var lineColor : UIColor! = UIColor.white
    var fillColor : UIColor! = UIColor.clear
    var isClose :Bool = true
    var isAnimate :Bool = false
    var animateDuretion : CFTimeInterval = 2
    var shapeLayer :CAShapeLayer!
    var path :UIBezierPath! = UIBezierPath()
    
    func setPoint(points:CGPoint...){
        pointList = []
        for point in points{
            self.pointList.append(point)
        }
    }
    
    func setWidth(width:CGFloat){
        self.lineWidth = width
    }
    
    func setFillColor(color:UIColor){
        self.fillColor = color
    }
    
    func open(){
        self.isClose = false
    }
    
    func close(){
        self.isClose = true
    }
    
    func Animate(duration:CFTimeInterval = 2){
        isAnimate = true
        self.animateDuretion = duration
    }
    
    func setLineColor(color:UIColor){
        self.lineColor = color;
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func createAnimateLayer(){
        drawPath()
        shapeLayer = CAShapeLayer()
        shapeLayer.frame = self.frame
        shapeLayer.fillColor = self.fillColor.cgColor
        shapeLayer.strokeColor = self.lineColor.cgColor
        shapeLayer.lineWidth = self.lineWidth
        shapeLayer.path = path.cgPath
        self.layer.addSublayer(shapeLayer)
    }
    
    func drawPath(){
        path = UIBezierPath()
        
        path.move(to: pointList[0])
        for i in 1 ..< pointList.count{
            path.addLine(to: pointList[i])
        }
        
        if(self.isClose){
            path.close()
        }
    }
    
    override func draw(_ rect: CGRect) {
        createAnimateLayer()
        if(isAnimate){
            strokeAnimation()
        }
    }
    
    func strokeAnimation(){
        let strokeAnimation = CABasicAnimation(keyPath: "strokeEnd")
        strokeAnimation.fromValue = 0.0
        strokeAnimation.toValue = 1.0
        strokeAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
        strokeAnimation.duration = self.animateDuretion
        strokeAnimation.fillMode = CAMediaTimingFillMode.forwards
        shapeLayer.add(strokeAnimation, forKey: nil)
    }
    
}

```
#3.解説
各関数のざっくりとした説明は以下になります。
変数の初期値などは必要に応じて変更していただけるといいと思います。

|関数|型|説明|
|:--|:-:|:--|
|setPoint(points:CGPoint...)|-|線を引く対象となる点を設定します。可変長引数のため、複数のCGPointを指定することが可能です。|
|setWidth(width:CGFloat)|-|線の太さを設定します。|
|setFillColor(color:UIColor)|-|塗りつぶしの色を設定します。colorに「UIColor.clear」を指定した場合には塗りつぶしは行われません。|
|open()|-|Pathを開かれた状態にします。始点と終点がパスで結ばれません。|
|close()|-|Pathを閉じた状態にします。始点と終点がパスで結ばれます。|
|Animate(duration:CFTimeInterval = 2)|-|ViewにaddSubviewされたタイミングで線を描画するアニメーションを行います。durationにCFTimeInterval(Double)型を与えることで、アニメーションの長さを変更します。|
|setLineColor(color:UIColor)|-|線の色を設定します。|
|createAnimateLayer()|-|線を描画するShapeLayerを生成します。|
|drawPath()|-|線を描画するためのパスを生成します。|
|draw(_ rect: CGRect)|-|addSubview時などに呼ばれるメソッドです。詳細は調べてみてください。|

#4.使用例
試しに星を描くサンプルを作成しました。

```Swift:ViewController.swift
import UIKit

class LineView: UIView {
...
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let line = LineView(frame: self.view.bounds)
        line.setPoint(points: CGPoint(x: view.frame.midX, y: view.frame.minY),CGPoint(x: view.frame.minX, y: view.frame.maxY),CGPoint(x: view.frame.maxX, y: view.frame.midY),CGPoint(x: view.frame.minX, y: view.frame.midY),CGPoint(x: view.frame.maxX, y: view.frame.maxY))
        line.setFillColor(color: UIColor.init(red: 0/255, green: 0/255, blue: 255/255, alpha: 1))
        line.setLineColor(color: UIColor.init(red: 255/255, green: 255/255, blue: 0/255, alpha: 1))
        line.setWidth(width: 5)
        line.Animate(duration: 5)
        view.addSubview(line)
        
    }

}
```

#5.おわりに
こういった汎用的なクラスをもっておくと作業効率が上がるような気がしますね。
趣味程度であれば言語を自分好みに拡張していくのが楽しくプログラミングを勉強する近道になると考えています。