用程式畫出噗浪彩虹旗─UIBezierPath繪圖練習

◆作業5–2:運用 UIBezierPath 繪製國旗&各種形狀圖案◆

文章懶人包:addQuadCurve&addCurve 程式筆記、用 Illustrator 快速找座標跟控制點、挖空路徑語法(.fillRule evenOdd)

程式範例理解

個人認為這個作業最燒腦部分XDD 理解完真的一帆風順(?)

  1. 直線部分:不難,理解過程筆記在此→
  2. 曲線部分:雖然懂控制點的原理,但是搞不懂起點跟終點的定義跟運作(其實硬要記也可以,但怕誤解要重新洗記憶更痛苦)下面稍微筆記一下理解的內容,用 Peter 這篇文章裡寫的語法去理解

【addQuadCurve】

let path = UIBezierPath(arcCenter: CGPoint(x: 50, y: 50), radius: 50, startAngle: aDegree * 270, endAngle: aDegree * 90, clockwise: true)path.addQuadCurve(to: CGPoint(x: 50, y: 0), controlPoint: CGPoint(x: 80, y: 50))

第一段會先得到:圓心在 (50,50)、半徑 50、從 270 度到 90 度(順時鐘→畫出右半邊)的半圓形
起點位在圓形 270 度的座標位置:(50,0)
終點位在圓形 90 度的座標位置:(50,100)
半圓形是從 (50,0) 畫到 (50,100) 的路徑,並且中間的部份會自動直線補起來,所以畫面上呈現半圓形

