#4 運用 UIBezierPath 模仿繪製可愛圖案_花媽

Adam
彼得潘的 Swift iOS / Flutter App 開發教室
7 min readJul 26, 2024

練習使用UIBeizerPath 來繪製一張花媽的圖案,本來想說花媽的輪廓應該比較簡單,沒想到實作起來發現花了比想像中更多的時間,還要很有耐心~真心佩服其他人可以畫出更複雜的圖案。

先把要繪製的花媽圖案上傳到ivew網站,可以查到每個地方的座標跟顏色。

https://yangcha.github.io/iview/iview.html

實作中發現繪製的先後順序蠻重要的,可以節省一些畫圖的步驟跟時間,因為view是一層一層疊加,可以遮住的部分就不用管,反正看不出來,例如先繪製頭髮後在畫頭部輪廓。

然後因為花媽的眼睛輪廓和腳看上去比較對稱,所以用CGAffineTransform 鏡像翻轉的方式繪製。

        //眼睛輪廓
let aDegree = Double.pi / 180
let eyePath = UIBezierPath(arcCenter: CGPoint(x: 171, y: 288), radius: 11, startAngle: aDegree * 0, endAngle: aDegree * 360, clockwise: true)
eyePath.close()

let leftEyeLayer = CAShapeLayer()
leftEyeLayer.path = eyePath.cgPath
leftEyeLayer.lineWidth = 1.5
leftEyeLayer.strokeColor = UIColor.black.cgColor
leftEyeLayer.fillColor = UIColor.white.cgColor
view.layer.addSublayer(leftEyeLayer)

//鏡像翻轉
let rightEyeLayer = CAShapeLayer()
rightEyeLayer.path = eyePath.cgPath
let boundingBox = eyePath.cgPath.boundingBox
rightEyeLayer.bounds = boundingBox
rightEyeLayer.position = CGPoint(x: boundingBox.midX, y: boundingBox.midY)
let transform = CGAffineTransform(scaleX: 1, y: 1).translatedBy(x: boundingBox.width, y: 0)
rightEyeLayer.setAffineTransform(transform)
rightEyeLayer.fillColor = UIColor.white.cgColor
rightEyeLayer.strokeColor = UIColor.black.cgColor
rightEyeLayer.lineWidth = 1.5
view.layer.addSublayer(rightEyeLayer)

其他的部分就是用UIBeizerPath的方式慢慢畫,還有如果要在CAShapeLayer顯示的效果相同可以先用.append將路徑合起來,再一起顯示。

        //嘴唇輪廓
let mouthPath = UIBezierPath()
mouthPath.move(to: CGPoint(x: 75, y: 372))
mouthPath.addQuadCurve(to: CGPoint(x: 287, y: 370), controlPoint: CGPoint(x: 186, y: 384))
mouthPath.addCurve(to: CGPoint(x: 295, y: 389), controlPoint1: CGPoint(x: 297, y: 371), controlPoint2: CGPoint(x: 300, y: 377))
mouthPath.addQuadCurve(to: CGPoint(x: 269, y: 394), controlPoint: CGPoint(x: 284, y: 392))
mouthPath.addQuadCurve(to: CGPoint(x: 110, y: 395), controlPoint: CGPoint(x: 183, y: 401))
mouthPath.addQuadCurve(to: CGPoint(x: 74, y: 391), controlPoint: CGPoint(x: 90, y: 394))
mouthPath.addCurve(to: CGPoint(x: 75, y: 372), controlPoint1: CGPoint(x: 56, y: 387), controlPoint2: CGPoint(x: 60, y: 368))
mouthPath.close()

//嘴唇中間線條
let mouthPath2 = UIBezierPath()
mouthPath2.move(to: CGPoint(x: 288, y: 380))
mouthPath2.addQuadCurve(to: CGPoint(x: 193, y: 387), controlPoint: CGPoint(x: 243, y: 387))
mouthPath2.addQuadCurve(to: CGPoint(x: 173, y: 388), controlPoint: CGPoint(x: 183, y: 398))
mouthPath2.addQuadCurve(to: CGPoint(x: 76, y: 382), controlPoint: CGPoint(x: 120, y: 388))

//路徑相加
mouthPath.append(mouthPath2)

let mouthLayer = CAShapeLayer()
mouthLayer.path = mouthPath.cgPath
mouthLayer.lineWidth = 2
mouthLayer.strokeColor = UIColor.black.cgColor
mouthLayer.fillColor = UIColor(red: 255/255, green: 186/255, blue: 255/255, alpha: 1).cgColor
view.layer.addSublayer(mouthLayer)

完成圖:

(左) : 原圖 ; (右) 練習作品

Github:

Reference:

--

--