Quartz2D

Quartz2D

Quartz2D概述

  • Quartz2D可以完成什么:
    • 绘制图形:线,三角形,圆,椭圆等等
    • 绘制文字(在image上)
    • 绘制\生成图片
    • 绘制\生成PDF
    • 剪裁\切割图片
    • 自定义UI控件
    • 手势解锁
  • 什么是图形上下文(Graphics Context):
    • 是一个CGContextRef类型的数据
    • 保存绘制的信息和状态(我们也可以理解成是一个画布,在这个画布上绘制)
    • 决定绘制的输出目标(绘制到什么地方去?)(输出目标可以是PDF文件、Bitmap或者显示器的窗口上)
  • Quartz2D可以获取到的图形上下文
    • Bitmap Graphics Context
    • PDF Graphics Context
    • Window Graphics Context
    • Layer Graphics Context
    • Printer Graphics Context
1.png

Quartz2D对于图形的应用

Quartz2D的基本用法

  • 在Quartz2D中苹果为我们提供了一套CoreGraphics框架,这是一套c语言的框架,下面的前两种方式就是采用这套,最后一种方式是在前面方式的基础上在OC中封装的一个类
  • 无论是哪个方法,都必须在drawRect方法中执行,因为在drawRect方法中才能获取上下文

CGPath绘制

//CGPath绘制
- (void)CGPath
{
    //获取图形上下文
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //初始化一条线路
    CGMutablePathRef pathref = CGPathCreateMutable();
    //设置起点
    //1.路径 2.旋转,缩放,平移等 3.起点的x轴坐标 4.起点的y轴坐标
    CGPathMoveToPoint(pathref, nil, 10, 10);
    //设置终点
    CGPathAddLineToPoint(pathref, nil, 100, 100);
    //把这个路线放到上下文上
    //1.上下文 2.路径
    CGContextAddPath(ref, pathref);
    //释放路径(凡是c语言函数中带create,copy,一样要释放)
    CGPathRelease(pathref);
    //绘制
    CGContextStrokePath(ref);
    //填充
    //    CGContextFillPath(ref);

}

CGContexRef绘制

//CGContexRef绘制
- (void)CGContext
{

    //获取图形上下文
    CGContextRef ref  = UIGraphicsGetCurrentContext();
    // 设置起点
    CGContextMoveToPoint(ref, 10, 10);
    //设置终点(第一条线)
    CGContextAddLineToPoint(ref, 100, 100);
    //设置终点(第二条线)
    CGContextAddLineToPoint(ref, 10, 100);
    //设置线冒
    CGContextSetLineCap(ref, kCGLineCapRound);
    //设置拐角
    CGContextSetLineJoin(ref, kCGLineJoinRound);
    //设置线宽
    CGContextSetLineWidth(ref, 10.0f);
    //闭合
    CGContextClosePath(ref);
    //设置线的颜色
    CGContextSetStrokeColorWithColor(ref, [UIColor redColor].CGColor);
    //设置填充颜色
    CGContextSetFillColorWithColor(ref, [UIColor yellowColor].CGColor);
    //下面两个谁在前面执行那个
    //    //填充
    //    CGContextFillPath(ref);
    //    //绘制
    //    CGContextStrokePath(ref);
    //由于上面两个方法只有一个能执行,所以为了两个都有效果,采用下面的方法,两个都设置(枚举)
    CGContextDrawPath(ref, kCGPathFillStroke);
}

UIBezierPath的基本用法

