利用 viewDidLoad 客製 App 畫面 (自訂 controller 類別先不用看)

目的:練習設置 viewDidLoad,在 viewDidLoad 裡設置一個 function ,運用此 function 新增多個大小不一、有旋轉角度變化的圖案,並加入漸層 CAGradientLayer()、雪花 CAEmitterCell() 效果。

角落生物連發…

基本架構概念:

import UIKit // 匯入工具class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 步驟一:宣告一個名為 addLizardView 的 function 來繪製角落生物,並貼到 backgroundView 上 // 步驟一的程式碼 }// 步驟二:執行 addLizardView 的 function // 步驟二的程式碼 }}

環境設置:

在 Xcode 開啟一個新專案,interface 選擇使用 storyboard 後,在 ViewController.swift 文件內的 super.viewDidLoad(){ 下面開始編輯

步驟 一 的程式碼:

// 宣告一個名為 addLizardView 的 function 來繪製角落生物,並貼到 backgroundView 上func addLizardView(moveX: CGFloat, moveY: CGFloat, scale: CGFloat, rotateDegree: CGFloat) {// 宣告一個 View ,名為 backgroundView,並定義其尺寸
let backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: 230, height: 220))
// 使用屬性,設定 backgroundView 的背景色 (MistyRose)。
backgroundView.backgroundColor = UIColor.clear
// 宣告一個 View ,名為 bodyView,並套用剛剛設定的 backgroundView 尺寸。
let bodyView = UIView(frame: backgroundView.frame)
// 使用 UIBezierPath() 畫出 身體 的輪廓
let bodyPath = UIBezierPath()
bodyPath.move(to: CGPoint(x: 26, y: 79))
bodyPath.addQuadCurve(to: CGPoint(x: 92, y: 30), controlPoint: CGPoint(x: 40, y: 35))
bodyPath.addQuadCurve(to: CGPoint(x: 188, y: 137), controlPoint: CGPoint(x: 188, y: 28))
bodyPath.addLine(to: CGPoint(x: 188, y: 171))
bodyPath.addQuadCurve(to: CGPoint(x: 203, y: 196), controlPoint: CGPoint(x: 187, y: 189))
bodyPath.addQuadCurve(to: CGPoint(x: 200, y: 208), controlPoint: CGPoint(x: 240, y: 210))
bodyPath.addQuadCurve(to: CGPoint(x: 107, y: 211), controlPoint: CGPoint(x: 156, y: 204))
bodyPath.addQuadCurve(to: CGPoint(x: 90, y: 208), controlPoint: CGPoint(x: 98, y: 214))
bodyPath.addLine(to: CGPoint(x: 66, y: 207))
bodyPath.addQuadCurve(to: CGPoint(x: 38, y: 192), controlPoint: CGPoint(x: 54, y: 214))
bodyPath.addQuadCurve(to: CGPoint(x: 33, y: 149), controlPoint: CGPoint(x: 28, y: 170))
bodyPath.addQuadCurve(to: CGPoint(x: 29, y: 118), controlPoint: CGPoint(x: 36, y: 132))
bodyPath.addQuadCurve(to: CGPoint(x: 26, y: 79), controlPoint: CGPoint(x: 21, y: 99))
bodyPath.close()

// 宣告一個圖層,名為 bodyLayer,並匯入剛剛所定義的輪廓路徑。順便設定路徑的線條顏色、寬度。
let bodyLayer = CAShapeLayer()
bodyLayer.path = bodyPath.cgPath
bodyLayer.fillColor = UIColor(red: 187/255, green: 255/255, blue: 255/255, alpha: 1).cgColor
bodyLayer.strokeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
bodyLayer.lineWidth = 5
// 定義 bodyView 的圖層遮罩要使用 bodyLayer 所定義的內容
bodyView.layer.addSublayer(bodyLayer)
// 左眼 (點):宣告一個圖層,名為 leftEyeLayer,並定義輪廓路徑、線條顏色、寬度。
let leftEyePath = UIBezierPath(ovalIn: CGRect(x: 42, y: 94, width: 13, height: 8))
let leftEyeLayer = CAShapeLayer()
leftEyeLayer.path = leftEyePath.cgPath
let leftEyeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
leftEyeLayer.fillColor = leftEyeColor
// 將 leftEyeLayer 的圖層遮罩加到 bodyViewbodyView.layer.addSublayer(leftEyeLayer)// 右眼 (點):宣告一個圖層,名為 rightEyeLayer,並定義輪廓路徑、線條顏色、寬度。
let rightEyePath = UIBezierPath(ovalIn: CGRect(x: 96, y: 93, width: 13, height: 8))
let rightEyeLayer = CAShapeLayer()
rightEyeLayer.path = rightEyePath.cgPath
let rightEyeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
rightEyeLayer.fillColor = rightEyeColor

