引言:
UIBezierPath類只是CGPathRef數(shù)據(jù)類型和path繪圖屬性的一個(gè)封裝。
參考:
摘要:
1.一般的矢量圖形軟件通過它來精確畫出曲線,貝茲曲線由線段與節(jié)點(diǎn)組成,節(jié)點(diǎn)是可拖動(dòng)的支點(diǎn),線段像可伸縮的皮筋,我們在繪圖工具上看到的鋼筆工具就是來做這種矢量曲線的。
2.出現(xiàn)的原因:
由于用計(jì)算機(jī)畫圖大部分時(shí)間是操作鼠標(biāo)來掌握線條的路徑,與手繪的感覺和效果有很大的差別。即使是一位精明的畫師能輕松繪出各種圖形,拿到鼠標(biāo)想隨心所欲的畫圖也不是一件容易的事。這一點(diǎn)是計(jì)算機(jī)萬萬不能代替手工的工作,所以到目前為止人們只能頗感無奈。使用貝塞爾工具畫圖很大程度上彌補(bǔ)了這一缺憾。
貝塞爾曲線是計(jì)算機(jī)圖形圖像造型的基本工具,是圖形造型運(yùn)用得最多的基本線條之一。它通過控制曲線上的四個(gè)點(diǎn)(起始點(diǎn)、終止點(diǎn)以及兩個(gè)相互分離的中間點(diǎn))來創(chuàng)造、編輯圖形。
說到底,就是直接用這個(gè)類來畫二維圖形,也是666
找到一篇很不錯(cuò)的博客
摘要出一部分,有空的話,看看全文比較好
ps:發(fā)現(xiàn)該作者的其它博客也很不錯(cuò),有空看看
1、CAShapeLayer繼承自CALayer,可以使用CALayer的所有屬性值
2、CAShapeLayer需要與貝塞爾曲線配合使用才有意義
3、使用CAShapeLayer與貝塞爾曲線可以實(shí)現(xiàn)不在view的drawRect方法中畫出有一些想要的圖形
4、CAShapeLayer屬于CoreAnimation框架,其動(dòng)畫渲染直接提交到手機(jī)的GPU當(dāng)中,相較于view的drawRect方法使用CPU渲染而言,其效率極高,能大大優(yōu)化內(nèi)存使用情況。
個(gè)人經(jīng)驗(yàn):可以重寫UIView的子類中的drawRect來實(shí)現(xiàn)進(jìn)度條效果,但是UIView的drawRect是用CPU渲染實(shí)現(xiàn)的,而使用CAShapeLayer效率更高,因?yàn)樗玫氖荊PU渲染。
創(chuàng)建的步驟:
(1)創(chuàng)建一個(gè)Bezier path對象(這沒什么好說的)
(2)使用方法moveToPoint:去設(shè)置初始線段的起點(diǎn)。這就不得不吐槽了,為什么是moveToPoint呢?這命名讓人感覺好像終點(diǎn)的樣子,假如改成moveFromPoint多好,能降低誤導(dǎo)概率
[_path moveToPoint:CGPointMake(startX, startY)];
(3)添加line或者curve去定義一個(gè)或者多個(gè)subpaths。
line是直線段,curve是曲線段
//3.1三次貝塞爾曲線舉個(gè)例子:(三次和二次addQuadCurveToPoint,貌似咋一看最大的區(qū)別是能加三個(gè)還是兩個(gè)參數(shù))
//三點(diǎn)曲線--讓小方塊的下滑線路
[_path addCurveToPoint:CGPointMake(0, 600)/*終點(diǎn)*/ controlPoint1:CGPointMake(startX, startY) /*起點(diǎn)*/controlPoint2:CGPointMake(startX - 180, startY - 200)];/*中途點(diǎn)*/
//3.2直線繪制多邊形舉個(gè)例子:
多邊形是一些簡單的形狀,這些形狀是由一些直線線條組成,我們可以用moveToPoint: 和 addLineToPoint:方法去構(gòu)建
方法moveToPoint:設(shè)置我們想要?jiǎng)?chuàng)建形狀的起點(diǎn)。從這點(diǎn)開始,我們可以用方法addLineToPoint:去創(chuàng)建一個(gè)形狀的線段。
我們可以連續(xù)的創(chuàng)建line,每一個(gè)line的起點(diǎn)都是先前的終點(diǎn),終點(diǎn)就是指定的點(diǎn)。
下面的代碼描述了如何用線段去創(chuàng)建一個(gè)五邊形。第五條線通過調(diào)用closePath方法得到的,它連接了最后一個(gè)點(diǎn)(0,40)和第一個(gè)點(diǎn)(100,0)
說明:closePath方法不僅結(jié)束一個(gè)shape的subpath表述,它也在最后一個(gè)點(diǎn)和第一個(gè)點(diǎn)之間畫一條線段,如果我們畫多邊形的話,這個(gè)一個(gè)便利的方法我們不需要去畫最后一條線
//自定義view里面自定義繪制這個(gè)view
- (void)drawRect:(CGRect)rect
{
UIColor *color = [UIColor redColor];
[color set]; //設(shè)置線條顏色
UIBezierPath* aPath = [UIBezierPath bezierPath];
aPath.lineWidth = 5.0;
aPath.lineCapStyle = kCGLineCapRound; //線條拐角
aPath.lineJoinStyle = kCGLineCapRound; //終點(diǎn)處理
// Set the starting point of the shape.
[aPath moveToPoint:CGPointMake(100.0, 0.0)];
// Draw the lines
[aPath addLineToPoint:CGPointMake(200.0, 40.0)];
[aPath addLineToPoint:CGPointMake(160, 140)];
[aPath addLineToPoint:CGPointMake(40.0, 140)];
[aPath addLineToPoint:CGPointMake(0.0, 40.0)];
[aPath closePath];//第五條線通過調(diào)用closePath方法得到的
[aPath stroke];//Draws line 根據(jù)坐標(biāo)點(diǎn)連線
}
至于繪制矩形(bezierPathWithRect)圓形/橢圓形(bezierPathWithOvalInRect)之類的是系統(tǒng)對常用的一點(diǎn)封裝而已。
ps:1.繪圖呢,調(diào)用drawRect(重繪父view)和CALayer都可以,但是相比之下CALayer調(diào)用GPU來進(jìn)行繪制,性能會(huì)更好點(diǎn)。如果要組合成動(dòng)畫,還是要用CALayer,(不過很多時(shí)候用它的子類CAShapeLayer)
2.它這種直線段繪圖(addLineToPoint)跟代碼順序有關(guān),所以敲的時(shí)候要注意了
3.另外如果調(diào)起 [aPath stroke],它是會(huì)自動(dòng)連上起點(diǎn)和終點(diǎn)的,當(dāng)然也可以用填充模式[aPath fill]替代[aPath stroke]畫線模式
==
(4)改變UIBezierPath對象跟繪圖相關(guān)的屬性。
例如,我們可以設(shè)置stroked path的屬性lineWidth和lineJoinStyle。也可以設(shè)置filled path的屬性usesEvenOddFillRule。
貝塞爾曲線的修改:
1.底層修改(比較麻煩):
雖然通常我們可以用UIBezierPath類的方法去添加直線段和曲線段,UIBezierPath類還提供了一個(gè)屬性CGPath,我們可以用來直接修改底層的path data type。如果我們希望用Core Graphics 框架函數(shù)去創(chuàng)建path,則我們要用到此屬性。
>有兩種方法可以用來修改和UIBezierPath對象相關(guān)的path??梢酝耆氖褂肅ore Graphics函數(shù)去修改path,也可以使用Core Graphics函數(shù)和UIBezierPath函數(shù)混合去修改。第一種方法在某些方面相對來說比較容易。我們可以創(chuàng)建一個(gè)CGPathRef數(shù)據(jù)類型,并調(diào)用我們需要修改path信息的函數(shù)。
如果我們使用Core Graphics函數(shù)和UIBezierPath函數(shù)混合方法,我們必須小心的移動(dòng)path 信息在兩者之間。因?yàn)閁IBezierPath類擁有自己底層的CGPathRef data type,我們不能簡單的檢索該類型并直接的修改它。相反,我們應(yīng)該生成一個(gè)副本,然后修改此副本,然后賦值此副本給CGPath屬性,如下代碼:
UIBezierPath* aPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 300, 300)];
// Get the CGPathRef and create a mutable version.
CGPathRef cgPath = aPath.CGPath;
CGMutablePathRef mutablePath = CGPathCreateMutableCopy(cgPath);
// Modify the path and assign it back to the UIBezierPath object
CGPathAddEllipseInRect(mutablePath, NULL, CGRectMake(50, 50, 200, 200));
aPath.CGPath = mutablePath;
// Release both the mutable copy of the path.
CGPathRelease(mutablePath);
ps:名稱解釋之GPU
GPU相當(dāng)于專用于圖像處理的CPU,正因?yàn)樗鼘#运鼜?qiáng),在處理圖像時(shí)它的工作效率遠(yuǎn)高于CPU,但是CPU是通用的數(shù)據(jù)處理器,在處理數(shù)值計(jì)算時(shí)是它的強(qiáng)項(xiàng),它能完成的任務(wù)是GPU無法代替的,所以不能用GPU來代替CPU。
時(shí)下的GPU多數(shù)擁有2D或3D圖形加速功能。如果CPU想畫一個(gè)二維圖形,只需要發(fā)個(gè)指令給GPU,如“在坐標(biāo)位置(x, y)處畫個(gè)長和寬為a×b大小的長方形”,GPU就可以迅速計(jì)算出該圖形的所有像素,并在顯示器上指定位置畫出相應(yīng)的圖形,畫完后就通知CPU “我畫完了”,然后等待CPU發(fā)出下一條圖形指令。
有了GPU,CPU就從圖形處理的任務(wù)中解放出來,可以執(zhí)行其他更多的系統(tǒng)任務(wù),這樣可以大大提高計(jì)算機(jī)的整體性能