//贝瑟尔基本用法
- (void)bezier
{
    //初始化
    UIBezierPath *path = [[UIBezierPath alloc] init];
    //设置起点
    [path moveToPoint:CGPointMake(10, 10)];
    //设置终点(一条线)
    [path addLineToPoint:CGPointMake(100, 100)];
    //设置终点(第二条线)
    [path addLineToPoint:CGPointMake(10, 100)];
    //设置线宽
    [path setLineWidth:10.0f];
    //设直线冒
    [path setLineCapStyle:kCGLineCapRound];
    //设置拐角(两条线才能有拐角)
    [path setLineJoinStyle:kCGLineJoinRound];
    //设直线的颜色
    [[UIColor redColor] setStroke];
    //设置填充颜色
    [[UIColor yellowColor] setFill];
    //闭合路径
    [path closePath];
    //填充
    [path fill];
    //绘制
    [path stroke];
}
//利用贝瑟尔绘制圆,椭圆和扇形
- (void)drawRound
{
    //绘制圆
    UIBezierPath *path = [UIBezierPath bezierPath];
    //    1.圆心 2.半径 3. 开始的值(PI/ 2) 4. 结束的值 5. yes: 逆时针绘制 no:顺时针
    [path addArcWithCenter:CGPointMake(self.bounds.size.width / 2, self.bounds.size.height / 2) radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    //绘制
    [path stroke];
    //绘制椭圆
    UIBezierPath *path1 = [UIBezierPath  bezierPathWithOvalInRect:CGRectMake(10, 10, 100, 50)];
    //绘制
    [path1 stroke];
    //扇形
    UIBezierPath *path2  =[[UIBezierPath alloc] init];
    //设置起点
    [path2 moveToPoint:CGPointMake(100, 100)];
    [path2 addArcWithCenter:CGPointMake(100, 100) radius:100 startAngle:0 endAngle:M_PI / 2 clockwise:YES];
    //闭合
    [path2 closePath];
    //绘制
    [path2 stroke];
}

自定义View

  • 如何利用Quartz2D绘制东西到view上?
    • 首先,得有图形上下文,因为它能保存绘图信息,并且决定着绘制到什么地方去
    • 其次,那个图形上下文必须跟view相关联,才能将内容绘制到view上面
  • 自定义view的步骤
    • 新建一个类,继承自UIView
    • 实现- (void)drawRect:(CGRect)rect方法,然后在这个方法中
    • 取得跟当前view相关联的图形上下文
    • 绘制相应的图形内容
    • 利用图形上下文将绘制的所有内容渲染显示到view上面
  • 注意:drawRect方法在view第一次显示到屏幕上会调用,在ViewDidLoad之后,viewWillAppear之前,如果想要在改变图形上下文之后调用drawRect方法显示改变后的效果,用setNeedsDisplay方法,调用完setNeedsDisplay方法之后,drawRect会被调用一次

绘制饼状图

  • 基本思路:可以封装一个类继承与UIView,也可以给UIView写一个分类,这里采用继承
//在外部留好接口:传入数据和饼状图划分的颜色,以数组形式传入
@interface NewView : UIView
/**  数字数组 */
@property (nonatomic,strong) NSMutableArray *numberArray;
/**  颜色数组 */
@property (nonatomic,strong) NSMutableArray *colorArray;
/**  圆心 */
@property (nonatomic,assign) CGPoint centerPoint;
@end
//在.m中的drawRect方法中绘制
- (void)drawRect:(CGRect)rect {
   //绘制圆
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //设置圆心
   CGPoint centerPoint = self.centerPoint;
    //设置一个半径
    CGFloat radius = 100;
    //设置起始点
    CGFloat starAngle = - M_PI_2;
    //计算总和
    CGFloat total = 0;
    for (NSNumber *num in self.numberArray) {
        total = total + [num floatValue];
    }
    //从头开始一个一个绘制,利用for循环
    for (int i = 0; i < self.numberArray.count; i++) {
        //计算百分比
        CGFloat per =  [self.numberArray[i] floatValue] / total ;
        //设置终点
        CGFloat endAngle = starAngle + 2 * M_PI * per;
        //设置圆心为起点
        CGContextMoveToPoint(ref,centerPoint.x , centerPoint.y);
        //添加一条圆弧
        CGContextAddArc(ref, centerPoint.x, centerPoint.y, radius, starAngle, endAngle, NO);
        //闭合
        CGContextClosePath(ref);
        //设置填充颜色
        CGContextSetFillColorWithColor(ref, [(UIColor *)self.colorArray[i] CGColor]);
        //绘制
        CGContextDrawPath(ref, kCGPathFillStroke);
        //重置起点
        starAngle = endAngle;
    }
}

利用贝瑟尔曲线绘制曲线

- (void)drawRect:(CGRect)rect {
    // Drawing code
//二元
    UIBezierPath *path  =[[UIBezierPath alloc] init];
    //设置起点
    [path moveToPoint:CGPointMake(10, 10)];
    //设置曲线的属性
    //参数1.曲线的终点,2.曲线的基准点
    [path addQuadCurveToPoint:CGPointMake(100,100) controlPoint:CGPointMake(50, 100)];
    //绘制
    [path stroke];
//    三元
    UIBezierPath *path  = [[UIBezierPath alloc] init];
    //设置起点
    [path moveToPoint:CGPointMake(10, 100)];
    //参数1.曲线的终点 2.曲线的第一个基准点 3.曲线的第二个基准点
    [path addCurveToPoint:CGPointMake(100, 100) controlPoint1:CGPointMake(35, 25) controlPoint2:CGPointMake(75, 175)];
    //绘制
    [path stroke];
}

Quartz2D对于图片的应用

  • 对于图片来说获取上下文可以不需要在drawRect中,有自己的获取方式
  • 获取图片的上下文一定在 UIGraphicsBeginImageContext(),UIGraphicsEndImageContext()这两个方法中写,或者进行对图片的裁剪,旋转,擦除等等.
  • 操作完图片之后可以用UIGraphicsGetImageFromCurrentImageContext()方法获得修改完之后的图片
  • 除了图片可以这样修改,PDF格式也提供了类似的方法

根据颜色生成图片

  • 实现原理:先获取一个固定大小的上下文,根据传进来的颜色,将上下文颜色填充,在image上平铺,输出image
//根据颜色生成图片
- (UIImage *)getImageWithColor:(UIColor *)color
{
    //开始
//    1.图片的尺寸,2.是否是不透明的,3.图片的缩放比例
    UIGraphicsBeginImageContext(CGSizeMake(200, 50));
    //获取上下文
    CGContextRef ref =  UIGraphicsGetCurrentContext();
    //设置颜色
    CGContextSetFillColorWithColor(ref, color.CGColor);
    //设置填充区域
    CGContextFillRect(ref, CGRectMake(0, 0, 100, 100));
    //填充
    CGContextDrawPath(ref, kCGPathFillStroke);
    //获取图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    //结束
    UIGraphicsEndImageContext();
    //输出图片
    return image;
}

图片的剪裁

//图片的裁剪
- (UIImage *)clipWithImage:(UIImage *)image
{
    //获取上下文(并给出这个上下文的尺寸)
    UIGraphicsBeginImageContext(CGSizeMake(image.size.width / 2.0, image.size.height));
    //这里的rect是值得在image的什么区域去绘制(下面这个写其实是绘制在整个image中)
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //结束
    UIGraphicsEndImageContext();
    //输出图片
    return UIGraphicsGetImageFromCurrentImageContext();
}

切圆

  • 实现原理:先画出一个圆型的上下文,再讲图片画到画布上
//切圆
- (UIImage *)clipWithimage:(UIImage *)image
{
    UIGraphicsBeginImageContext(image.size);
    //获取上下文
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //画圆
    CGContextAddArc(ref, image.size.width / 2.0, image.size.height / 2.0, image.size.height / 2.0, 0, M_PI * 2, NO);
    //裁剪画布
    CGContextClip(ref);
    // 把图片画到画布上
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //结束
    UIGraphicsEndImageContext();
    //输出并返回
    return  UIGraphicsGetImageFromCurrentImageContext();
}

图片旋转,平移,缩放

//图片旋转
- (UIImage *)transWithImage:(UIImage *)image
{
    UIGraphicsBeginImageContext(image.size);
    //获取上下文
    CGContextRef ref = UIGraphicsGetCurrentContext();
    //缩放(旋转缩放平移是在上下文操作图片)
    CGContextScaleCTM(ref, 0.6, 0.6);
    //平移
    CGContextTranslateCTM(ref, 50, 0);
    //旋转 1.上下文 2.角度
    CGContextRotateCTM(ref, M_PI_4);
    //把图片画到画布上
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    //结束
    UIGraphicsEndImageContext();
    //返回绘制的图片
    return UIGraphicsGetImageFromCurrentImageContext();
}

图片擦除(刮奖原理)(截屏也用到了这个的核心原理)

  • 实现原理:当手指触摸到屏幕上的时候,去到触摸的某一个点,放大成一个正方形或者圆形,形成橡皮的感觉,在滑动过的区域将图片刮除,显示下面的label或者其他view,一定要保证刮除的我图片一定是透明的,否则看不到下面的label或者view
- (void)viewDidLoad {
    [super viewDidLoad];
    //初始化要显示在下面的提示label
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 200, 50)];
    label.textAlignment = NSTextAlignmentCenter;
    label.text = @"恭喜您中奖了";
    [self.view addSubview:label];
    //初始化显示在上面的imageview(用上面的根据颜色生成图片方法生成一个灰色的图层,看起来像一种刮奖的图层)
    self.imageView = [[UIImageView alloc] initWithImage:[self getImageWithColor:[UIColor grayColor]]];
    self.imageView.frame = CGRectMake(100, 100, 200, 50);
    [self.view addSubview:self.imageView];
}
//刮奖()
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = touches.anyObject;
    CGPoint point = [touch locationInView:self.imageView];
    //滑块区域(触碰到的点放大成正方形)
   CGRect rect =  CGRectMake( point.x - 10,point.y - 10, 20, 20);
    //获取上下文(这里记得一定要透明)
    UIGraphicsBeginImageContextWithOptions(self.imageView.bounds.size, NO, 0);
   CGContextRef ref =  UIGraphicsGetCurrentContext();
    //把imageView的layer映射到上下文中(这个是核心,由于UIView本质上显示东西的layer层,所以实质是将imageView显示的东西全部复制给上下文,app中长用到的截屏就利用了这个原理)
    [self.imageView.layer renderInContext:ref];
    //清除划过的区域
    CGContextClearRect(ref, rect);
    UIImage *image =UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    //返回图片并不断的传给UIImageView上去显示
    self.imageView.image = image;

}

