Swift iOS App | 從程式製作國旗圖案 — Mongo flag

歷經無數個夜晚(其實也只有兩個晚上)終於把這個作業做完了,在上過利用程式繪製國旗的課程後,在繪製前就決定要來選一個曲線和直線都可以挑戰到的國旗,於是最後就選了蒙古國旗,過程中其實也是挺好玩的,就像解謎題一樣,最終完成的成品雖然未達標準但也有7,8分像了

利用這個網站標注座標也是一門學問,後來實作時才發現火的部分好像不需要標注這麼多點…這裡好像不適用在以拉畫貝茲的觀念

https://www.geogebra.org/graphing

過程中難度第二高的應該就屬太極圖是比較難的,一開始打算把陰陽兩片水滴狀的東西分開畫,但過程中礙於Coding ability不足還不夠熟練,所以整個砍掉重練,改成一個大西瓜中間切兩半的模式進行

但中間那條縫卻也是另一個超級大難關,也許是還不熟悉方法,畫完後不是太大就是位置對不起來,後來才發現原來把那條縫append在太極上的兩個小圓上,預覽時同步對位就好話多了,但是這條縫幾乎是已完全目測的方式完成,眼睛快脫窗….

完成後成就感還挺高!

讓火生起來也是一個如同鑽木取火般的超累,繪製的過程中就像下圖依樣上下顛倒真的超燒腦,但是同時間受到彼得潘小王子的提點就突破盲腸了,主要就是要用firePath.move (to: CGPoint (x: 58, y: 38)) 這段語法把位置先固定住,之後就完全可以按照先前的所標註的的座標畫了

