Quartz 2D編程指南 (四) —— Paths路徑(一)

版本記錄

版本號 時間
V1.0 2018.09.04

前言

Quartz 2D框架相信大家都知道,也都一直在使用嚣潜。Quartz 2D的API是純C語言的冬骚,它是一個二維繪圖引擎,同時支持iOS和Mac系統(tǒng)懂算。Quartz 2D的API來自于Core Graphics框架只冻,數(shù)據(jù)類型和函數(shù)基本都以CG作為前綴,接下來幾篇我們就一起來看一下這個框架计技。感興趣可以看上面幾篇文章属愤。
1. Quartz 2D編程指南 (一) —— 簡介(一)
2. Quartz 2D編程指南 (二) —— Quartz 2D概覽(二)
3. Quartz 2D編程指南 (三) —— 圖形上下文(三)

Paths - 路徑

路徑定義一個或多個形狀或子路徑。 子路徑可以包含直線酸役,曲線或兩者住诸。 它可以是開放的或封閉的。 子路徑可以是簡單的形狀涣澡,例如線贱呐,圓,矩形或星形入桂,或者更復雜的形狀奄薇,例如山脈的輪廓或抽象涂鴉。 圖3-1顯示了您可以創(chuàng)建的一些路徑抗愁。 直線(圖中左上角)是虛線馁蒂;線條也可以是實心的呵晚。 彎曲的路徑(在中間的頂部)由幾條曲線組成,是一條開放的路徑沫屡。 同心圓被填充饵隙,但沒有被描邊。 加利福尼亞州是一條封閉的道路沮脖,由許多曲線和線條組成金矛,路徑既有描邊也有填充。 星星說明了填充路徑的兩個選項勺届,您將在本章后面閱讀這些選項驶俊。

Figure 3-1 Quartz supports path-based drawing

在本章中,您將了解構成路徑的構建塊免姿,如何描邊和繪制路徑以及影響路徑外觀的參數(shù)饼酿。


Path Creation and Path Painting - 路徑創(chuàng)建與路徑繪制

路徑創(chuàng)建和路徑繪制是單獨的任務。 首先胚膊,您創(chuàng)建一個路徑故俐。 如果要渲染路徑,請求Quartz繪制它澜掩。 如圖3-1所示,您可以選擇描邊路徑杖挣,填充路徑肩榕,或者描邊和填充路徑。 您還可以使用路徑來約束路徑邊界內其他對象的繪制惩妇,實際上是創(chuàng)建剪切區(qū)域株汉。

圖3-2顯示了已繪制的路徑,其中包含兩個子路徑歌殃。 左邊的子路徑是一個矩形乔妈,右邊的子路徑是由直線和曲線組成的抽象形狀。 每個子路徑都被填充并且其輪廓被描邊氓皱。

Figure 3-2 A path that contains two shapes, or subpaths

圖3-3顯示了獨立繪制的多條路徑路召。 每條路徑都包含一條隨機生成的曲線,其中一些曲線已填充波材,另一些曲線則被描邊股淡。繪圖通過裁剪區(qū)域約束到圓形區(qū)域。

Figure 3-3 A clipping area constrains drawing

The Building Blocks - 構建Block

子路徑由線廷区,弧和曲線構成唯灵。 Quartz還提供了便捷功能,可通過單個函數(shù)調用添加矩形和橢圓隙轻。 點也是路徑的基本構建塊埠帕,因為點定義了形狀的起始和結束位置垢揩。

1. Points - 點

點是x和y坐標,用于指定用戶空間中的位置敛瓷。 您可以調用函數(shù)CGContextMoveToPoint來指定新子路徑的起始位置叁巨。 Quartz跟蹤當前點,這是用于路徑構建的最后位置琐驴。 例如俘种,如果調用函數(shù)CGContextMoveToPoint將位置設置為(10,10),則會將當前點移動到(10,10)绝淡。 如果然后繪制一條長50個單位的水平線宙刘,則該線上的最后一個點(60,10)將成為當前點。 始終從當前點開始繪制直線牢酵,圓弧和曲線悬包。