绘制文字(以图片的形式输出)(给图片右下角绘制专属的唯一标示(也就是水印)就用到了这个原理)

//绘制文字
- (UIImage *)drawWithStr:(NSString *)str
{
    //获取上下文
    UIGraphicsBeginImageContext(self.view.frame.size);
    //利用富文本设置文字的属性
    NSDictionary *dic = @{NSFontAttributeName:[UIFont systemFontOfSize:14.0f],NSForegroundColorAttributeName:[UIColor redColor]};
    //绘制在上下文中
    [str drawInRect:CGRectMake(10, 10, 200, 100) withAttributes:dic];
    //输出image
    return UIGraphicsGetImageFromCurrentImageContext();
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • Quartz2D以及drawRect的重绘机制字数1487 阅读21 评论1 喜欢1一、什么是Quartz2D Q...
    PurpleWind阅读 730评论 0 3
  • 什么是Quartz2D 是一个二维的绘图引擎,同时支持iOS和Mac系统 Quartz2D的API是纯C语言的,它...
    Mario_ZJ阅读 549评论 0 1
  • Quartz2D 简介 Quartz2D是二维(平面)的绘图引擎(经包装的函数库,方便开发者使用。也就是说苹果帮我...
    iOS_Cqlee阅读 608评论 0 2
  • 一、什么是Quartz2D Quartz2D是⼀个二维绘图引擎,同时支持iOS和Mac系统Quartz2D的API...
    CoderZb阅读 2,262评论 4 17
  • 天呐,到底怎么了,他到底怎么了
    丫头Alisa阅读 142评论 0 0