Swift iOS App | 作業#6–2 英國國旗 | 從程式製作國旗圖案

Pei W.
彼得潘的 Swift iOS / Flutter App 開發教室
11 min readAug 13, 2018

其實前幾天就完成了國旗的作業,但畫不出三角形這件事讓我耿耿於懷。

就在文章發出去的隔天,彼得潘就寫了下面這篇文章。根本就是我的救星,讓我能做出魂牽夢縈的英國國旗。

製作前

Great Britain

乍看之下,英國國旗似乎有點複雜,上面很多紅藍白色的區塊。認真地觀察了一下,最後決定分成三個部分(也真的一次開了三個playground分開寫,最後再合體)

  • 第一部分:紅底背景 + 白色區塊(x4)
  • 第二部分:藍色三角形(x8)
  • 第三部分:紅色四邊形(x4)

第一部分的程式碼相信大家都很熟悉了,下面主要說明如何做出第二及第三部分的圖形。

畫三角形

import UIKit// 生成300x150的長方形。由於我開了三個playground分別寫,為了讓最後順利合體,長方形的大小設定都要一致。定義的時候也要注意不要重複(如frame, view...)let frameBlue = CGRect(x: 0, y: 0, width: 300, height: 150)let viewBlue = UIView(frame: frameBlue)viewBlue.backgroundColor = UIColor(red: 0.0/255.0, green: 35.0/255.0, blue: 124.0/255.0, alpha: 1)
// View製作完後,開始用UIBezierPath()畫三角形。分別輸入三個頂點的座標(x,y)。
let trianglePath = UIBezierPath()var point = CGPoint(x: 35, y: 0) 第一個點trianglePath.move(to: point)point = CGPoint(x: 125, y: 0) 第二個點trianglePath.addLine(to: point)point = CGPoint(x: 125, y: 45) 第三個點trianglePath.addLine(to: point)trianglePath.close()
// 同個View中可以繪製許多圖形。下面一樣用UIBrzierPath畫了其餘七個藍色三角形
let trianglePath2 = UIBezierPath()var point2 = CGPoint(x:0, y:17)trianglePath2.move(to: point2)point2 = CGPoint(x:0, y:50)trianglePath2.addLine(to: point2)point2 = CGPoint(x:64, y:50)trianglePath2.addLine(to: point2)trianglePath2.close()let trianglePath3 = UIBezierPath()var point3 = CGPoint(x:0, y:100)trianglePath3.move(to: point3)point3 = CGPoint(x:64, y:100)trianglePath3.addLine(to: point3)point3 = CGPoint(x:0, y:133)trianglePath3.addLine(to: point3)trianglePath3.close()let trianglePath4 = UIBezierPath()var point4 = CGPoint(x:35, y:150)trianglePath4.move(to: point4)point4 = CGPoint(x:125, y:105)trianglePath4.addLine(to: point4)point4 = CGPoint(x:125, y:150)trianglePath4.addLine(to: point4)trianglePath4.close()let trianglePath5 = UIBezierPath()var point5 = CGPoint(x:175, y:105)trianglePath5.move(to: point5)point5 = CGPoint(x:175, y:150)trianglePath5.addLine(to: point5)point5 = CGPoint(x:265, y:150)trianglePath5.addLine(to: point5)trianglePath5.close()let trianglePath6 = UIBezierPath()var point6 = CGPoint(x:235, y:100)trianglePath6.move(to: point6)point6 = CGPoint(x:300, y:100)trianglePath6.addLine(to: point6)point6 = CGPoint(x:300, y:133)trianglePath6.addLine(to: point6)trianglePath6.close()let trianglePath7 = UIBezierPath()var point7 = CGPoint(x:300, y:50)trianglePath7.move(to: point7)point7 = CGPoint(x:300, y:17)trianglePath7.addLine(to: point7)point7 = CGPoint(x:235, y:50)trianglePath7.addLine(to: point7)trianglePath7.close()let trianglePath8 = UIBezierPath()var point8 = CGPoint(x:265, y:0)trianglePath8.move(to: point8)point8 = CGPoint(x:175, y:45)trianglePath8.addLine(to: point8)point8 = CGPoint(x:175, y:0)trianglePath8.addLine(to: point8)trianglePath8.close()
// 畫完後用.append將大家合體trianglePath.append(trianglePath2)trianglePath.append(trianglePath3)trianglePath.append(trianglePath4)trianglePath.append(trianglePath5)trianglePath.append(trianglePath6)trianglePath.append(trianglePath7)trianglePath.append(trianglePath8)