大多數(shù)情況下,通過向Quartz函數(shù)傳遞兩個浮點值來指定一個點來指定x和y坐標馍乙。 某些函數(shù)要求您傳遞CGPoint數(shù)據(jù)結構布近,該結構包含兩個浮點值。

2. Lines - 線

一條線由其端點定義丝格。 它的起始點始終假定為當前點撑瞧,因此在創(chuàng)建線時,只指定其端點显蝌。 使用函數(shù)CGContextAddLineToPoint將單行線附加到子路徑预伺。

您可以通過調用函數(shù)CGContextAddLines將一系列連接的線添加到路徑中。 您將此函數(shù)傳遞給一系列點曼尊。 第一點必須是第一行的起點酬诀,剩下的點是端點。 Quartz在第一個點開始一個新的子路徑骆撇,并將一個直線段連接到每個端點瞒御。

3. Arcs - 弧

弧是圓弧段。 Quartz提供了兩個創(chuàng)建弧的函數(shù)神郊。 函數(shù)CGContextAddArc從圓創(chuàng)建一個彎曲的段肴裙。 您可以指定圓的中心,半徑和徑向角(以弧度表示)涌乳。 您可以通過指定2 pi的徑向角度來創(chuàng)建整圓践宴。 圖3-4顯示了獨立繪制的多條路徑。 每條路徑包含一個隨機生成的圓爷怀;有些被填滿阻肩,有些被描邊。

Figure 3-4 Multiple paths; each path contains a randomly generated circle

當您想要對矩形的角進行圓角時,CGContextAddArcToPoint函數(shù)是理想的選擇烤惊。 Quartz使用您提供的端點來創(chuàng)建兩條切線乔煞。 您還提供了Quartz切割圓弧的圓的半徑。 弧的中心點是兩個半徑的交點柒室,每個半徑垂直于兩條切線中的一條渡贾。 弧的每個端點都是其中一條切線上的切點,如圖3-5所示雄右。 圓圈的紅色部分實際上是繪制的空骚。

Figure 3-5 Defining an arc with two tangent lines and a radius

如果當前路徑已包含子路徑,則Quartz會將當前點的直線段附加到弧的起始點擂仍。 如果當前路徑為空囤屹,Quartz會在弧的起始點創(chuàng)建一個新的子路徑,并且不會添加初始直線段逢渔。

4. Curves - 曲線

二次和三次Bézier曲線是代數(shù)曲線肋坚,可以指定任意數(shù)量的有趣曲線形狀。 通過將多項式公式應用于起點和終點以及一個或多個控制點來計算這些曲線上的點肃廓。 以這種方式定義的形狀是矢量圖形的基礎智厌。 公式比位數(shù)組更緊湊更容易存儲,并且具有可以在任何分辨率下重新創(chuàng)建曲線的優(yōu)點盲赊。

圖3-6顯示了通過獨立繪制多個路徑創(chuàng)建的各種曲線铣鹏。 每條路徑包含一條隨機生成的曲線;有些被填滿哀蘑,有些被描邊诚卸。

Figure 3-6 Multiple paths; each path contains a randomly generated curve

在許多數(shù)學文本和描述計算機圖形的在線資源中討論了產生二次和三次Bézier曲線的多項式公式,以及如何從公式生成曲線的細節(jié)递礼。 這里不討論這些細節(jié)惨险。

使用CGContextAddCurveToPoint函數(shù)羹幸,使用您指定的控制點和端點脊髓,從當前點追加三次貝塞爾曲線。 圖3-7顯示了由圖中所示的當前點栅受,控制點和端點產生的三次Bézier曲線将硝。 兩個控制點的放置決定了曲線的幾何形狀。 如果控制點都在起點和終點之上屏镊,則曲線向上拱起依疼。 如果控制點都低于起點和終點,則曲線向下拱起而芥。

Figure 3-7 A cubic Bézier curve uses two control points

