iOS Core Graphics基本使用

簡介:

Core Graphics 和Quartz 2D的區(qū)別

quartz是一個通用的術(shù)語,用于描述在iOS和MAC OS X ZHONG 整個媒體層用到的多種技術(shù) 包括圖形、動畫、音頻、適配。

Quart 2D 是一組二位繪圖和渲染API,Core Graphic會使用到這組API

Quartz Core 專指Core Animation用到的動畫相關(guān)的庫、API和類

點和像素的對比

系統(tǒng)擁有坐標(biāo)系,如320*480 硬件有retain屏幕和非retain屏:如320*480、640*960

Core Graphics 使用的是系統(tǒng)的坐標(biāo)系來繪制圖片。在分辨率為640*960手機(jī)上繪制圖片時,實際上Core Graphics 的坐標(biāo)是320*480。這個時候每個坐標(biāo)系上的點,實際上擁有兩個像素。

圖形上下文

Core Graphics 使用圖形上下文進(jìn)行工作,這個上下文的作用像畫家的畫布一樣。

在圖形上下文之外是無法繪圖的,我們可以自己創(chuàng)建一個上下文,但是性能和內(nèi)存的使用上,效率是非常低得。

我們可以通過派生一個UIView的子類,獲得它的上下文。在UIView中調(diào)用drawRect:方法時,會自動準(zhǔn)備好一個圖形上下文,可以通過調(diào)用

UIGraphicsGetCurrentContext()來獲取。 因為它是運行期間繪制圖片,我們可以動態(tài)的做一些額外的操作

Core Graphics的優(yōu)點

快速、高效,減小應(yīng)用的文件大小。同時可以自由地使用動態(tài)的、高質(zhì)量的圖形圖像。 使用Core Graphics,可以創(chuàng)建直線、路徑、漸變、文字與圖像等內(nèi)容,并可以做變形處理。

繪制自定義視圖

drawRect:是系統(tǒng)的方法,不要從代碼里面直接調(diào)用 drawRect:,而應(yīng)該使用setNeedsDisplay重繪.

//points:

//指定一個點成為current point,Quartz會跟蹤current point一般執(zhí)行完一個相關(guān)函數(shù)后,current point都會相應(yīng)的改變

