# 17 調色大師 — 滿滿色素的北極熊冰淇淋

***
彼得潘的 Swift iOS / Flutter App 開發教室
11 min readJun 11, 2022

練習目的: 熟練 outlet / action / UISlider / UIColor / Switch

底圖來源 https://beauty-upgrade.tw/60882/

前陣子流行的網紅冰淇淋,這麼的紅我怎麼至今還沒吃過呢!為了解解渴,所以做了可以任意調色北極熊冰淇淋,想要多少色素就有多少色素,簡直夢幻至極~

使用到的功能:

  • 利用 Slider 進行調色
  • 利用 Random 隨機調色
  • 利用 Switch 切換開關、Enable & Disable
  • 利用 CAEmitterLayer 製造下雪效果
  • 利用 if else 讓開關判斷操作

製作畫面

  • 將北極熊冰淇淋圖片去背,並加入畫面中
  • Slider:用以調整三原色、透明度、漸層 Slider 的數值
  • Button:用以隨機控制三原色及透明度 Slider 的數值
  • Switch:放了兩個 Switch,一個用來觸發三原色、透明度、漸層 Slider 的 Enable & Disable,一個用來控制下雪效果的開關
  • Lable:分別顯示元件的說明及 Slider 的表現數值

設定 IBOutlet

@IBOutlet weak var redSlider: UISlider!@IBOutlet weak var greenSlider: UISlider!@IBOutlet weak var blueSlider: UISlider!@IBOutlet weak var alphaSlider: UISlider!@IBOutlet weak var gradientSlider: UISlider!@IBOutlet weak var imageView: UIImageView!@IBOutlet weak var redLabel: UILabel!@IBOutlet weak var greenLabel: UILabel!@IBOutlet weak var blueLabel: UILabel!@IBOutlet weak var alphaLabel: UILabel!@IBOutlet weak var gradientSwitch: UISwitch!@IBOutlet weak var gradientView: UIImageView!@IBOutlet weak var randomButton: UIButton!@IBOutlet weak var switchLabel: UILabel!@IBOutlet weak var emitterSwitch: UISwitch!

使用 slider 調整 RGB 三色,並以 Label 顯示 Slider 目前的數值

由於 Value 的型別是 Float、UIColor 的型別是 CGFloat,因此在 RGB 內必須要給 CGFloat,因此可寫 CGFloat ( ) 生一個 CGFloat 出來,( ) 內可以放 Float 型別的參數

