* 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)中進行繪制、完成操作(如平移)、修改圖形狀態參數(如線寬和填充顏色)等。