CGContextMoveToPoint(CGContextRef??_Nullable c, <#CGFloat x#>, <#CGFloat y#>)

//Lines:

//創(chuàng)建一條直線,從current point到(x,y),然后current point會變成(x,y)

CGContextAddLineToPoint(CGContextRef??_Nullable c, <#CGFloat x#>, <#CGFloat y#>)

//創(chuàng)建多條直線,比如points有兩個點,那么會畫兩條直線,從current point到(x1,y1),

//然后是(x1,y1)到(x2,y2),然后current point會變成points中的最后一個點

//Arcs:

//(x,y)為圓的中心,radius為半徑,startAngle為開始角度,endAngle為結(jié)束角度,clockwise表示,0為順時針,1為逆時針

//假如想創(chuàng)建一個完整的圓圈,那么開始弧度是0,結(jié)束弧度為2PI,因為周長是2PI*r,最后執(zhí)行

//current point就被重置為(x,y),假如當(dāng)前path已經(jīng)存在一個subpath,那么這個函數(shù)執(zhí)行

//的另一個效果是,會有一點直線從current point到弧的起點

CGContextAddArc(<#CGContextRef??_Nullable c#>, <#CGFloat x#>, <#CGFloat y#>, <#CGFloat radius#>, <#CGFloat startAngle#>, <#CGFloat endAngle#>, <#int clockwise#>)

//(x1,y1)(x2,y2),r為半徑,首先畫兩條線分別是current point to(x1,y1)和

//(x1,y1)to (x2,y2)這樣就是出現(xiàn)一個以(x1,y1)為頂點的兩條射線

//然后定義半徑長度,這個半徑是垂直于兩條射線的,這樣就能決定一個圓了,更好的理解下圖,不過

//個人下圖所標(biāo)的tangent point1 的位置是錯誤的。

//最后,函數(shù)執(zhí)行完后,current point就被重置為(x2,y2)

//還有一點要注意的是,假如當(dāng)前path已經(jīng)存在一個subpath,那么這個函數(shù)執(zhí)行的另一種效果是

//會有一條直線,從current point到(x1,y1)

CGContextAddArcToPoint(<#CGContextRef??_Nullable c#>, <#CGFloat x1#>, <#CGFloat y1#>, <#CGFloat x2#>, <#CGFloat y2#>, <#CGFloat radius#>)

/Curves

//畫曲線,一般是一條直線,然后定義幾個控制點,使直線變彎曲

//控制點(x1,y1)(x2,y2)直線的終點(x,y)

//假如第二個控制點(cp2x,cp2y)比(cp1x,cp1y) 更接近current point,那么會形成一個封閉的曲線

CGContextAddCurveToPoint(<#CGContextRef??_Nullable c#>, <#CGFloat cp1x#>, <#CGFloat cp1y#>, <#CGFloat cp2x#>, <#CGFloat cp2y#>, <#CGFloat x#>, <#CGFloat y#>)

//二次曲線函數(shù)

//控制點(px,py) 直線的終點(x,y),執(zhí)行完函數(shù)貌似current point不會變化,沒有具體測試過

CGContextAddQuadCurveToPoint(<#CGContextRef??_Nullable c#>, <#CGFloat cpx#>, <#CGFloat cpy#>, <#CGFloat x#>, <#CGFloat y#>)

//Rectangles

CGContextAddRect(<#CGContextRef??_Nullable c#>, <#CGRect rect#>)

//一次性畫多個矩形,畫矩形有一些特別,current point沒有發(fā)生變化

CGContextAddRects(<#CGContextRef??_Nullable c#>, <#const CGRect * _Nullable rects#>, <#size_t count#>)

//Creat a Path

//調(diào)用函數(shù)CGCcontextBeginPath開始創(chuàng)建路徑,先調(diào)用函數(shù)CGContextMoveToPoint設(shè)置起點

//然后開始畫自己想畫的路徑,注意:

1.Liners,arcs,and curves,是從current point開始的

2.假如想封閉一條路徑,那么調(diào)用函數(shù)CGContextClosePath把當(dāng)前點和起點連接起來

3.當(dāng)畫arcs的時候,Quartz會畫一條線從current point到start point

4.畫矩形的時候不會有從current point到start point的線

5.創(chuàng)建完畢后,必須調(diào)用painting函數(shù),fill or stroke the path,不然不顯示

6.開始創(chuàng)建一個新路徑的時候,使用函數(shù)CGContextBeginPath

//將一個路徑添加到graphics context中

CGContextAddPath(<#CGContextRef??_Nullable c#>, <#CGPathRef??_Nullable path#>)

//stroking:畫出路徑

//Filling:填充路徑的封閉區(qū)域

//影響Stroking的參數(shù),

//線寬

CGContextSetLineWidth(<#CGContextRef??_Nullable c#>, <#CGFloat width#>)

//線轉(zhuǎn)彎樣式,比如圓滑方式

CGContextSetLineJoin(<#CGContextRef??_Nullable c#>, <#CGLineJoin join#>)

//線兩端的樣式,比如兩端變的圓滑

CGContextSetLineCap(<#CGContextRef??_Nullable c#>, <#CGLineCap cap#>)

//虛線相關(guān)

CGContextSetLineDash(<#CGContextRef??_Nullable c#>, <#CGFloat phase#>, <#const CGFloat * _Nullable lengths#>, <#size_t count#>)

//透明度相關(guān)

CGContextSetStrokePattern(<#CGContextRef??_Nullable c#>, <#CGPatternRef??_Nullable pattern#>, <#const CGFloat * _Nullable components#>)

//Stroking的相關(guān)函數(shù)

//Strokes當(dāng)前path.

void CGContextStrokePath (CGContextRef c);

//Strokes 指定的 矩形.

void CGContextStrokeRect (CGContextRef c,CGRect rect);

//Strokes 指定的 矩形, 使用指定的寬度.

void CGContextStrokeRectWithWidth (CGContextRef c,CGRect rect,CGFloat width);

//Strokes 指定的橢圓.

void CGContextStrokeEllipseInRect (CGContextRef context,CGRect rect);

//Strokes 一些直線.

void CGContextStrokeLineSegments (CGContextRef c,const CGPoint points[],size_t count);

//決定是Stroking 還是Filling

void CGContextDrawPath (CGContextRef c,CGPathDrawingMode mode);

//1.創(chuàng)建畫布 獲取上下文 2.添加控件 3.添加方法

CGContextRef context = UIGraphicsGetCurrentContext();//創(chuàng)建畫布 獲取上下文

//設(shè)置圖形上下文狀態(tài)屬性

CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);//設(shè)置筆觸顏色

CGContextSetRGBFillColor(context, 0, 1.0, 0, 1);//設(shè)置填充色

CGContextSetLineWidth(context, 2.0);//設(shè)置線條寬度

CGPoint lines [] = {

CGPointMake(100, 100),

CGPointMake(150, 150)

};

CGContextAddLines(context, lines, 2);

CGContextDrawPath(context, kCGPathStroke);

#define DEGREES_TO_RADIANS(degrees) ((degrees)*M_PI)/180

//1.創(chuàng)建畫布 獲取上下文 2.添加控件 3.添加方法

CGContextRef context = UIGraphicsGetCurrentContext();//創(chuàng)建畫布 獲取上下文

//設(shè)置圖形上下文狀態(tài)屬性

CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);//設(shè)置筆觸顏色

CGContextSetRGBFillColor(context, 0, 1.0, 0, 1);//設(shè)置填充色

CGContextSetLineWidth(context, 2.0);//設(shè)置線條寬度

//2.畫圓弧

CGContextAddArc(context, 100, 100, 50, DEGREES_TO_RADIANS(20), DEGREES_TO_RADIANS(160), 1);

CGContextDrawPath(context, kCGPathStroke);//最后一個參數(shù)是填充類型

圓角矩形

CGContextRef context = UIGraphicsGetCurrentContext();//創(chuàng)建畫布 獲取上下文

//設(shè)置圖形上下文狀態(tài)屬性

CGContextSetRGBStrokeColor(context, 1.0, 0, 0, 1);//設(shè)置筆觸顏色

CGContextSetRGBFillColor(context, 0, 1.0, 0, 1);//設(shè)置填充色

CGContextSetLineWidth(context, 2.0);//設(shè)置線條寬度

float fw = 180;

float fh = 280;

CGContextMoveToPoint(context, fw, fh-20);??// 開始坐標(biāo)右邊開始

CGContextAddArcToPoint(context, fw, fh, fw-20, fh, 10);??// 右下角角度

CGContextAddArcToPoint(context, 120, fh, 120, fh-20, 10); // 左下角角度

CGContextAddArcToPoint(context, 120, 250, fw-20, 250, 10); // 左上角

CGContextAddArcToPoint(context, fw, 250, fw, fh-20, 10); // 右上角

CGContextClosePath(context);

CGContextDrawPath(context, kCGPathFillStroke); //根據(jù)坐標(biāo)繪制路徑

/*畫矩形*/

CGContextStrokeRect(context,CGRectMake(100, 120, 10, 10));//畫方框

CGContextFillRect(context,CGRectMake(120, 120, 10, 10));//填充框

//矩形,并填棄顏色

CGContextSetLineWidth(context, 2.0);//線的寬度

aColor = [UIColor blueColor];//blue藍(lán)色

CGContextSetFillColorWithColor(context, aColor.CGColor);//填充顏色

aColor = [UIColor yellowColor];

CGContextSetStrokeColorWithColor(context, aColor.CGColor);//線框顏色

CGContextAddRect(context,CGRectMake(140, 120, 60, 30));//畫方框

CGContextDrawPath(context, kCGPathFillStroke);//繪畫路徑

//矩形,并填棄漸變顏色

//第一種填充方式,第一種方式必須導(dǎo)入類庫quartcore并#import ,這個就不屬于在context上畫,而是將層插入到view層上面。那么這里就設(shè)計到Quartz Core 圖層編程了。

CAGradientLayer *gradient1 = [CAGradientLayer layer];

gradient1.frame = CGRectMake(240, 120, 60, 30);

gradient1.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor,

(id)[UIColor grayColor].CGColor,

(id)[UIColor blackColor].CGColor,

(id)[UIColor yellowColor].CGColor,

(id)[UIColor blueColor].CGColor,

(id)[UIColor redColor].CGColor,

(id)[UIColor greenColor].CGColor,

(id)[UIColor orangeColor].CGColor,

(id)[UIColor brownColor].CGColor,nil];

[self.layer insertSublayer:gradient1 atIndex:0];

//第二種填充方式

CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();

CGFloat colors[] =

{

1,1,1, 1.00,

1,1,0, 1.00,

1,0,0, 1.00,

1,0,1, 1.00,

0,1,1, 1.00,

0,1,0, 1.00,

0,0,1, 1.00,

0,0,0, 1.00,

};

CGGradientRef gradient = CGGradientCreateWithColorComponents

(rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));//形成梯形,漸變的效果

CGColorSpaceRelease(rgb);

//畫線形成一個矩形

//CGContextSaveGState與CGContextRestoreGState的作用

/*

CGContextSaveGState函數(shù)的作用是將當(dāng)前圖形狀態(tài)推入堆棧。之后,您對圖形狀態(tài)所做的修改會影響隨后的描畫操作,但不影響存儲在堆棧中的拷貝。在修改完成后,您可以通過CGContextRestoreGState函數(shù)把堆棧頂部的狀態(tài)彈出,返回到之前的圖形狀態(tài)。這種推入和彈出的方式是回到之前圖形狀態(tài)的快速方法,避免逐個撤消所有的狀態(tài)修改;這也是將某些狀態(tài)(比如裁剪路徑)恢復(fù)到原有設(shè)置的唯一方式。

*/

CGContextSaveGState(context);

CGContextMoveToPoint(context, 220, 90);

CGContextAddLineToPoint(context, 240, 90);

CGContextAddLineToPoint(context, 240, 110);

CGContextAddLineToPoint(context, 220, 110);

CGContextClip(context);//context裁剪路徑,后續(xù)操作的路徑

//CGContextDrawLinearGradient(CGContextRef context,CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint,CGGradientDrawingOptions options)

//gradient漸變顏色,startPoint開始漸變的起始位置,endPoint結(jié)束坐標(biāo),options開始坐標(biāo)之前or開始之后開始漸變

CGContextDrawLinearGradient(context, gradient,CGPointMake

(220,90) ,CGPointMake(240,110),

kCGGradientDrawsAfterEndLocation);

CGContextRestoreGState(context);// 恢復(fù)到之前的context

CGContextSaveGState(context);

CGContextMoveToPoint(context, 260, 90);

CGContextAddLineToPoint(context, 280, 90);

CGContextAddLineToPoint(context, 280, 100);

CGContextAddLineToPoint(context, 260, 100);

CGContextClip(context);//裁剪路徑

//說白了,開始坐標(biāo)和結(jié)束坐標(biāo)是控制漸變的方向和形狀

CGContextDrawLinearGradient(context, gradient,CGPointMake

(260, 90) ,CGPointMake(260, 100),

kCGGradientDrawsAfterEndLocation);

CGContextRestoreGState(context);// 恢復(fù)到之前的context

//下面再看一個顏色漸變的圓

CGContextDrawRadialGradient(context, gradient, CGPointMake(300, 100), 0.0, CGPointMake(300, 100), 10, kCGGradientDrawsBeforeStartLocation);

/*畫扇形和橢圓*/

//畫扇形,也就畫圓,只不過是設(shè)置角度的大小,形成一個扇形

aColor = [UIColor colorWithRed:0 green:1 blue:1 alpha:1];

CGContextSetFillColorWithColor(context, aColor.CGColor);//填充顏色

//以10為半徑圍繞圓心畫指定角度扇形

CGContextMoveToPoint(context, 160, 180);

CGContextAddArc(context, 160, 180, 30,??-60 * PI / 180, -120 * PI / 180, 1);

CGContextClosePath(context);

CGContextDrawPath(context, kCGPathFillStroke); //繪制路徑

//畫橢圓

CGContextAddEllipseInRect(context, CGRectMake(160, 180, 20, 8)); //橢圓

CGContextDrawPath(context, kCGPathFillStroke);

/*畫三角形*/

//只要三個點就行跟畫一條線方式一樣,把三點連接起來

CGPoint sPoints[3];//坐標(biāo)點

sPoints[0] =CGPointMake(100, 220);//坐標(biāo)1

sPoints[1] =CGPointMake(130, 220);//坐標(biāo)2

sPoints[2] =CGPointMake(130, 160);//坐標(biāo)3

CGContextAddLines(context, sPoints, 3);//添加線

CGContextClosePath(context);//封起來

CGContextDrawPath(context, kCGPathFillStroke); //根據(jù)坐標(biāo)繪制路徑

/*畫貝塞爾曲線*/

//二次曲線

CGContextMoveToPoint(context, 120, 300);//設(shè)置Path的起點

CGContextAddQuadCurveToPoint(context,190, 310, 120, 390);//設(shè)置貝塞爾曲線的控制點坐標(biāo)和終點坐標(biāo)

CGContextStrokePath(context);

//三次曲線函數(shù)

CGContextMoveToPoint(context, 200, 300);//設(shè)置Path的起點

CGContextAddCurveToPoint(context,250, 280, 250, 400, 280, 300);//設(shè)置貝塞爾曲線的控制點坐標(biāo)和控制點坐標(biāo)終點坐標(biāo)

CGContextStrokePath(context);

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容