[study#8-2] 調色大師-聖誕美甲選色

選了一張手部的圖片,將指甲的部分去背鏤空,剛好適合來調色

手部指甲原始圖 與 去背鏤空圖

除了上色還要加上圖案,所以要準備相應的圖片與圖層安排

UISlider結合UIColor

將去背鏤空圖,連結至程式頁建立outlet,命名為changeView

將顏色及透明度的Slider,連結至程式頁建立outlet,命名為redSlider, greenSlider, blueSlider, alphaSlider

@IBOutlet weak var changeView: UIImageView!@IBOutlet weak var redSlider: UISlider!@IBOutlet weak var greenSlider: UISlider!@IBOutlet weak var blueSlider: UISlider!@IBOutlet weak var alphaSlider: UISlider!

將顏色及透明度的Slider,連結至程式頁建立action

@IBAction func redSliderFunc(_ sender: Any) {
}
@IBAction func greenSliderFunc(_ sender: Any) {
}
@IBAction func blueSliderFunc(_ sender: Any) {
}
@IBAction func alphaSliderFunc(_ sender: Any) {
}

建立redSliderFunc的內容

@IBAction func redSliderFunc(_ sender: Any) {    changeView.backgroundColor = 
UIColor(displayP3Red: CGFloat(redSlider.value/255),
green: CGFloat(greenSlider.value/255),
blue: CGFloat(blueSlider.value/255),
alpha: CGFloat(alphaSlider.value))
}

(由於我想讓顏色的數值呈現不是介在0與1之前, 而是0到255,所以slider的最大值是設為255,func 內容也因應調整)

4個SliderFunc建立相同的內容,在滑動任一Slider時就能改變UIColor

label顯示數值

將代表各數值的Label,連結至程式頁建立outlet,命名為redLabel, greenLabel, blueLabel, alphaLabel

@IBOutlet weak var redLabel: UILabel!@IBOutlet weak var greenLabel: UILabel!@IBOutlet weak var blueLabel: UILabel!@IBOutlet weak var alphaLabel: UILabel!

在各Slider中添加語法,將數值以Label顯示

@IBAction func alphaSliderFunc(_ sender: Any) {   ...   alphaLabel.text = String(format:"%.2f", alphaSlider.value)}

在alphaSliderFunc內,添加alphaLabel.text語法;

format:”%.2f” 表示格式到小數點第二位

在blueSliderFunc內,添加blueLabel.text語法;

由於希望是整數,所以先添加一個常數 let blueInt = Int(blueSlider.value)

@IBAction func blueSliderFunc(_ sender: Any) {   ...   let blueInt = Int(blueSlider.value)   blueLabel.text = String(blueInt)}

redSliderFunc跟greenSliderFunc用同樣的方式添加。

分區調整顏色

此範例分為左右手可調整不同顏色,最上層的去背鏤空圖至少需分為兩塊(我使用的圖片因位置不易直接切分為左右手,實際切分為3個view)

@IBOutlet weak var rightView: UIImageView!@IBOutlet weak var leftView: UIImageView!

其他操作步驟跟以上一樣,就能為左手與右手分開調色

漸層顯示

比起用Slider顯示漸層,我比較想使用“開關”來顯示漸層

Switch 及 Label

加入Switch開關功能

將Switch連結至程式頁建立action

@IBAction func funcRiGra(_ sender: UISwitch) {
}

在此func中添加if else語法

if sender.isOn {
}
else{
}

isOn表示開啟,此時else表示關閉;

將不同狀態所要顯示的內容放入{}內即可

先前調色是採用backgroundColor,而漸層色是用CAGradientLayer與View

所以我使用多添加一個全透明的imageView

將全透明View連結至程式頁建立outlet,命名rightGraView

@IBOutlet weak var rightGraView: UIImageView!

建立CAGradientLayer

let graRightLayer = CAGradientLayer()graRightLayer.frame = rightGraView.bounds

設定漸層色1: Red: 1, green: 0, blue: 0

設定漸層色2: Red: 0, green: 0.5, blue: 1

graRightLayer.colors = [UIColor.init(displayP3
Red: 1, green: 0, blue: 0, alpha: 1).cgColor, UIColor.init(displayP3
Red: 0, green: 0.5, blue: 1, alpha: 1).cgColor]

將view與漸層遮罩結合

rightGraView.layer.addSublayer(graRightLayer)

設定switch開啟時有漸層,關閉時無漸層;所以將漸層語法放進if

@IBAction func funcRiGra(_ sender: UISwitch) { let graRightLayer = CAGradientLayer() if sender.isOn {  graRightLayer.frame = rightGraView.bounds  graRightLayer.colors = [UIColor.init(displayP3
Red: 1, green: 0, blue: 0, alpha: 1).cgColor,
UIColor.init(displayP3Red: 0, green: 0.5,
blue: 1, alpha: 1).cgColor]
rightGraView.layer.addSublayer(graRightLayer)
}
else{ }}

但是這裡事情沒那麼簡單!!

在漸層view之上還有一層有backgroundColor的去背鏤空view

因此需要讓最上層的backgroundColor透明度alpha為0,才能看到漸層view

去背鏤空view的alpha: 0;漸層view的alpha: 1

在關閉switch時,漸層view的alpha設為0,並使去背鏤空view同slider效果

if sender.isOn {   changeView.backgroundColor = UIColor(displayP3
Red: 1, green: 1, blue: 1, alpha: 0)
rightView.backgroundColor = UIColor(displayP3
Red: 1, green: 1, blue: 1, alpha: 0)
leftView.backgroundColor = UIColor(displayP3
Red: 1, green: 1, blue: 1, alpha: 0)
graRightLayer.frame = rightGraView.bounds graRightLayer.colors = [UIColor.init(displayP3
Red: 1, green: 0, blue: 0, alpha: 1).cgColor,
UIColor.init(displayP3Red: 0, green: 0.5,
blue: 1, alpha: 1).cgColor]
rightGraView.layer.addSublayer(graRightLayer)
}
else{ changeView.backgroundColor = UIColor(displayP3Red: CGFloat(redSlider.value/255), green: CGFloat(greenSlider.value/255), blue: CGFloat(blueSlider.value/255), alpha: CGFloat(alphaSlider.value)) rightView.backgroundColor = UIColor(displayP3Red: CGFloat(redSlider.value/255), green: CGFloat(greenSlider.value/255), blue: CGFloat(blueSlider.value/255), alpha: CGFloat(alphaSlider.value)) leftView.backgroundColor = UIColor(displayP3Red: CGFloat(leftRedSlider.value/255), green: CGFloat(leftGreenSlider.value/255), blue: CGFloat(leftBlueSlider.value/255), alpha: CGFloat(leftAlphaSlider.value)) graRightLayer.frame = rightGraView.bounds graRightLayer.colors = [UIColor.init(displayP3
Red: 1, green: 0, blue: 0, alpha: 0).cgColor,
UIColor.init(displayP3Red: 0, green: 0.5,
blue: 1, alpha: 0).cgColor]
rightGraView.layer.addSublayer(graRightLayer)}

改變漸層方向

在layer設定startPoint與endPoint,這裡 x 與 y 只能設定1或0

才能顯示需要效果,例如:由右上到左下

graLeftLayer.startPoint = CGPoint(x: 1, y: 0)graLeftLayer.endPoint = CGPoint(x: 0, y: 1)

開啟漸層時,同時可以關閉Slider以避免干擾

開關關閉時,再將slider設定為可使用

@IBAction func funcRiGra(_ sender: UISwitch) { ... if sender.isOn {

alphaSlider.isEnabled = false
redSlider.isEnabled = false greenSlider.isEnabled = false blueSlider.isEnabled = false ... } else{ alphaSlider.isEnabled = true redSlider.isEnabled = true greenSlider.isEnabled = true blueSlider.isEnabled = true ... }}

搭配亂數,顯示隨機選色

用button來進行亂數選色:將button連結至程式頁建立action

@IBAction func randomLButton(_ sender: UIButton){
}

有red, green, blue, alpha這4個需要用亂數產出;

定義4個常數並帶入亂數語法

@IBAction func randomLButton(_ sender: UIButton){

let
redLrandom = Double.random(in: 0...1)
let greenLrandom = Double.random(in: 0...1) let blueLrandom = Double.random(in: 0...1) let alphaLrandom = Double.random(in: 0...1)}

將View.backgroundColor的顏色數值改為CGFloat(亂數常數)

@IBAction func randomLButton(_ sender: UIButton){  ...   changeView.backgroundColor = UIColor(displayP3
Red: CGFloat(redLrandom),
green: CGFloat(greenLrandom),
blue: CGFloat(blueLrandom),
alpha: CGFloat(alphaLrandom))
}

讓亂數數值連動到Slider與Label:

在randomLButton內變更slider.value;
由於我的顏色slider最大值是255,所以顏色的數值要乘上255

leftAlphaSlider.value = Float(alphaLrandom)leftRedSlider.value = Float(redLrandom) * 255leftGreenSlider.value = Float(greenLrandom) * 255leftBlueSlider.value = Float(blueLrandom) * 255

在randomLButton內添加Label文字變更;
需要整數與小數2位等格式,如下

let redRInt = Int(redLrandom * 255)let greenRInt = Int(greenLrandom * 255)let blueRInt = Int(blueLrandom * 255)alphaLabel.text = String(format:"%.2f", alphaLrandom)redLabel.text = String(redRInt)greenLabel.text = String(greenRInt)blueLabel.text = String(blueRInt)

亂數與漸層搭配

想試試用亂數產生漸層;
且剛好有左右手兩個區塊的silder,在開啟漸層時可以運用!

由於設定漸層時alpha為1,所以只要多增加3個亂數常數

let redRrandom = Double.random(in: 0...1)let greenRrandom = Double.random(in: 0...1)let blueRrandom = Double.random(in: 0...1)

把switch連結至程式頁建立outlet,命名gradationSwitch

@IBOutlet weak var gradationSwitch: UISwitch!

在randomLButton內建立if else

@IBAction func randomLButton(_ sender: UIButton) {  ...  if gradationSwitch.isOn{
}
else{
}
}

先前在switch的func內,可以使用sender .isOn,表示是自己的開關;

但在button的func內,需指明是哪一個變數的開關,故須先將switch建立outlet,才能指明是gradationSwitch.isOn

將先前寫好的內容移至else中,須注意若有共用常數需寫在if 之前

@IBAction func randomLButton(_ sender: UIButton) {  let redLrandom = Double.random(in: 0...1)
let greenLrandom = Double.random(in: 0...1)
let blueLrandom = Double.random(in: 0...1)
let alphaLrandom = Double.random(in: 0...1)
let redRrandom = Double.random(in: 0...1)
let greenRrandom = Double.random(in: 0...1)
let blueRrandom = Double.random(in: 0...1)
if gradationSwitch.isOn{ }
else{
changeView.backgroundColor = UIColor(displayP3
Red: CGFloat(redLrandom),
green: CGFloat(greenLrandom),
blue: CGFloat(blueLrandom),
alpha: CGFloat(alphaLrandom))
}}

再至if 內編寫開啟漸層時內顯示目標,將原來的Layer數值換成亂數常數

graRightLayer.colors = [UIColor.init(displayP3Red: 1, green: 0, blue: 0, alpha: 1).cgColor, UIColor.init(displayP3Red: 0, green: 0.5, blue: 1, alpha: 1).cgColor]

因為在不同func使用同一個常數graRightLayer,

所以要將以下常數放在func外面

let graRightLayer = CAGradientLayer()

if gradationSwitch.isOn{  graRightLayer.frame = rightGraView.bounds  graRightLayer.colors = [UIColor.init(displayP3
Red: CGFloat(redRrandom),
green: CGFloat(greenRrandom),
blue: CGFloat(blueRrandom),
alpha: 1
).cgColor, UIColor.init(displayP3
Red: CGFloat(redLrandom),
green: CGFloat(greenLrandom),
blue: CGFloat(blueLrandom),
alpha: 1
).cgColor]
rightGraView.layer.addSublayer(graRightLayer)}

先前開啟漸層時,slider不可用,現在要改成轉換slider用途

原本2個Label:右手美甲,左手美甲,
連結至程式頁建立outlet,命名upLabel, bottomLabel

@IBOutlet weak var upLabel: UILabel!@IBOutlet weak var bottomLabel: UILabel!

修改switch,除了alphaSlider外,讓其他slider可用

@IBAction func funcRiGra(_ sender: UISwitch) {  ...  if sender.isOn {

alphaSlider.isEnabled = false
redSlider.isEnabled = true greenSlider.isEnabled = true blueSlider.isEnabled = true upLabel.text = "上層漸變" bottomLabel.text = "下層漸變" ... } else{ alphaSlider.isEnabled = true redSlider.isEnabled = true greenSlider.isEnabled = true blueSlider.isEnabled = true upLabel.text = "右手美甲" bottomLabel.text = "左手美甲" ... }}

在RGB slider func裡增加if else,將原本內容移至else中,

並在if內增加漸層時的效果

將原本設定Layer時color為固定數值的方式,改為個別的slider.value

@IBAction func greenSliderFunc(_ sender: Any) {  if gradationSwitch.isOn {   ...   graRightLayer.colors = [UIColor.init(displayP3
Red: CGFloat(redSlider.value/255),
green: CGFloat(greenSlider.value/255),
blue: CGFloat(blueSlider.value/255),
alpha: 1
).cgColor, UIColor.init(displayP3
Red: CGFloat(leftRedSlider.value/255),
green: CGFloat(leftGreenSlider.value/255),
blue: CGFloat(leftBlueSlider.value/255),
alpha: 1).cgColor]
... } else{ ... }
}

如此,上下漸變的顏色可以根據slider更換

然後再調整button的slider跟label顯示:

在if 內分別顯示上層漸變與下層漸變的數值

@IBAction func randomLButton(_ sender: UIButton) {  ...  if gradationSwitch.isOn{    ...    alphaLabel.text = "1"    redLabel.text = String(redRInt)    greenLabel.text = String(greenRInt)    blueLabel.text = String(blueRInt)    alphaSlider.value = 1    redSlider.value = Float(redRrandom) * 255    greenSlider.value = Float(greenRrandom) * 255    blueSlider.value = Float(blueRrandom) * 255    alphaLLabel.text = "1"    redLLabel.text = String(redRandom)    greenLLabel.text = String(greenRandom)    blueLLabel.text = String(blueRandom)    leftAlphaSlider.value = 1    leftRedSlider.value = Float(redLrandom) * 255    leftGreenSlider.value = Float(greenLrandom) * 255    leftBlueSlider.value = Float(blueLrandom) * 255  }  else{    ...  }
}

如此,在開啟漸層時點選隨機選色,可亂數產生漸層(也有單色的可能)

並且漸層的亂數數值可顯示於label

(本次調色切分為3個view,裡面語法更亂一點,但總算先完成效果了)

專案的 GitHub 連結:

--

--

Yolanda H.
彼得潘的 Swift iOS / Flutter App 開發教室

悠琅妲之愛梯熙緹推敲推敲潑墨坊 { iOS App | website SEO | Python | Aroma | Zumba | Chinese Poems | Tabletop game }