iOS QuartZ 2D 窥探

QuartZ 2D

demo地址

本demo是由本人通过学习,看前辈们的博客看文档和自己学习的一个小总结,只用于学习使用,其中难避免有一些错误(如果发现了希望能指正),以及引用一些前辈总结出来的东西(如果内容为禁止引用请指出,小弟马上删除),所以此Demo仅供学习参考,不作为权威学习资料。

适用于:本人自己总结笔记, 对QuarZ 2D初步了解,作为笔记使用

本Demo只对一般的画图形以及基本图形操作进行一般总结

quraz2d.png

目录

QuartZ2D简介

QuartZ 2D(Core Graphics)是一个二维绘制引擎,同时支持iOS和Mac系统。它提供低级别、轻量级、高保真的2D渲染。该框架可以用于基于路径的绘图、变换、颜色管理、脱贫渲染、模板、渐变。

可以完成的工作

  • 绘制图形:线条\三角形\矩形\圆\弧 等
  • 绘制文字
  • 绘制\生成图片
  • 读取\生成PDF
  • 截图\裁剪图片

QuartZ2D开发中的作用

  • 绘制一些系统没有的图形,比如折线图
  • 自定义控件

图形上下文

图形上下文(CGContextRef)相当于画板,用于分钟绘画信息绘画状态和输出。

类型

  • Bitmap Graphics Context
  • PDF Graphics Context
  • Window Graphics Context
  • Layer Context
  • Post Graphics Context

DrawRect

UIView的显示

UIView的显示过程

1.当UIView需要显示时,内部的层会准备好一个CGConextRef(图形上下文)然后调用delegate(这里就是UIView)的drawLayer:inContext:方法,并且传入已经准备好的CGContextRef对象。而UIView在drawLayer:inContext:方法中又会调用自己的drawRect:方法
2平时在drawRect:中通过UIGraphicsGetCurrentContext()获取的就是由层传入的CGContextRef对象,在drawRect:中完成的所有绘图都会填入层的CGContextRef中,然后被拷贝至屏幕

UIView的显示原理

1既使不导入QuartzCore框架,NSObject和UIView类中的-drawLayer:inContext:方法,也是存在的,只是没有代码提示而已.
2默认情况下,根图层的delegate就是根图层所在的UIView对象,只不过是弱引用.
@property(assign) id delegate;
3当UIView需要显示时,它内部的view.layer图层会准备好一个CGContextRef关联到图层设备,然后调用view.layer.delegate代理(就是view)的(原生的)-drawLayer:inContext:方法.

绘图步骤

直接绘画

1.获取当前控件图形上下文
2.描述绘画内容
3.设置绘画上下文状态
4.渲染图形上下文

// 1.获取图形上下文
CGContextRef context = UIGraphicsGetCurrentContext();

// 2.直接绘制内容
CGContextMoveToPoint(context, 50, 50); // 移动到一个点
CGContextAddLineToPoint(context, 200, 50); // 画直线

//3. 设置属性
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); // 设置画笔颜色
CGContextSetLineWidth(context, 5); // 设置线宽

// 4.渲染
CGContextStrokePath(context);
format_context.png

通过添加路径(等)绘制

1.获取当前控件图形上下文
2.创建路径,描绘路径(CGPath, UIBezierPath)
3.把路径添加到上下文中
4.设置上下文状态
5.渲染上下文

// 1.获取当前山下文
CGContextRef context = UIGraphicsGetCurrentContext();

// 2.创建路径,描绘路径
CGMutablePathRef path = CGPathCreateMutable();

CGPathMoveToPoint(path, NULL, 10, 50); //移动到(10, 50)
CGPathAddLineToPoint(path, NULL, 300, 50); //画一条直线到(300, 50)

CGPathMoveToPoint(path, NULL, 10, 80); //移动到(10, 80)
CGPathAddLineToPoint(path, NULL, 300, 80); //画一条直线到(300, 80)

CGPathAddRect(path, NULL, CGRectMake(10, 100, 200, 200)); //画一个矩形(10, 100, 200, 200)

//3.把路径添加到上下文中
CGContextAddPath(context, path);
//4.设置上下文状态
[[UIColor redColor] set]; // 设置颜色
CGContextSetLineWidth(context, 10); //设置线宽
CGContextSetLineCap(context, kCGLineCapRound); //设置线终点样式
CGContextSetLineJoin(context, kCGLineJoinRound);//设置线拐角样式

//5.渲染
CGContextStrokePath(context);

//释放CGMutablePathRef
CGPathRelease(path);
format_addPath.png

通过UIBezierPath绘图

提示:
1.UIKit已经封装了一些绘图的功能:UIBezierPath,里面封装了很多东西,可以帮我画一些基本的线段,矩形,圆等等,一般开发中用贝塞尔路径绘图。
2.CGPath转换:UIKit框架转CoreGraphics直接 .CGPath 就能转换

绘制过程:
1.创建Bezier路径
2.绘制bezier路径
3.设置bezier状态
4.绘制路径

//1.获取UIBezierPath
UIBezierPath *path = [UIBezierPath bezierPath];

//2. 画一个圆 参数分别是: 圆心,半径,开始弧度,结束弧度,顺时针
[path addArcWithCenter:self.center radius:100 startAngle:0 endAngle:M_PI * 2 clockwise:YES];

