- 通過 UIBezier 在 Layer 上畫一個 Chat 的圖案
- 製作一個 Loading 畫面
DrawingAnimation + CustomLoadingView
Drawing Animation
這裡放了一個名字叫 customCanvas 的 View 在畫面上,我們打算在這個 View 的 Layer 上畫圖。
UIBezierPath
這裡通過 UIBezierPath 來畫出上面這張圖,當然靠想像力來畫有點難度,可以借助 PaintCode 這樣的工具來幫忙。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
private var customPath: UIBezierPath { let bezier2Path = UIBezierPath() bezier2Path.move(to: CGPoint(x: 166.1, y: 48.28)) bezier2Path.addCurve(to: CGPoint(x: 166.1, y: 131.72), controlPoint1: CGPoint(x: 199.3, y: 71.32), controlPoint2: CGPoint(x: 199.3, y: 108.68)) bezier2Path.addCurve(to: CGPoint(x: 89.68, y: 147.91), controlPoint1: CGPoint(x: 145.34, y: 146.13), controlPoint2: CGPoint(x: 116.5, y: 151.53)) bezier2Path.addCurve(to: CGPoint(x: 43.5, y: 169.5), controlPoint1: CGPoint(x: 71.56, y: 159.66), controlPoint2: CGPoint(x: 43.5, y: 169.5)) bezier2Path.addCurve(to: CGPoint(x: 58.33, y: 138.86), controlPoint1: CGPoint(x: 43.5, y: 169.5), controlPoint2: CGPoint(x: 53.16, y: 153.11)) bezier2Path.addCurve(to: CGPoint(x: 45.9, y: 131.72), controlPoint1: CGPoint(x: 53.95, y: 136.8), controlPoint2: CGPoint(x: 49.78, y: 134.42)) bezier2Path.addCurve(to: CGPoint(x: 45.9, y: 48.28), controlPoint1: CGPoint(x: 12.7, y: 108.68), controlPoint2: CGPoint(x: 12.7, y: 71.32)) bezier2Path.addCurve(to: CGPoint(x: 166.1, y: 48.28), controlPoint1: CGPoint(x: 79.09, y: 25.24), controlPoint2: CGPoint(x: 132.91, y: 25.24)) bezier2Path.close() bezier2Path.lineWidth = 9 bezier2Path.stroke() return bezier2Path } |
然後定義 shapeLayer:CAShapeLayer 的基本參數,比如粗細、顏色、填充等等,其中 path 就是上圖的路徑。
1 2 3 4 5 6 7 8 9 |
lazy var shapeLayer:CAShapeLayer = { let layer = CAShapeLayer() layer.path = customPath.cgPath layer.strokeColor = UIColor.yellow.cgColor layer.fillColor = UIColor.clear.cgColor layer.lineWidth = 4.0 layer.lineCap = kCALineCapRound return layer }() |
並將它加入到 customCanvas 當中
1 |
customCanvas.layer.addSublayer(shapeLayer) |
當我們拖動 UiSlider 的時候,改變畫圖的進度
1 |
shapeLayer.strokeEnd = CGFloat(slider.value) |
Custom Loading View
我們另外建了一個 LoadingViewController 用來顯示 Loading 的畫面。
這次要畫 Loading 的圓的路徑就容易多了
1 2 3 4 |
private var customPath: UIBezierPath { let bezierPath = UIBezierPath(ovalIn: CGRect(x: 35, y: 35, width: 75, height: 75)) return bezierPath } |
然後在加入到 shapeLayer 當中
1 2 3 4 5 6 7 8 9 |
lazy var shapeLayer:CAShapeLayer = { let layer = CAShapeLayer() layer.path = customPath.cgPath layer.strokeColor = UIColor.blue.cgColor layer.fillColor = UIColor.clear.cgColor layer.lineWidth = 4.0 layer.lineCap = kCALineCapRound return layer }() |
這次多了自動去執行動畫的部分,通過 repeatCount 可以設定動畫執行的次數,這裡設定了無數次 Float.infinity
1 2 3 4 5 6 7 8 9 |
let animation = CABasicAnimation(keyPath: "strokeEnd") animation.fromValue = 0.0 animation.byValue = 1.0 animation.duration = 1.5 animation.fillMode = kCAFillModeForwards animation.isRemovedOnCompletion = false animation.repeatCount = Float.infinity shapeLayer.add(animation, forKey: "drawChatIconAnimation") |
Present LoadingViewController
這裡把 ViewController 最底層的 View 設定了 backGroundColor = UIColor.clear
這樣搭配設定 modalPresentationStyle / modalTransitionStyle 可以實現 ViewController 半透明的效果。
在 HomeViewController 中, present LoadingViewController
1 2 3 4 |
let VC = LoadingViewController() VC.modalPresentationStyle = .overFullScreen VC.modalTransitionStyle = .crossDissolve present(VC, animated: true, completion: nil) |
筆記
- 思考:在使用 UIBezierPath 畫圖的時候,如何實現 autoLayout 而不是 hard code 方式給予數字。
參考
- 官方文件 – UIBezierPath
- PaintCode Template
- 可以到 Github 上看對應的 Source Code