// 用CAShapeLayer生成上方這一三角形大家庭
let maskLayerBlue = CAShapeLayer()maskLayerBlue.path = trianglePath.cgPath
- 這邊點來點去的,是在解決型別的問題。參考彼得潘的解釋「CAShapeLayer 可繪製特定的形狀。我們透過設定它的 path 設定形狀。由於 path 型別是 CGPath,所以我們無法將它設為剛剛產生的三角形路徑 trianglePath(型別為 UIBezierPath),而須從 trianglePath 的屬性 path 得到 CGPath 型別的三角形路徑。」
viewBlue.layer.mask = maskLayerBlue
- 透過layer.mask,我們設定的那些路徑圍起來的區域會顯示出來,顏色就是我們最開頭設定的長方形底色。
viewBlue

成果如下,

畫四邊形

做法其實與畫三角形一樣,只不過需要多設定一個頂點的座標。

import UIKit
// 前面都是一樣der,老爺,給我一個長方形!
let frameRed = CGRect(x: 0, y: 0, width: 300, height: 150)let viewRed = UIView(frame: frameRed)viewRed.backgroundColor = UIColor(red: 208/255, green: 55/255, blue: 44/255, alpha: 1)
// 開始畫
let redPath = UIBezierPath()var pointR = CGPoint(x:0, y:0)redPath.move(to: pointR)pointR = CGPoint(x: 100, y: 50)redPath.addLine(to: pointR)pointR = CGPoint(x: 80, y: 50)redPath.addLine(to: pointR)pointR = CGPoint(x: 0, y: 10)redPath.addLine(to: pointR)redPath.close()// 似曾相識的感覺?要特別注意的是在填座標時,務必以順時針或逆時針的方向依序填,不然就會跑出蝴蝶結的效果哦。
左下角不小心綁了可愛蝴蝶結
let redPath2 = UIBezierPath()var pointR2 = CGPoint(x:275, y:0)redPath2.move(to: pointR2)pointR2 = CGPoint(x:300, y:0)redPath2.addLine(to: pointR2)pointR2 = CGPoint(x:200, y:50)redPath2.addLine(to: pointR2)pointR2 = CGPoint(x:180, y:50)redPath2.addLine(to: pointR2)redPath2.close()let redPath3 = UIBezierPath()var pointR3 = CGPoint(x:200, y:100)redPath3.move(to: pointR3)pointR3 = CGPoint(x:223, y:100)redPath3.addLine(to: pointR3)pointR3 = CGPoint(x:300, y:140)redPath3.addLine(to: pointR3)pointR3 = CGPoint(x:300, y:150)redPath3.addLine(to: pointR3)redPath3.close()let redPath4 = UIBezierPath()var pointR4 = CGPoint(x:121, y:100)redPath4.move(to: pointR4)pointR4 = CGPoint(x:100, y:100)redPath4.addLine(to: pointR4)pointR4 = CGPoint(x:0, y:150)redPath4.addLine(to: pointR4)pointR4 = CGPoint(x:21, y:150)redPath4.addLine(to: pointR4)redPath4.close()redPath.append(redPath2)redPath.append(redPath3)redPath.append(redPath4)
// 根本和畫三角形一樣,學一招打天下
let maskLayerRed = CAShapeLayer()maskLayerRed.path = redPath.cgPathviewRed.layer.mask = maskLayerRedviewRed

成果如下,

製作完成

分開寫完三個部分後,終於可以把大家疊在一起了...

Finished !

英國,我們越來越近啦~

--

--