您可以通過調用CGContextAddQuadCurveToPoint函數(shù)并指定控制點和端點律罢,從當前點追加二次Bézier曲線。 圖3-8顯示了使用相同端點但控制點不同的兩條曲線。 控制點確定曲線拱起的方向误辑。 由于二次曲線僅使用一個控制點沧踏,因此不可能使用二次貝塞爾曲線創(chuàng)建盡任意多的有趣形狀。 例如巾钉,無法使用單個控制點創(chuàng)建交叉翘狱。

Figure 3-8 A quadratic Bézier curve uses one control point

5. Closing a Subpath - 關閉子路徑

要關閉當前子路徑,應用程序應調用CGContextClosePath砰苍。 此函數(shù)添加從當前點到子路徑起點的線段潦匈,并關閉子路徑。 以子路徑起點結束的直線赚导,圓弧和曲線實際上不會關閉子路徑茬缩。 您必須顯式調用CGContextClosePath才能關閉子路徑。

一些Quartz函數(shù)將路徑的子路徑視為應用程序關閉它們辟癌。 這些命令將每個子路徑視為您的應用程序調用CGContextClosePath來關閉它寒屯,隱式地將一個線段添加到子路徑的起始點。

關閉子路徑后黍少,如果應用程序進行額外調用以向路徑添加直線寡夹,圓弧或曲線,Quartz將從剛剛關閉的子路徑的起點開始一個新的子路徑厂置。

6. Ellipses - 橢圓

橢圓本質上是一個壓扁的圓圈菩掏。 您可以通過定義兩個焦點來創(chuàng)建一個焦點,然后繪制位于一定距離的所有點昵济,以便將橢圓上任意點到一個焦點的距離加上到從該點到另一個焦點的距離這個和始終是相同的值智绸。 圖3-9顯示了獨立繪制的多條路徑。 每條路徑包含一個隨機生成的橢圓访忿;有些被填滿瞧栗,有些被描邊。

Figure 3-9 Multiple paths; each path contains a randomly generated ellipse

您可以通過調用函數(shù)CGContextAddEllipseInRect將橢圓添加到當前路徑海铆。 您提供了一個定義橢圓邊界的矩形迹恐。 Quartz使用一系列Bézier曲線近似橢圓。 橢圓的中心是矩形的中心卧斟。 如果矩形的寬度和高度相等(即正方形)殴边,則橢圓為圓形,半徑等于矩形寬度(或高度)的一半珍语。 如果矩形的寬度和高度不相等锤岸,則它們定義橢圓的長軸和短軸。

添加到路徑的橢圓以移動操作開始板乙,以關閉子路徑操作結束是偷,所有移動都以順時針方向定向。

7. Rectangles - 矩形

您可以通過調用函數(shù)CGContextAddRect將矩形添加到當前路徑。 您提供了一個CGRect結構體蛋铆,其中包含矩形的原點及其寬度和高度饿幅。

添加到路徑的矩形以移動操作開始,以關閉子路徑操作結束戒职,所有移動都以逆時針方向定向栗恩。

您可以通過調用CGContextAddRects函數(shù)并提供CGRect結構數(shù)組,將許多矩形添加到當前路徑洪燥。 圖3-10顯示了獨立繪制的多條路徑磕秤。 每個路徑包含一個隨機生成的矩形;有些被填滿捧韵,有些被描邊市咆。

Figure 3-10 Multiple paths; each path contains a randomly generated rectangle

Creating a Path - 創(chuàng)建路徑