// 將 rightEyeLayer 的圖層遮罩加到 bodyView
bodyView.layer.addSublayer(rightEyeLayer)
// 嘴巴 (線條):// 使用 UIBezierPath() 畫出 嘴巴 的輪廓。
let mouthPath = UIBezierPath()
mouthPath.move(to: CGPoint(x: 45, y: 110))
mouthPath.addQuadCurve(to: CGPoint(x: 67, y: 104), controlPoint: CGPoint(x: 58, y: 112))
mouthPath.addQuadCurve(to: CGPoint(x: 92, y: 110), controlPoint: CGPoint(x: 78, y: 111))
// 嘴巴 (線條):宣告一個圖層,名為 mouthLayer,並定義輪廓路徑、線條顏色、寬度。
let mouthLayer = CAShapeLayer()
mouthLayer.path = mouthPath.cgPath
mouthLayer.fillColor = UIColor.clear.cgColor
mouthLayer.strokeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
mouthLayer.lineWidth = 3
// 將 mouthLayer 的圖層遮罩加到 bodyView
bodyView.layer.addSublayer(mouthLayer)
// 左手 (線條):// 使用 UIBezierPath() 畫出 左手 的輪廓。
let leftHandPath = UIBezierPath()
leftHandPath.move(to: CGPoint(x: 60, y: 140))
leftHandPath.addLine(to:CGPoint(x: 68, y: 147))
leftHandPath.addQuadCurve(to: CGPoint(x: 66, y: 155), controlPoint: CGPoint(x: 74, y: 154))
leftHandPath.addQuadCurve(to: CGPoint(x: 48, y: 154), controlPoint: CGPoint(x: 57, y: 161))
// 左手 (線條):宣告一個圖層,名為 leftHandLayer,並定義輪廓路徑、線條顏色、寬度。
let leftHandLayer = CAShapeLayer()
leftHandLayer.path = leftHandPath.cgPath
leftHandLayer.fillColor = UIColor.clear.cgColor
leftHandLayer.strokeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
leftHandLayer.lineWidth = 3
// 將 leftHandLayer 的圖層遮罩加到 bodyView
bodyView.layer.addSublayer(leftHandLayer)
// 左腳 (線條):// 使用 UIBezierPath() 畫出 左腳 的輪廓。
let leftFootPath = UIBezierPath()
leftFootPath.move(to: CGPoint(x: 67, y: 207))
leftFootPath.addQuadCurve(to: CGPoint(x: 52, y: 192), controlPoint: CGPoint(x: 66, y: 194))
// 左腳 (線條):宣告一個圖層,名為 leftFootLayer,並定義輪廓路徑、線條顏色、寬度。
let leftFootLayer = CAShapeLayer()
leftFootLayer.path = leftFootPath.cgPath
leftFootLayer.fillColor = UIColor.clear.cgColor
leftFootLayer.strokeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
leftFootLayer.lineWidth = 3
// 將 leftFootLayer 的圖層遮罩加到 bodyView
bodyView.layer.addSublayer(leftFootLayer)
// 右手 (線條):// 使用 UIBezierPath() 畫出 右手 的輪廓。
let rightHandPath = UIBezierPath()
rightHandPath.move(to: CGPoint(x: 84, y: 141))
rightHandPath.addQuadCurve(to: CGPoint(x: 78, y: 145), controlPoint: CGPoint(x: 80, y: 140))
rightHandPath.addQuadCurve(to: CGPoint(x: 78, y: 155), controlPoint: CGPoint(x: 67, y: 152))
rightHandPath.addQuadCurve(to: CGPoint(x: 97, y: 154), controlPoint: CGPoint(x: 88, y: 161))
// 右手 (線條):宣告一個圖層,名為 rightHandLayer,並定義輪廓路徑、線條顏色、寬度。
let rightHandLayer = CAShapeLayer()
rightHandLayer.path = rightHandPath.cgPath
rightHandLayer.fillColor = UIColor.clear.cgColor
rightHandLayer.strokeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
rightHandLayer.lineWidth = 3
// 將 rightHandLayer 的圖層遮罩加到 bodyView
bodyView.layer.addSublayer(rightHandLayer)
// 右腳 (線條):// 使用 UIBezierPath() 畫出 右腳 的輪廓。
let rightFootPath = UIBezierPath()
rightFootPath.move(to: CGPoint(x: 90, y: 208))
rightFootPath.addQuadCurve(to: CGPoint(x: 104, y: 191), controlPoint: CGPoint(x: 89, y: 193))
// 右腳 (線條):宣告一個圖層,名為 rightFootLayer,並定義輪廓路徑、線條顏色、寬度。
let rightFootLayer = CAShapeLayer()
rightFootLayer.path = rightFootPath.cgPath
rightFootLayer.fillColor = UIColor.clear.cgColor
rightFootLayer.strokeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
rightFootLayer.lineWidth = 3
// 將 rightFootLayer 的圖層遮罩加到 bodyView
bodyView.layer.addSublayer(rightFootLayer)
// 鰭 (線條):// 使用 UIBezierPath() 畫出 鰭 的輪廓。
let finPath = UIBezierPath()
finPath.move(to: CGPoint(x: 179, y: 80))
finPath.addQuadCurve(to: CGPoint(x: 186, y: 108), controlPoint: CGPoint(x: 196, y: 89))
finPath.addQuadCurve(to: CGPoint(x: 195, y: 135), controlPoint: CGPoint(x: 203, y: 119))
finPath.addQuadCurve(to: CGPoint(x: 196, y: 164), controlPoint: CGPoint(x: 204, y: 149))
finPath.addQuadCurve(to: CGPoint(x: 199, y: 191), controlPoint: CGPoint(x: 207, y: 176))
finPath.addLine(to: CGPoint(x: 187, y: 189))
finPath.close()
// 鰭 (線條):宣告一個圖層,名為 finLayer,並定義輪廓路徑、線條顏色、寬度。
let finLayer = CAShapeLayer()
finLayer.path = finPath.cgPath
finLayer.fillColor = CGColor(red: 122/255, green: 197/255, blue: 205/255, alpha: 1)
finLayer.strokeColor = CGColor(red: 65/255, green: 13/255, blue: 0/255, alpha: 1)
finLayer.lineWidth = 3
// 將 finLayer 的圖層遮罩加到 backgroundView (不可加到 bodyView 不然會被跟 bodyView 的遮罩打架,無法正常顯示)
backgroundView.layer.addSublayer(finLayer)
// 在 backgroundView 加入 前景 (bodyView)
backgroundView.addSubview(bodyView)
// 使用屬性,設定 view 的背景色 (MistyRose)。
view.backgroundColor = UIColor(red: 255/255, green: 228/255, blue: 225/255, alpha: 1)
// 在 backgroundView 設定位移、縮放比、旋轉角度
let oneDegree = CGFloat.pi / 180
backgroundView.transform = CGAffineTransform.identity.translatedBy(x: moveX, y: moveY).scaledBy(x: scale, y: scale).rotated(by: oneDegree * rotateDegree)
view.addSubview(backgroundView)