@IBAction func changeColor(_ sender: Any) {imageView.backgroundColor = UIColor(red: CGFloat(redSlider.value), green: CGFloat(greenSlider.value), blue: CGFloat(blueSlider.value), alpha: CGFloat(alphaSlider.value))//Slider的數值顯示到小數點後第二位redLabel.text = String(format: "%.2f", redSlider.value) greenLabel.text = String(format: "%.2f", greenSlider.value)blueLabel.text = String(format: "%.2f", blueSlider.value)alphaLabel.text = String(format: "%.2f", alphaSlider.value)}

使用亂數 Random 設置隨機選色按鈕

讓 Slider 任意自行滑動以及 Label 數字隨之變化顯示當前停留的值

@IBAction func colorRandom(_ sender: Any) {//宣告各色的RandomredSlider.value = Float.random(in: 0...1)greenSlider.value = Float.random(in: 0...1)blueSlider.value = Float.random(in: 0...1)alphaSlider.value = Float.random(in: 0...1)imageView.backgroundColor = UIColor(red: CGFloat(redSlider.value), green: CGFloat(greenSlider.value), blue: CGFloat(blueSlider.value), alpha: CGFloat(alphaSlider.value))redLabel.text = String(format: "%.2f", redSlider.value)        greenLabel.text = String(format: "%.2f", greenSlider.value)        blueLabel.text = String(format: "%.2f", blueSlider.value)        alphaLabel.text = String(format: "%.2f", alphaSlider.value)}

利用 CAGradientLayer 製作漸層

@IBAction func changeGradientColor(_ sender: Any) {let gradientLayer = CAGradientLayer() //產生漸層gradientLayer.colors = [CGColor(red: 1, green: 182/255, blue: 193/255, alpha: 1),        CGColor(red: 230/255, green: 230/255, blue: 250/255, alpha: 1)        ]gradientLayer.frame = gradientView.bounds //設定漸層layer的大小和位置gradientLayer.locations = [0.0,NSNumber(value:gradientSlider                                                    .value)] //變化的方向gradientView.layer.addSublayer(gradientLayer) //把漸層加到宣告的layer上}

參考文章:

設定漸層 Switch

@IBAction func gradientSwitchControl(_ sender: Any) {//當Switch為開時,漸層 Slider 可以操作、其餘Slider和隨機變色按鈕不能操作,且Slider回到起始點、預設為無顏色if gradientSwitch.isOn{redSlider.isEnabled = falsegreenSlider.isEnabled = falseblueSlider.isEnabled = falsealphaSlider.isEnabled = falserandomButton.isEnabled = falsegradientSlider.isEnabled = trueimageView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0)redSlider.value = 0greenSlider.value = 0blueSlider.value = 0alphaSlider.value = 0 } else { //當Switch為關時,漸層 Slider 不可以操作、其餘Slider和隨機變色按鈕可以操作gradientSlider.isEnabled = falseredSlider.isEnabled = truegreenSlider.isEnabled = trueblueSlider.isEnabled = true alphaSlider.isEnabled = truerandomButton.isEnabled = true} }

CAEmitterLayer 製造下雪效果

func snowEmitter(){let snowEmitterCell = CAEmitterCell()        snowEmitterCell.contents = UIImage(named: "snow")?.cgImage        snowEmitterCell.birthRate = 10snowEmitterCell.lifetime = 20snowEmitterCell.velocity = 10snowEmitterCell.velocityRange = 10        snowEmitterCell.yAcceleration = 10snowEmitterCell.scale = 1snowEmitterCell.scaleRange = 1snowEmitterCell.scaleSpeed = -0.02snowEmitterCell.spin = 0.5snowEmitterCell.spinRange = 0.5snowEmitterCell.emissionRange = .pi*0.5        snowEmitterLayer.emitterCells = [snowEmitterCell]        snowEmitterLayer.position = CGPoint(x: view.bounds.width/2, y: -100)        snowEmitterLayer.emitterSize = CGSize(width: view.bounds.width, height: 0)snowEmitterLayer.emitterShape = .line        view.layer.addSublayer(snowEmitterLayer)}

設定下雪 Switch

因為要控制 particle 發射與否。因此發射粒子圖層只需要在 Controller 內各生成一個 CAEmitterLayer( ),來控制顯示圖層,不用每次都重新生成一次 CAEmitterLayer(如果把 CAEmitterLayer( ) 生成在 function 內,則每次呼叫 function 時都會重新生成 CAEmitterLayer,當然 CAEmitterLayer 的樣式設定還是可以寫在 function 中)

let snowEmitterLayer = CAEmitterLayer()

串連Button設定觸發後的行為

當Switch為開時,呼叫下雪Function,說明文字變為“開啟下雪” ; 當Switch為關時,將下雪效果從Superlayer中移除,說明文字變為“關閉下雪”

@IBAction func changeEmitterStatus(_ sender: Any) {//當Switch為開時,呼叫下雪Function,說明文字變為“開啟下雪”if emitterSwitch.isOn{snowEmitter()switchLabel.text = "開啟下雪"} else {//當Switch為關時,將下雪效果從Superlayer中移除,說明文字變為“關閉下雪”snowEmitterLayer.removeFromSuperlayer()switchLabel.text = "關閉下雪"}}

預設 APP 一開啟就下雪,因此在 viewDidLoad 中呼叫下雪 Function

override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view.snowEmitter()}

參考文章

上傳 GitHub

--

--