* Quartz*
1. Mac OS X的Darwin核心之上的繪圖層,有時候也認為是CoreGraphics。共有兩種部分組成Quartz:
2. Quartz Compositor,合成視窗系統,管理和合成幕後視窗影像來建立Mac OS X使用者接口。
3. Quartz 2D,是iOS和Mac OS X環境下的二維繪圖引擎。
涉及內容包括:基於路徑的繪圖,透明度繪圖,遮蓋,陰影,透明層,顏色管理,防鋸齒渲染,生成PDF,以及PDF元數據相關處理。
*一、Quartz 2D的簡單介紹**
1. Quartz 2D屬於Core Graphics(所以大多數相關方法的都是以CG開頭),是iOS/Mac OSX 提供的在內核之上的強大的2D繪圖引擎,並且這個繪圖引擎是設備無關的。也就是說,不用關心設備的大小,設備的分辨率,只要利用Quartz 2D,這些設備相關的會自動處理。
**2.**Quartz 2D能夠提供的強大功能如下:
1. 透明層(transparency layers) 2. 陰影 基於path的繪圖(path-based drawing) 3. 離屏渲染(offscreen rendering) 4. 復雜的顏色處理(advanced color management) 5. 抗鋸齒渲染(anti-aliased rendering) 6. PDF創建,展示,解析(這部分不在這個系列之中) 配合Core Animation, OpenGL ES,UIKit完成復雜的功能 畫板-The Graphics Context 7. 而Quartz 2D的容器就是CGContextRef數據模型。這種數據模型是C的結構體,存儲了渲染到屏幕上需要的一切信息。
二、Quartz 2D詳解:
Quartz 2D的基本數據類型:
Quartz 2D中的數據類型都是透明的,也就是說用戶只需要使用即可,不需要實際訪問其中的變量。具體的數據類型包括
1. CGPathRef 路徑類型,用來繪制路徑(注意帶有ref後綴的一般都是繪制的畫板) 2. CGImageRef,繪制bitmap 3. CGLayerRef,繪制layer,layer可復用,可離屏渲染 4. CGPatternRef,重復繪制 5. CGShadingRef和CGGradientRef,繪制漸變(例如顏色漸變) 6. CGFunctionRef,定義回調函數,CGShadingRef和CGGradientRef的輔助類型 7. CGColorRef and CGColorSpaceRef,定義如何處理顏色 8. CGFontRef,繪制文字
Quartz 2D的坐標
UIKit默認的坐標系統與Quartz不同。在UIKit中,原點位於左上角,y軸正方向為向下。UIView通過將修改Quartz的Graphics Context的CTM[原點平移到左下角,同時將y軸反轉(y值乘以-1)]以使其與UIView匹配。這些都是系統自動幫我們完成。
三、直線/矩形
基本圖形繪制需要的屬性
1.獲取當前上下文(context)(UIGraphicsGetCurrentContext) 2.設置顏色: CGContextSetFillColorWithColor:設置描邊顏色 CGContextSetFillColorWithColor:設置填充顏色 3. 畫的范圍 CGContextStrokeRect:描邊的范圍 CGContextFillRect:填充的范圍 4.CGContextSetLineWidth:線寬 5.CGContextSetLineCap:線頂端的樣式 6.CGContextSetLineJoin:線拐角的樣式 7. 線的起始點: CGContextMoveToPoint:起點 CGContextAddLineToPoint:終點 8.CGContextFillPath :填充的路徑 9.CGContextStrokePath:描邊的路徑
直線、矩形 demo
- (void)drawRect:(CGRect)rect { //1.獲得當前context CGContextRef context = UIGraphicsGetCurrentContext(); //設置顏色 (填充色和 描邊的顏色) CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0.8 alpha:1].CGColor); CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); //設置描邊線寬 CGContextSetLineWidth(context, 20); //對矩形進行填色 或 描邊 //(注意:如果先描邊再填充,由於矩形大小一致,那麼描邊的線就會被填充的矩形擋住) CGContextFillRect(context, rect); CGContextStrokeRect(context, rect); //----------------------------------------------------------------- //MARK: ------ 實際line和point的代碼 // 設置描邊顏色 CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor); CGContextSetLineWidth(context, 8.0);//線的寬度 CGContextSetLineCap(context, kCGLineCapRound);//線的頂端 CGContextSetLineJoin(context, kCGLineJoinRound);//線相交的模式 //----------------------------------------------------------------- //MARK:黃色的 ">" 圖形 //移動畫筆到哪個點 CGContextMoveToPoint(context,20,20); //畫筆畫到哪個點 CGContextAddLineToPoint(context, rect.size.width - 20, rect.size.height / 2 - 20); CGContextAddLineToPoint(context, 20, rect.size.height - 20); //根據上下文中的點,成線進行描邊 CGContextStrokePath(context); //------------------------------------------------------------------ //MARK: 紅色的小的三角的填充 CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor); CGContextMoveToPoint(context, 0, rect.size.height / 2 - 30); CGContextAddLineToPoint(context, 30, rect.size.height / 2); CGContextAddLineToPoint(context, 0, rect.size.height / 2 + 30); CGContextFillPath(context); //虛線效果 //CGContextSetLineDash(context, 1, lengths, 1); //------------------------------------------------------------------ //MARK: 紅色虛線效果 CGContextSetStrokeColorWithColor(context,[UIColor redColor].CGColor); CGContextSetLineWidth(context, 1); CGContextMoveToPoint(context, rect.size.width - 20, 20); CGContextAddLineToPoint(context, rect.size.height - 20, rect.size.width - 20); CGFloat lengths[] = {20}; CGContextSetLineDash(context, 1, lengths, 1); CGContextStrokePath(context); }
運行之後的效果:
虛線效果
CGContextSetLineDash參數詳解
void CGContextSetLineDash (
CGContextRef _Nullable c,
CGFloat phase,
const CGFloat * _Nullable lengths,
size_t count
);
c 繪制的context,這個不用多說
phase,第一個虛線段從哪裡開始,例如傳入3,則從第三個單位開始
lengths,一個C數組,表示繪制部分和空白部分的分配。例如傳入[2,2],則繪制2個單位,然後空白兩個單位,以此重復
count lengths的數量
四、曲線— 圓弧的繪制
Quartz提供了兩個方法來繪制圓弧
1. CGContextAddArc,普通的圓弧一部分(以某圓心,某半徑,某弧度的圓弧)
2. CGContextAddArcToPoint,用來繪制圓角
CGContextAddArc
結構:
void CGContextAddArc (
CGContextRef _Nullable c,
CGFloat x, // 圓心X坐標
CGFloat y, // 圓心Y坐標
CGFloat radius, // 弧度半徑
CGFloat startAngle, // 開始的弧度
CGFloat endAngle, // 結束的弧度
int clockwise //1表示順時針,0表示逆時針
);
- (void)drawRect:(CGRect)rect { //-------------------------------------------------------------------- //MARK: 畫弧 //1.獲取圖片上下文 CGContextRef context = UIGraphicsGetCurrentContext(); //2.設置弧度及位置 //根據中心點,半徑,起始的弧度,最後的弧度,是否順時針畫一個圓弧 CGContextAddArc(context, rect.size.width / 2, rect.size.height / 2, 20, M_PI_4, M_PI, 1); CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); //3.畫 CGContextDrawPath(context, kCGPathStroke); // ----------------------------------------------------- //MARK:畫有線圈的圓餅 CGContextSetRGBStrokeColor(context, 1, 0, 0, 1);//設置線的顏色 CGContextSetRGBFillColor(context, 0, 0, 1, 1);//設置填充顏色 CGContextSetLineWidth(context, 2); //設置線的寬度 CGContextAddEllipseInRect(context, CGRectMake(10, 30, 60, 60)); //畫一個橢圓或者圓 CGContextDrawPath(context, kCGPathFillStroke); }
2.CGContextAddArcToPoint
void CGContextAddArcToPoint (
CGContextRef _Nullable c,
CGFloat x1,
CGFloat y1,
CGFloat x2,
CGFloat y2,
CGFloat radius
);
c context x1,y1和當前點(x0,y0)決定了第一條切線(x0,y0)->(x1,y1) x2,y2和(x1,y1)決定了第二條切線 radius,想切的半徑。
也就是說,
繪制一個半徑為radius的圓弧,和上述 兩條直線都相切。
- (void)drawRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);//設置線的顏色 CGContextSetRGBFillColor(ctx, 0, 0, 1, 1);//設置填充顏色 CGContextSetLineWidth(ctx, 2); //設置線的寬度 //CGContextAddArcToPoint 先要確定三個點, //1.從哪裡開始劃線 CGContextMoveToPoint (也就是兩條線的交點) //2.第二個點與起始點 確定一條直線 //3.第三個點與第二個點 確定另外一條直線 //畫一個圓角矩形 //確定矩形的位置和大小 CGRect rrect = CGRectMake(rect.size.width / 2 - 30, rect.size.height / 2 - 30, 60.0, 60.0); CGFloat radius = 15.0;//半徑,半徑為正方形一半時,那就可以切成圓形 CGFloat minx = CGRectGetMinX(rrect),//矩形中最小的x midx = CGRectGetMidX(rrect),//矩形中最大x值的一半 maxx = CGRectGetMaxX(rrect);//矩形中最大的x值 CGFloat miny = CGRectGetMinY(rrect),//矩形中最小的Y值 midy = CGRectGetMidY(rrect),//矩形中最大Y值的一半 maxy = CGRectGetMaxY(rrect);//矩形中最大的Y值 CGContextMoveToPoint(ctx, minx, midy);//從點A 開始 //從點A到點B再從點B到點C形成夾角進行切圓 CGContextAddArcToPoint(ctx, minx, miny, midx, miny, radius); CGContextAddArcToPoint(ctx, maxx, miny, maxx, midy, radius); CGContextAddArcToPoint(ctx, maxx, maxy, midx, maxy, radius); CGContextAddArcToPoint(ctx, minx, maxy, minx, midy, radius); CGContextClosePath(ctx); CGContextDrawPath(ctx, kCGPathFillStroke); }
運行效果:
貝塞爾曲線
- (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); CGContextSetLineWidth(context, 4); CGFloat minx = CGRectGetMinX(rect),//矩形中最小的x midx = CGRectGetMidX(rect),//矩形中最大x值的一半 maxx = CGRectGetMaxX(rect);//矩形中最大的x值 CGFloat miny = CGRectGetMinY(rect),//矩形中最小的Y值 midy = CGRectGetMidY(rect),//矩形中最大Y值的一半 maxy = CGRectGetMaxY(rect);//矩形中最大的Y值 //貝塞爾曲線一,兩個控制點 紅色 CGPoint s = CGPointMake(minx + 10, miny + 10); //起始點 CGPoint e = CGPointMake(maxx - 10, maxy - 10);//終點 CGPoint cp1 = CGPointMake(miny, midy);//控制點1 CGPoint cp2 = CGPointMake(midy, minx);//控制點2 CGContextMoveToPoint(context, s.x, s.y); CGContextAddCurveToPoint(context, cp1.x, cp1.y, cp2.x, cp2.y, e.x, e.y); CGContextStrokePath(context); //貝塞爾曲線二,一個控制點 藍色 CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor); s = CGPointMake(minx, maxy); e = CGPointMake(maxx, maxy); cp1 = CGPointMake(midx, midy); CGContextMoveToPoint(context, s.x, s.y); CGContextAddQuadCurveToPoint(context, cp1.x, cp1.y, e.x, e.y); CGContextStrokePath(context); }
運行效果
五、顏色漸變
demo
- (void)drawRect:(CGRect)rect { // Drawing code // 創建Quartz上下文 CGContextRef context = UIGraphicsGetCurrentContext(); // 創建色彩空間對象 CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); // 創建起點顏色 CGColorRef beginColor = CGColorCreate(colorSpaceRef, (CGFloat[]){0.01f, 0.5f, 0.01f, 1.0f}); // 創建終點顏色 CGColorRef endColor = CGColorCreate(colorSpaceRef, (CGFloat[]){0.99f, 0.99f, 0.01f, 1.0f}); // 創建顏色數組 const void **values = (const void*[]){beginColor, endColor};//顏色數組 CFArrayRef colorArray = CFArrayCreate( kCFAllocatorDefault, values,//顏色數組 2,//數組的個數 nil// CGGradientCreateWithColors的最後一個locations參數可以傳空,這樣默認為從0.0到1.0。 ); // 創建漸變對象 CGGradientRef gradientRef = CGGradientCreateWithColors(colorSpaceRef, colorArray, (CGFloat[]){ 0.0f, // 對應起點顏色位置 1.0f // 對應終點顏色位置 }); // 釋放顏色數組 CFRelease(colorArray); // 釋放起點和終點顏色 CGColorRelease(beginColor); CGColorRelease(endColor); // 釋放色彩空間 CGColorSpaceRelease(colorSpaceRef); /* 1.context 上線文 2.gradientRef 顏色數組 3.startPoint 開始位置 4.endPoint 結束位置 5.CGGradientDrawingOptions 當你的起點或者終點不在圖形上下文的邊緣內時,指定該如何處理。你可以使用你的開始或結束顏色來填充漸變以外的空間。此參數為以下值之一: KCGGradientDrawsAfterEndLocation擴展整個漸變到漸變的終點之後的所有點 KCGGradientDrawsBeforeStartLocation擴展整個漸變到漸變的起點之前的所有點。 0不擴展該漸變。 */ CGPoint startPoint = CGPointMake(0.0f, 0.0f); CGPoint endPoint = CGPointMake(rect.size.width, rect.size.height); CGGradientDrawingOptions options = kCGGradientDrawsAfterEndLocation; CGContextDrawLinearGradient( context, gradientRef, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation // kCGGradientDrawsAfterEndLocation ); // 釋放漸變對象 CGGradientRelease(gradientRef); }
效果圖
六、多中顏色的渲染
demo
- (void)drawRect:(CGRect)rect { // 創建Quartz上下文 CGContextRef context = UIGraphicsGetCurrentContext(); // 創建色彩空間對象 CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); // 創建漸變對象 CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorSpaceRef, (CGFloat[]){ 1.0f,0.8f,0.5f,1.0f,//第一個顏色RGB 和透明度 0.6f,0.5f,0.6f,1.0f,//第二個顏色RGB 和透明度 0.3f,0.2f,0.f,1.0f,//第三個顏色RGB 和透明度 .0f,0.0f,0.3f,1.0f }, (CGFloat[]){ 0.0f,0.3f,.6f,1},//顏色漸變的位置 4);//顏色的個數 // 釋放色彩空間 CGColorSpaceRelease(colorSpaceRef); // 填充漸變色 CGContextDrawLinearGradient(context, gradientRef, CGPointMake(0.0f, 0.0f), CGPointMake(320.0f, 460.0f), 0); // 釋放漸變對象 CGGradientRelease(gradientRef); }
效果
幾何圖形繪制屬性—詳解
1.Graphics Context(圖層上下文)
Graphics Context
其實就是表示了一個繪制目標,也就是你打算繪制的地方,它包含繪制系統用於完成繪制指令的繪制參數和設備相關信息。Graphics Context定義了基本的繪制屬性,如顏色、裁減區域、線條寬度和樣式信息、字體信息、混合模式等。 *獲取Graphics Context:
1. Quartz提供的創建函數、Mac OS X框架或IOS的UIKit框架提供的函數。Quartz提供了多種Graphics Context的創建函數,包括bitmap和PDF,我們可以使用這些Graphics Context創建自定義的內容。
2. 在代碼中,我們用CGContextRef來表示一個Graphics Context。當獲得一個Graphics Context後,可以使用Quartz 2D函數在上下文(context)中進行繪制、完成操作(如平移)、修改圖形狀態參數(如線寬和填充顏色)等。