addQuadCurve 作用原理(來源:Apple 開發官網說明

第二段為加上曲線,曲線的終點(to: CGPoint)為 (50,0)、控制點為 (80,50)
有了曲線的終點跟控制點,此時曲線的起點為:剛才上一個路徑的終點(上圖中的「A.Current Point」)也就是 90 度位置的 (50,100)

曲線會像上圖一樣─曲線位在 A 點(Current Point)、C點(End Point)之間,並透過 B 點(Control Point)控制曲度

圖片理解(左至右)

【addCurve】

let path = UIBezierPath(arcCenter: CGPoint(x: 50, y: 50), radius: 50, startAngle: aDegree * 180, endAngle: aDegree * 0, clockwise: true)path.addCurve(to: CGPoint(x: 0, y: 50), controlPoint1: CGPoint(x: 50, y: 80), controlPoint2: CGPoint(x: 50, y: 20))

第一段其他同理,只是畫成上半邊的半圓形
起點位在圓形 180 度的座標位置:(0,50)
終點位在圓形 90 度的座標位置:(100,50)

addCurve 作用原理(來源:Apple 開發官網說明

第二段是製作有兩個控制點的曲線,曲線終點為(0,50),起點為上一段半圓形路徑的結束位置 (100,50),並用 Control Point 1 (50,80) 跟 Control Point 2 (50,20) 來控制曲度
如上圖:Control Point 1 會影響曲線起點端的圖形,Control Point 2 則會影響曲線終點的圖形

因此範例中的半圓形,起點在右邊、終點在左邊,起點控制在下面的 Control Point 1、終點控制在上面的 Control Point 2,一邊往下一邊往上變成一個太極的圖案

圖片理解(左至右)

官網說明有提到──必須要先有一個點(起點)addQuadCurve 或 addCurve 才會有作用

當初理解卡住的點就是:看連結敘述得知 to: CGPoint 是曲線的終點,但不知道曲線的起點在哪(怎麼知道哪個點是起點?明明沒寫座標怎麼知道圓形的結束角度就是起點 ←超級鑽牛角尖
尤其看到有兩個控制點的 addCurve 更是混亂,因為起點終點各接一個控制點,沒有搞清楚的話畫出來的曲線會完全相反
後來還開始懷疑是不是搞錯 to: CGPoint 的定義,想說他到底是不是代表終點XD

最後才搞懂原來起點是上一個路徑的終點=現在位置(如果是沒有畫上一個路徑的情況可以用 move(to:) 增加新座標

※以上為自己理解後的結果,如果內容有誤麻煩指正,我也不想記成錯的 (つд⊂)

製圖

因為想要結合國旗+圖案作業,一直思考有什麼是可以兩者一起做的。查參考圖時想起來噗浪(上古神獸如我還是天天在用)曾經有出過彩虹旗商品,圖案便是彩虹旗底+噗浪 Logo,剛好符合這次的作業需求!

噗浪出過的彩虹旗,吉祥物的骨頭還改成愛心超可愛♥(圖片來源:噗浪線上商店商品頁

不過還有個麻煩的點就是:這個商品只有照片,沒有釋出 2D 版本大圖可以直接用,所以要重新製作一張參考圖(後面發現反而是好處XD)

唯一找到的 2D 圖很小,直接影像描圖出來的路徑因為解析度差,坑坑巴巴不好看,此時又覺得做微調又覺得有點浪費時間,赫然發現噗浪官方居然有提供 Logo 原始檔及使用規範 可以使用(肝溫啊)

左:原圖影像描圖/中:超小原圖/右:融合官方提供原檔+把骨頭改為愛心後的最終檔案
完成!2D 版本圖檔截圖,把顏色大小標在旁邊方便查看數值

製作記錄

【Illustrator 座標偷吃步】

上述說到的「重新製圖意外的好處」 就是以拉裡面也會標示錨點的 X、Y 座標!!!剛好這次用的圖曲線多,單看圖片很難判定哪個點才是重要的起/終點(因為圓面多,不像直面多的圖以轉折點判定就好)用以拉的錨點等於可以省去這個判斷的步驟

就是他!

至於 Control Point 要怎麼判斷:如果是兩個錨點的拉桿延伸後會有交叉點是使用 addQuadCurve(只彎一邊的曲線)交叉的點就是 Contorl Point(原理同跟上方理解部分)

如果兩個錨點拉桿延伸沒有交會點(一南一北/平行)就是使用 addCurve。至於哪個點是 Control Point 1、哪個是 Control Point 2 就要看起點終點分別是設哪個(起點是控制 1、終點控制 2 就對了)

記得要用白色的箭頭+顯示控制點(如下圖左方框處)才能看到錨點,找到Contorl Point 時先用鋼筆工具點一個錨點,再用白箭頭查看剛才點的錨點 X、Y 位置就完成啦!

操作上其實 addCurve 比 addQuadCurve 更快XD 拉桿終點點兩下就好。有時候拉桿太長找交叉點找好久,還要拿白紙對位置怕偏掉 (›´ω`‹ )

addQuadCurve 跟 addCurve 的 Control Point 位置判斷

其實 twber 大大有寫一篇更快的方法,直接用 SVG 弄出座標(難怪以前沒有用繪圖軟體開 SVG 時都會充滿看不懂的代碼)需要快速產出的時候感覺很方便:

8/26更新:Peter 也寫了一篇 SVG 轉路徑的教學

【座標】

看了其他文章發現座標會飄是正常(?)所以就算用以拉裡是置中的,放上來也會偏右 (´・ω・`) 因為微調要調全部座標數字太瑣碎,所幸把背景改長一點XD(懶人)

【中空路徑製作】

本來上方圈圈愛心的部分也可以做兩個路徑,再用 append 結合(圈圈+愛心)
但考慮到下方的 P 跟 R 也有空心問題,所以還使用中空的方式製作

語法部分查到的中大多寫:
layer名.fillRule = kCAFillRuleEvenOdd 或 .fillRule = evenOdd
但輸入時提示指說已改名為:
layer名.fillRule = CAShapeLayerFillRule.evenOdd

詳細運作規則可以參考下方連結(其實我自己是沒有看很懂XD 不過有順利成功)

成品

左:原圖 /右:程式碼畫出來的圖

唯一的小瑕疵就是愛心的部分怎麼調控制點都畫不出原圖那種圓順感,圈圈愛心的部分也有點方 ( ˘・з・)

以圖證明(?)上圖真的是程式畫的 XD

【完整程式碼】

貼上來比想像中的長呢…( ´Д`)

理解完程式原理之後開始畫就像著魔(?)一股腦畫完(加上以拉偷吃步找座標跟控制點很快速,預覽出來的圖形準確度很高,就更有成就感的一直畫下去)

原本 path 是分成吉祥物跟文字,再用 append 結合,但後來看了一些前輩的作品,每個圖案都是獨立互不干擾的情況下(沒有線條或圖形要往上疊加)用一個 path 也可以完成

是說在理解時還一度自暴自棄抱怨說:「程式畫圖太難了吧,為什麼我不用以拉畫圖就好」
男友聽到超理性回說:「以拉裡面也是用這個方法在畫圖啊,只是你看不到過程而已」(瞬間醍醐灌頂)
做出各種繪圖軟體的大大們,請收下我的膝蓋,你們都是神啊 。゚(゚´ω`゚)゚。

--

--