* 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 {
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);
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor); CGContextSetLineWidth(context, 8.0);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextMoveToPoint(context,20,20);
CGContextAddLineToPoint(context, rect.size.width - 20, rect.size.height / 2 - 20);
CGContextAddLineToPoint(context, 20, rect.size.height - 20);
CGContextStrokePath(context);
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);
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
运行之后的效果:
虚线效果
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();
CGContextAddArc(context, rect.size.width / 2, rect.size.height / 2, 20, M_PI_4, M_PI, 1);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextDrawPath(context, kCGPathStroke);
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
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);
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),
midx = CGRectGetMidX(rrect),
maxx = CGRectGetMaxX(rrect);
CGFloat
miny = CGRectGetMinY(rrect),
midy = CGRectGetMidY(rrect),
maxy = CGRectGetMaxY(rrect);
CGContextMoveToPoint(ctx, minx, midy);
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
运行效果:
贝塞尔曲线
- (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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
运行效果
五、颜色渐变
demo
- (void)drawRect:(CGRect)rect {
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
);
CGGradientRef gradientRef = CGGradientCreateWithColors(colorSpaceRef, colorArray, (CGFloat[]){
0.0f,
1.0f
});
CFRelease(colorArray);
CGColorRelease(beginColor);
CGColorRelease(endColor);
CGColorSpaceRelease(colorSpaceRef);
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
);
CGGradientRelease(gradientRef);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
效果图
六、多中颜色的渲染
demo
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradientRef =
CGGradientCreateWithColorComponents(colorSpaceRef,
(CGFloat[]){
1.0f,0.8f,0.5f,1.0f,
0.6f,0.5f,0.6f,1.0f,
0.3f,0.2f,0.f,1.0f,
.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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
效果
几何图形绘制属性—详解
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)中进行绘制、完成操作(如平移)、修改图形状态参数(如线宽和填充颜色)等。
查阅的资料
感谢大家在博客或者简书的分享,我在这里做了总结和扩展,仅供大家学习和讨论,如果有什么不对的请大家及时留言评论,谢谢~
本人github账号: 702029772@qq.com
- 博主:zenny_chen http://www.cnblogs.com/zenny-chen/archive/2012/02/23/2364152.html
- 博主:贱见 https://account.aliyun.com/login/login.htm?from_type=yqclub&oauth_callback=https%3A%2F%2Fyq.aliyun.com%2Fusers%2F1482959332945947%3Fspm%3D5176.100239.blogrightarea35932.3.0TK01t%26do%3Dlogin