import UIKit
// 生成400x200的紅色長方形背景let redFrame = CGRect (x: 0, y: 0, width: 400, height: 200)let redView = UIView (frame: redFrame)redView.backgroundColor = UIColor (red: 230/255, green: 0/255, blue: 25/255, alpha: 1)// 生成400x200的紅色長方形背景let redOvalFrame = CGRect (x: 0, y: 0, width: 400, height: 200)let redOvalView = UIView (frame: redOvalFrame)redOvalView.backgroundColor = UIColor (red: 230/255, green: 0/255, blue: 25/255, alpha: 1)// 生成第二個紅色長方形背景let redFrameTwo = CGRect (x: 50, y: 110, width: 400, height: 200)let redViewTwo = UIView (frame: redFrameTwo)redViewTwo.backgroundColor = UIColor (red: 230/255, green: 0/255, blue: 25/255, alpha: 1)// 生成134x200的中間藍色長方形let blueFrame = CGRect (x: 133, y: 0, width: 134, height: 200)let blueView = UIView (frame: blueFrame)blueView.backgroundColor = UIColor (red: 0/255, green: 102/255, blue: 255/255, alpha: 1)// 生成第一個400x200的黃色長方形背景let firstYellowMaskFrame = CGRect (x: 0, y: 0, width: 400, height: 200)let firstYellowMaskView = UIView (frame: firstYellowMaskFrame)firstYellowMaskView.backgroundColor = UIColor (red: 255/255, green: 217/255, blue: 0/255, alpha: 1)// 生成第二個400x200的黃色長方形背景let secondYellowMaskFrame = CGRect (x: 0, y: 0, width: 400, height: 200)let secondYellowMaskView = UIView (frame: secondYellowMaskFrame)secondYellowMaskView.backgroundColor = UIColor (red: 255/255, green: 217/255, blue: 0/255, alpha: 1)// 生成左邊黃色長方形let firstYellowVerticalFrame = CGRect (x: 30, y: 90, width: 16.5, height: 80)let firstYellowVerticalView = UIView (frame: firstYellowVerticalFrame)firstYellowVerticalView.backgroundColor = UIColor (red: 255/255, green: 217/255, blue: 0/255, alpha: 1)// 生成右邊黃色長方形let secondYellowVerticalFrame = CGRect (x: 86.5, y: 90, width: 16.5, height: 80)let secondYellowVerticalView = UIView (frame: secondYellowVerticalFrame)secondYellowVerticalView.backgroundColor = UIColor (red: 255/255, green: 217/255, blue: 0/255, alpha: 1)// 生成中間上方黃色長方形let firstYellowHorizontalFrame = CGRect (x: 50, y: 103, width: 33.5, height: 6.5)let firstYellowHorizontalView = UIView (frame: firstYellowHorizontalFrame)firstYellowHorizontalView.backgroundColor = UIColor (red: 255/255, green: 217/255, blue: 0/255, alpha: 1)// 生成中間下方黃色長方形let secondYellowHorizontalFrame = CGRect (x: 50, y: 150, width: 33.5, height: 6.5)let secondYellowHorizontalView = UIView (frame: secondYellowHorizontalFrame)secondYellowHorizontalView.backgroundColor = UIColor (red: 255/255, green: 217/255, blue: 0/255, alpha: 1)// 生成中間上方黃色三角形let firstTrianglePath = UIBezierPath()var point = CGPoint (x: 50, y: 90)firstTrianglePath.move(to: point)point = CGPoint (x: 83.5, y: 90)firstTrianglePath.addLine(to: point)point = CGPoint (x: 67, y: 100)firstTrianglePath.addLine(to: point)firstTrianglePath.close()// 生成中間下方黃色三角形let secondTrianglePath = UIBezierPath()secondTrianglePath.move (to: CGPoint (x: 50, y: 160))secondTrianglePath.addLine(to: CGPoint (x: 83.5, y: 160))secondTrianglePath.addLine(to: CGPoint (x: 67, y: 170))secondTrianglePath.close()// 生成中間圓形let ovalPath = UIBezierPath (ovalIn: CGRect (x: 52, y: 50, width: 30, height: 30))// 生成中間月形let moonPath = UIBezierPath (arcCenter: CGPoint (x: 66.5, y: 70), radius: 18, startAngle: CGFloat.pi * 0/180, endAngle: CGFloat.pi * 180/180, clockwise: true)moonPath.addQuadCurve(to: CGPoint (x: 84.5, y: 70 ), controlPoint: CGPoint (x: 66.5, y: 95))moonPath.close()// 生成中間兩個圓形let smallOvalOne = UIBezierPath (ovalIn: CGRect (x: 63, y: 117, width: 8, height: 8))let smallOvalTwo = UIBezierPath (ovalIn: CGRect (x: 63, y: 135.5, width: 8, height: 8))smallOvalOne.append(smallOvalTwo)// 生成中間太極圓形let taichiOval = UIBezierPath (ovalIn: CGRect (x: 50, y: 113.3, width: 33.5, height: 33.5))// 生成中間太極圓形的縫let taichiMiddlePath = UIBezierPath (arcCenter: CGPoint (x: 66.8, y: 140.3), radius: 8.5, startAngle: CGFloat.pi * 270/180, endAngle: CGFloat.pi * 90/180, clockwise: false)//taichiMiddlePath.addLine(to: CGPoint (x: 66.8, y: 148.3))taichiMiddlePath.addArc(withCenter: CGPoint(x: 66.8, y: 140.3), radius: 10.5, startAngle: CGFloat.pi * 90/180, endAngle: CGFloat.pi * 270/180, clockwise: true)taichiMiddlePath.addArc(withCenter: CGPoint (x: 66.8, y: 120.9), radius: 8.5, startAngle: CGFloat.pi * 90/180, endAngle: CGFloat.pi * 270/180, clockwise: false)//taichiMiddlePath.addLine(to: CGPoint (x: 66.8, y: 111.3))taichiMiddlePath.addArc(withCenter: CGPoint(x: 66.8, y: 120.9), radius: 10.5, startAngle: CGFloat.pi * 270/180, endAngle: CGFloat.pi * 90/180, clockwise: true)taichiMiddlePath.close()//因為太極縫是Append在smallOvalOne,所以繪製的時候預覽時,可以用下面的程式碼做預覽,過程中就可得到可靠的參考smallOvalOne.append(taichiMiddlePath)//rightTaichiPathPartOne.addQuadCurve(to: CGPoint (x: 50.3, y: 120.9), controlPoint: CGPoint (x: 54.3, y: 136.9))//rightTaichiPathPartOne.addQuadCurve(to: CGPoint (x: 58.9, y: 103.9), controlPoint: CGPoint (x: 50.3, y: 108.9))// 生火let firePath = UIBezierPath()// 先把點移動到特定的座標firePath.move (to: CGPoint (x: 58, y: 38))firePath.addQuadCurve(to: CGPoint(x: 59, y: 34), controlPoint: CGPoint (x: 59, y: 33))firePath.addCurve(to: CGPoint (x: 62, y: 28), controlPoint1: CGPoint (x: 63, y: 32), controlPoint2: CGPoint (x: 59, y: 31))firePath.addQuadCurve(to: CGPoint(x: 62, y: 30), controlPoint: CGPoint (x: 61, y: 29))firePath.addCurve(to: CGPoint (x: 62, y: 38), controlPoint1: CGPoint (x: 64, y: 32), controlPoint2: CGPoint (x: 62, y: 33.5))firePath.addArc(withCenter: CGPoint (x: 64, y: 38), radius: 2, startAngle: CGFloat.pi * 180/180, endAngle: CGFloat.pi * 0/180, clockwise: false)firePath.addCurve(to: CGPoint (x: 63.5, y: 32.5), controlPoint1: CGPoint (x: 64, y: 33.7), controlPoint2: CGPoint (x: 63, y: 36))firePath.addCurve(to: CGPoint (x: 63.8, y: 24.3), controlPoint1: CGPoint (x: 63.8, y: 28.2), controlPoint2: CGPoint (x: 65.6, y: 28.3))firePath.addQuadCurve(to: CGPoint (x: 66.5, y: 20), controlPoint: CGPoint(x: 64, y: 21.5))firePath.addQuadCurve(to: CGPoint (x: 67.1, y: 23.5), controlPoint: CGPoint(x: 65.1, y: 21.9))firePath.addQuadCurve(to: CGPoint (x: 69.9, y: 30.8), controlPoint: CGPoint(x: 69.9, y: 26.3))firePath.addCurve(to: CGPoint (x: 68.5, y: 38), controlPoint1: CGPoint (x: 69.9, y: 35.3), controlPoint2: CGPoint (x: 69.9, y: 30.1))firePath.addArc (withCenter: CGPoint (x: 70.5, y: 38), radius: 2, startAngle: CGFloat.pi * 180/180, endAngle: CGFloat.pi * 0/180, clockwise: false)firePath.addCurve(to: CGPoint(x: 70.5, y: 33), controlPoint1: CGPoint (x: 70.5, y: 33.7), controlPoint2: CGPoint (x: 70.5, y: 35.8))firePath.addCurve(to: CGPoint (x: 71.5, y: 28.5), controlPoint1: CGPoint (x: 70.5, y: 29.8), controlPoint2: CGPoint (x: 72.8, y: 31.3))firePath.addQuadCurve(to: CGPoint (x: 72.8, y: 31.3), controlPoint: CGPoint (x: 73, y: 29.3))firePath.addCurve(to: CGPoint (x: 73.6, y: 34.5), controlPoint1: CGPoint (x: 73.6, y: 34.5), controlPoint2: CGPoint (x: 71.3, y: 32.4))firePath.addQuadCurve(to: CGPoint (x: 75, y: 38), controlPoint: CGPoint (x: 75.1, y: 35.9))firePath.addArc(withCenter: CGPoint (x: 66.5, y: 38), radius: 8.5, startAngle: CGFloat.pi * 0/180, endAngle: CGFloat.pi * 180/180, clockwise: true)firePath.close()ovalPath.append(firePath)// 把中間上方黃色三角形、下方黃色三角形、中間圓形組合起來firstTrianglePath.append(secondTrianglePath)firstTrianglePath.append(ovalPath)firstTrianglePath.append(moonPath)firstTrianglePath.append(smallOvalOne)firstTrianglePath.append(smallOvalTwo)firstTrianglePath.append(taichiOval)//生成上方組合的黃色 CAShapeLayerlet maskLayer = CAShapeLayer()maskLayer.path = firstTrianglePath.cgPath//生成遮罩firstYellowMaskView.layer.mask = maskLayerfirstYellowMaskView//生成太急兩個小圓的遮罩let maskLayerTwo = CAShapeLayer()maskLayerTwo.path = smallOvalOne.cgPathredOvalView.layer.mask = maskLayerTworedOvalView//把所有的原件組合在一起吧!redView.addSubview(blueView)redView.addSubview(firstYellowVerticalView)redView.addSubview(secondYellowVerticalView)redView.addSubview(firstYellowHorizontalView)redView.addSubview(firstYellowMaskView)redView.addSubview(redOvalView)redView.addSubview(secondYellowHorizontalView)

過程畫面:

畫到這裡時火還沒生起來,火是整個國旗的最後一個物件

--

--