//3.设置状态
[[UIColor blueColor] set]; //设置颜色
[path setLineWidth:5]; //设置线宽

//4.渲染
[path stroke];
format_bezier.png

画图形

直线

// 获取行下文
CGContextRef context = UIGraphicsGetCurrentContext();

float width = self.bounds.size.width; //宽度
float heiht = self.bounds.size.height; //高度
float distance = 40; //间距

float beginY = 10; //开始的Y坐标
float beginX = 10; //开始的X坐标

//横线
NSInteger countOfX = (heiht - beginY)/distance;
for(NSInteger index = 0; index <= countOfX; index ++){
float Y = beginY + index * distance;
CGPoint begin = CGPointMake(beginX, Y);
CGPoint end   = CGPointMake(width, Y);

CGContextMoveToPoint(context, begin.x, begin.y);
CGContextAddLineToPoint(context, end.x, end.y);
}

//竖线
NSInteger countOfY = (width - beginX)/distance;
for(NSInteger index = 0; index <= countOfY; index ++){
float X = beginX + index * distance;
CGPoint begin = CGPointMake(X, beginY);
CGPoint end   = CGPointMake(X, heiht);

CGContextMoveToPoint(context, begin.x, begin.y);
CGContextAddLineToPoint(context, end.x, end.y);
}

// 设置属性
[[UIColor blueColor] set];
CGContextSetLineWidth(context, 0.5);

// 渲染
CGContextStrokePath(context);
graphical_lines.png

三角形

// 三角形的三个点
CGPoint point1 = CGPointMake(160, 100);
CGPoint point2 = CGPointMake(10,  300);
CGPoint point3 = CGPointMake(320, 300);

// 绘制点
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:point1];
[path addLineToPoint:point2];
[path addLineToPoint:point3];
[path addLineToPoint:point1];

// 设置样式
[[UIColor redColor] set];
[path setLineWidth:10];
[path setLineJoinStyle:kCGLineJoinRound];

// 渲染
[path stroke];
graphical_triangle.png

矩形

//1.获取上下文
CGContextRef context  = UIGraphicsGetCurrentContext();

//2.画第一个矩形
CGContextAddRect(context, CGRectMake(50, 50, 100, 100));
[UIColor redColor];
CGContextStrokePath(context);

//3.画第二个矩形
CGContextAddRect(context, CGRectMake(50, 200, 200, 200));
[[UIColor blueColor] set];
CGContextSetLineWidth(context, 5);
CGContextStrokePath(context);
graphical_rect.png

椭圆

//1.获取上下文
CGContextRef context  = UIGraphicsGetCurrentContext();
//第一个椭圆(圆)
CGContextAddEllipseInRect(context, CGRectMake(50, 50, 200, 200));
[[UIColor redColor] set];
CGContextSetLineWidth(context, 5);
CGContextStrokePath(context);
//第二个圆(椭圆)
CGContextAddEllipseInRect(context, CGRectMake(50, 300, 300, 200));
[[UIColor blueColor] set];
CGContextSetLineWidth(context, 10);
CGContextStrokePath(context);
graphical_ellipse.png

圆弧

CGContextRef context  = UIGraphicsGetCurrentContext();
// 参数依次是: 上下文,圆心x, 圆心y, 半径, 开始弧度, 结束弧度, 逆时针方向
CGContextAddArc(context, 200, 200, 90, M_PI_2, M_PI, YES);
CGContextStrokePath(context);
//第二个圆弧
CGContextMoveToPoint(context, 200, 400);
CGContextAddArc(context, 200, 400, 90, 0, M_PI_2, YES);
CGContextAddLineToPoint(context, 200, 400);
[[UIColor grayColor] set];
CGContextFillPath(context);
graphical_arc.png

曲线

UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(0, 200)];
//第一段曲线 参数:到的点,控制点(具体查看赛贝尔线)
[path addQuadCurveToPoint:CGPointMake(self.bounds.size.width * 0.5, 200) controlPoint:CGPointMake(self.bounds.size.width * 0.25, 150)];
//第二段曲线
[path addQuadCurveToPoint:CGPointMake(self.bounds.size.width, 200) controlPoint:CGPointMake(self.bounds.size.width * 0.75, 250)];
[[UIColor redColor] set];
[path setLineWidth:2];
[path stroke];
graphical_curve.png

图片处理

水印

/** 图片加水印 */
+ (UIImage *)imageName:(NSString *)imageName logoImageName:(NSString *)logoImageName {
    UIImage *image = [UIImage imageNamed:imageName];
    // 开始Image上下文
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
    //画主图
    [image drawAtPoint:CGPointZero]; //
    //画log图
    UIImage *logoImage = [UIImage imageNamed:logoImageName];
    [logoImage drawInRect:CGRectMake(image.size.width - 100, image.size.height - 100, 100, 100)];
    //获取合成图
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndPDFContext();
    return newImage;
}
image_logo.png

剪切

/** 图片剪切 */
+ (UIImage *)imageClip:(NSString *)imageName {
    UIImage *image = [UIImage imageNamed:imageName];
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
    //剪切
    UIBezierPath *path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(image.size.width * 0.5, image.size.height * 0.5) radius:image.size.width * 0.5 startAngle:0 endAngle:M_PI * 2 clockwise:YES];
    [path addClip];
    // 画图
    [image drawAtPoint:CGPointZero];
    // 获取新图片
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

demo地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352