如果要在圖形上下文中構造路徑,可以通過調用函數(shù)CGContextBeginPath來發(fā)出Quartz信號再来。接下來蒙兰,通過調用函數(shù)CGContextMoveToPoint,在路徑中設置第一個形狀或子路徑的起點芒篷。建立第一個點后搜变,可以在路徑中添加直線,圓弧和曲線针炉,請記住以下內容:

  • 在開始新路徑之前挠他,請調用函數(shù)CGContextBeginPath
  • 從當前點開始繪制直線篡帕,圓弧和曲線殖侵。空路徑沒有當前點镰烧;你必須調用CGContextMoveToPoint來設置第一個子路徑的起始點拢军,或者調用一個方便的函數(shù),隱式地為你做這個怔鳖。
  • 如果要關閉路徑中的當前子路徑茉唉,請調用函數(shù)CGContextClosePath以將段連接到子路徑的起始點。即使您未明確設置新的起點败砂,后續(xù)路徑調用也會開始新的子路徑赌渣。
  • 繪制弧時魏铅,Quartz在當前點和弧的起點之間繪制一條線昌犹。
  • 添加橢圓和矩形的Quartz例程向路徑添加新的閉合子路徑。
  • 您必須調用繪制函數(shù)來填充或描邊路徑览芳,因為創(chuàng)建路徑不會繪制路徑斜姥。有關詳細信息,請參閱Painting a Path

繪制路徑后铸敏,將從圖形上下文中刷新它缚忧。您可能不希望如此輕易地丟失路徑,特別是如果它描繪了您想要反復使用的復雜場景杈笔。因此闪水,Quartz提供了兩種用于創(chuàng)建可重用路徑的數(shù)據(jù)類型-CGPathRefCGMutablePathRef。您可以調用函數(shù)CGPathCreateMutable來創(chuàng)建可變的CGPath對象蒙具,您可以在其中添加直線球榆,圓弧,曲線和矩形禁筏。 Quartz提供了一組CGPath函數(shù)持钉,這些函數(shù)與The Building Blocks中討論的函數(shù)并行。路徑函數(shù)在CGPath對象上運行篱昔,而不是在圖形上下文上運行每强。這些函數(shù)是:

有關路徑函數(shù)的完整列表邢羔,請參閱Quartz 2D Reference Collection

如果要將路徑附加到圖形上下文桑孩,請調用函數(shù)CGContextAddPath拜鹤。路徑保留在圖形上下文中,直到Quartz繪制它流椒。您可以通過調用CGContextAddPath再次添加路徑敏簿。

注意:您可以通過調用函數(shù)CGContextReplacePathWithStrokedPath將圖形上下文中的路徑替換為路徑的描邊版本。

后記

本篇主要講述了Paths路徑宣虾,感興趣的給個贊或者關注~~~

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末惯裕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子绣硝,更是在濱河造成了極大的恐慌蜻势,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹉胖,死亡現(xiàn)場離奇詭異握玛,居然都是意外死亡够傍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門挠铲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冕屯,“玉大人,你說我怎么就攤上這事拂苹“财福” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵瓢棒,是天一觀的道長搞挣。 經常有香客問我,道長音羞,這世上最難降的妖魔是什么囱桨? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮嗅绰,結果婚禮上舍肠,老公的妹妹穿的比我還像新娘。我一直安慰自己窘面,他們只是感情好翠语,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著财边,像睡著了一般肌括。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上酣难,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天谍夭,我揣著相機與錄音,去河邊找鬼憨募。 笑死紧索,一個胖子當著我的面吹牛,可吹牛的內容都是我干的菜谣。 我是一名探鬼主播珠漂,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼尾膊!你這毒婦竟也來了媳危?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤冈敛,失蹤者是張志新(化名)和其女友劉穎待笑,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莺债,經...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡滋觉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了齐邦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椎侠。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖措拇,靈堂內的尸體忽然破棺而出我纪,到底是詐尸還是另有隱情,我是刑警寧澤丐吓,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布浅悉,位于F島的核電站,受9級特大地震影響券犁,放射性物質發(fā)生泄漏术健。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一粘衬、第九天 我趴在偏房一處隱蔽的房頂上張望荞估。 院中可真熱鬧,春花似錦稚新、人聲如沸勘伺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽飞醉。三九已至,卻和暖如春屯阀,著一層夾襖步出監(jiān)牢的瞬間缅帘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工难衰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留股毫,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓召衔,卻偏偏與公主長得像铃诬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苍凛,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容