小编会开展一系列的Quartz2D专题的学习,而所记录的内容原文都是出自大师博客文顶顶感兴趣的可以直接看原文。
Quartz 2D 是一个二维绘图引擎
,同时支持iOS和Mac系统
Quartz2D 能完成的工作
- 绘制图形:线条、三角形、矩形、圆、弧等
- 绘制文字
- 绘制/生成图片
- 读取/生成PDF
- 截图/裁剪图片
-
自定义UI控件
等等
图形上下文(Graphics Context
):是一个CGContextRef
类型的数据
图形上下文的作用
:
- 保存绘图的信息、绘图状态
- 决定绘制的输出目标(绘制到什么地方去?)
(输出目标可以是PDF文件、Bitmap或者显示器的窗口上) - 相同一套绘图序列,指定不同的Graphics Context,就可将相同的图像绘制到不同的目标上
image.png
Quartz 2D 提供了一下
几种类型
的Graphics Context:
- Bitmap Graphics Context
- PDF Graphics Context
- Window Graphics Context
- Layer Graphics Context
- Printer Graphics Context
image.png
学习目标:
* 如何利用Quartz 2D自定义view?(自定义UI控件)
自定义view的步骤
(1) 新建一个类,继承自UIView
(2)实现-(void)drawRext:(CGRect)rect
方法,然后在这个方法中获取跟当前View相关联的图形上下文
(3)绘制相关的图形内容
(4)利用图形上下文将绘制的所有内容渲染显示到view上面
* 如何利用Quart 2D绘制东西到view上?
首先,得有图形上下文,因为它能保存绘图信息,并且决定着绘制到什么地方去
其次,那个图形上下文必须跟view相关联,才能将内容绘制到view上面
// 注意:drawRect如果是手动调用的话,它是不会创建跟view相关联的上下文
// 刷新调用drawRect方法,可以手动调用:[self setNeedDisplay]
/// 作用:专门用来绘图
/// 什么时候调用:当View显示的时候调用
/// @param rect 当前View的bounds
- (void)drawRect:(CGRect)rect {
}
实例(2020年4月12日更新)
推荐使用UIBezierPath描述路径,更加灵活
比如画一个矩形
- (void)drawRect:(CGRect)rect {
// 1.0 获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 2.0 描述路径
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 100, 100)];
[[UIColor redColor] set];
// 3.0 把路径添加到上下文
CGContextAddPath(ctx, path.CGPath);
// 4.0 把上下文的内容渲染到view上
CGContextFillPath(ctx);
}
/**
备注:已下的方法也能达到同样的效果
因为使用[path fill] 底层的实现原理如下
1.获取上下文-->2.描述路径-->3.把路径添加到上下文-->4.把上下文的内容渲染到layer上
*/
- (void)drawRect:(CGRect)rect {
UIBezierPath *path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 100, 100)];
[[UIColor redColor] set];
[path fill];
}
bitMap位图上下文
bitMap位图上下文
须手动去开启
,开启多大的上下文,生成的图片就是多大,并且需要手动关闭上下文
`实例`:在一张图片上添加一个文字“@Liven”的文字水印
@interface ViewController ()
@property (nonatomic, strong, readwrite) UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 加载图片
UIImage *image = [UIImage imageNamed:@"测试.png"];
// 2. 创建bitMap位图上下文
// opaque 不透明度
// scale 0表示根据屏幕的缩放比例
UIGraphicsBeginImageContextWithOptions(image.size, 0, 0);
// 3.将图片添加到位图上下文中
[image drawAtPoint:CGPointZero];
// 4.添加水印文字比如:@Liven
NSString *str = @"@@Liven";
[str drawAtPoint:CGPointZero withAttributes:nil];
// 5.把上下文当中绘制的所有内容,生成一张图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
// 6.关闭位图上下文
UIGraphicsEndImageContext();
[self.view addSubview:self.imageView];
self.imageView.image = newImage;
}
- (UIImageView *)imageView {
if (!_imageView) {
_imageView = [[UIImageView alloc]initWithFrame:self.view.bounds];
}
return _imageView;
}
@end
画图的步骤分三步
:
1、获取载体图形上下文:CGContextRef
在UIView的drawRect方法中获取的是关联Layer层的图形上下文
2、开始绘图
设置图形的形状,和图形状态(颜色、线宽等)
***3、展现图形****
即渲染图形,渲染的方式有两种:
CGContextStrokePath(ctx) ----空心
CGContextFillPath(ctx) ----实心
以下是Quartz2D的基本使用
#import "LineView.h"
@implementation LineView
- (void)drawRect:(CGRect)rect{
//1.画直线
// [self drawLine];
//2.三角形
// [self drawTriangle];
//3.四边形
// [self drawSquare];
//4.圆
// [self drawCircle];
//5.扇形
[self drawRoundCircle];
}
#pragma mark - 直线
- (void)drawLine{
//1.取得和当前视图相关联的图形上下文(因为图形上下文决定绘制的输出目标)
//如果是在drawRect方法中调用UIGraphicsGetCurrentContext方法获取出来的就是Layer的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.绘制直线,保存绘图信息
// 设置起点
CGContextMoveToPoint(ctx, 20, 100);
// 设置终点
CGContextAddLineToPoint(ctx, 300, 100);
// 设置绘图的状态
// 设置线条的颜色为蓝色
CGContextSetRGBStrokeColor(ctx, 0, 1, 0, 1);
// 设置线条宽度
CGContextSetLineWidth(ctx, 15);
// 设置线条起点和终点的样式为圆角 cap:帽
CGContextSetLineCap(ctx, kCGLineCapRound);
// 设置线条的转角的样式为圆角 join:连接点
CGContextSetLineJoin(ctx, kCGLineJoinRound);
//3、渲染 (绘制出一条空心的线)
// 注意:线条是不能渲染为实心的 CGContextFillPath(ctx)
CGContextStrokePath(ctx);
}
#pragma mark - 三角形
- (void)drawTriangle{
//1.获取图形上下文
CGContextRef ctxt = UIGraphicsGetCurrentContext();
//2.绘制三角形
CGContextMoveToPoint(ctxt, 20, 100);
CGContextAddLineToPoint(ctxt, 20, 300);
CGContextAddLineToPoint(ctxt, 200, 200);
// 关闭起点和终点
// 闭合起点和终点还有一种方式就是:在终点到起点处再画多一条线
CGContextClosePath(ctxt);
//3.渲染图形到layer上
CGContextStrokePath(ctxt);
}
#pragma mark - 画四边形
- (void)drawSquare{
//1.获取图形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.绘制图形
CGContextAddRect(ctx, CGRectMake(20, 20, 150, 100));
// 设置绘图状态 (状态的设置必须跟图形的类型一致(空心还是实心))
// 空心
// CGContextSetRGBStrokeColor(ctx, 1, 0, 0, 1);
// 实心
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1);
// 第二种设置图形状态的方法
// [[UIColor redColor]setStroke]; //空心
// [[UIColor redColor]setFill] //实心
//3.渲染
// 空心的
// CGContextStrokePath(ctx);
// 实心的
CGContextFillPath(ctx);
}
#pragma mark - 画圆
- (void)drawCircle{
//1、
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2、
// 第一个和第二个参数是设置圆心,第三个是半径,第四个是设置起始角度,第五个是设置终止角度,第六个是顺时针还是逆时针
// 0:顺时针 1:逆时针
CGContextAddArc(ctx, 100, 100, 50, 0, 2*M_PI, 0);
//用椭圆的方法画圆,矩形的内切圆
//CGContextAddEllipseInRect(ctx, CGRectMake(250, 300, 100, 100));
//3.渲染
CGContextStrokePath(ctx); //空心
CGContextFillPath(ctx);
}
#pragma mark - 扇形
- (void)drawRoundCircle{
//1.
CGContextRef ctx = UIGraphicsGetCurrentContext();
//2.
CGContextMoveToPoint(ctx, 100, 100);
CGContextAddLineToPoint(ctx, 100, 150);
CGContextAddArc(ctx, 100, 100, 50, M_PI_2, M_PI, 0);
CGContextClosePath(ctx)
//3.
CGContextStrokePath(ctx);
}
文字和图片
#import "LabelAndImageView.h"
@implementation LabelAndImageView
- (void)drawRect:(CGRect)rect{
//1.文字
// [self drawString];
//2.图片
[self drawImage];
}
#pragma mark - 绘制文字
- (void)drawString{
NSString *str = @"好像好像好像好像好像好像好像好像好像好像好像好像好像";
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddRect(ctx, CGRectMake(10, 100, 300, 200));
[[UIColor redColor]setStroke];
CGContextStrokePath(ctx);
NSMutableDictionary *md = [NSMutableDictionary dictionary];
//设置文字颜色
md[NSForegroundColorAttributeName] = [UIColor blackColor];
//设置文字背景颜色
md[NSBackgroundColorAttributeName] = [UIColor lightGrayColor];
//设置文字大小
md[NSFontAttributeName] = [UIFont systemFontOfSize:18];
//绘制文字,会自动换行,当文字超出rect的范围就不显示
[str drawInRect:CGRectMake(10, 100, 300, 200) withAttributes:md];
//在某一点插入文字,但是文字不会换行
// [str drawAtPoint:CGPointMake(10, 100) withAttributes:md];
}
- (void)drawImage{
//1.加载图片到内存
UIImage *image = [UIImage imageNamed:@"image.jpeg"];
//2.利用drawAsPatternInRect方法绘制图片到layer,是通过平铺原有照片
// [image drawAsPatternInRect:self.frame];
//drawInRect是拉伸压缩图片尺寸填充
// [image drawInRect:self.frame];
//以原图的尺寸,在某点插入图片
[image drawAtPoint:CGPointMake(20, 20)];
}