步驟 二 的程式碼:

addLizardView(moveX: 120, moveY: 100, scale: 2, rotateDegree: 17)
addLizardView(moveX: 90, moveY: 300, scale: 1.5, rotateDegree: -17)
addLizardView(moveX: 130, moveY: 470, scale: 1, rotateDegree: 27)

加入漸層效果

let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [CGColor(srgbRed: 255/255, green: 55/255, blue: 33/255, alpha: 1), CGColor(srgbRed: 255/255, green: 228/255, blue: 225/255, alpha: 1)]gradientLayer.startPoint = CGPoint(x: 0, y: 0) // 決定漸層的方向
gradientLayer.endPoint = CGPoint(x: 1, y: 1) // 決定漸層的方向
view.layer.insertSublayer(gradientLayer, at: 0) // 將漸層的 layer 加在最底層。不可使用 addSublayer 加入漸層,不然會變成在最上層把我們設計的畫面覆蓋掉。

加入雪花效果:

在步驟一的程式碼之後再加入下列程式

let smallLizardEmitterCell = CAEmitterCell()smallLizardEmitterCell.contents = UIImage(named: "small_lizard")?.cgImagesmallLizardEmitterCell.birthRate = 10 // 落下圖案的生成速度smallLizardEmitterCell.lifetime = 20 // 出現在畫面上的時間smallLizardEmitterCell.velocity = 100 // 落下圖案的移動速度smallLizardEmitterCell.yAcceleration = 50 // 落下圖案的向下加速度smallLizardEmitterCell.emissionRange = CGFloat.pi // 落下角度let smallLizardEmitterLayer = CAEmitterLayer()smallLizardEmitterLayer.emitterCells = [smallLizardEmitterCell]smallLizardEmitterLayer.emitterPosition = CGPoint(x: view.bounds.width / 2, y: -250) // 落下圖案的生成位置smallLizardEmitterLayer.emitterSize = CGSize(width: view.bounds.width, height: 0) // 落下圖案的生成尺寸smallLizardEmitterLayer.emitterShape = .line // 讓落下圖案的發射路徑為直線smallLizardEmitterCell.scale = 0.5 // 隨機產生落下圖案尺寸的中心值smallLizardEmitterCell.scaleRange = 0.2 // 落下圖案尺寸的中心值的區間值smallLizardEmitterCell.scaleSpeed = -0.03 // 設定落下圖案大小改變的速度,小於 0 會愈來愈小smallLizardEmitterCell.spin = 2 //落下時的轉速中心值smallLizardEmitterCell.spinRange = 3 // 轉速中心值的區間view.layer.addSublayer(smallLizardEmitterLayer) //將圖層 smallLizardEmitterLayer 加入 view 中
此圖使用 GIF 呈現,畫面不是很流暢

--

--