iOS 2D绘图详解(Quartz 2D)之概述
前言:最近在研究自定义控件,由于想要彻底的定制控件的视图还是要继承UIView,虽然对CALayer及其子类很熟练,但是对Quartz 2D这个强大的框架仍然概念模棱两可。于是,决定学习下,暂定7篇文章讲解,会写一些Demo。
官方文档
本文的代码Demo在最后一部分
Quartz 2D用来干嘛的?
Quartz 2D属于Core Graphics(所以大多数相关方法的都是以CG开头),是iOS/Mac OSX
提供的在内核之上的强大的2D绘图引擎,并且这个绘图引擎是设备无关的。也就是说,不用关心设备的大小,设备的分辨率,只要利用Quartz
2D,这些设备相关的会自动处理。Quartz 2D能够提供的强大功能如下
- 透明层(transparency layers)
- 阴影
- 基于path的绘图(path-based drawing)
- 离屏渲染(offscreen rendering)
- 复杂的颜色处理(advanced color management)
- 抗锯齿渲染(anti-aliased rendering)
- PDF创建,展示,解析(这部分不在这个系列之中)
- 配合Core Animation, OpenGL ES,UIKit完成复杂的功能
画板-The Graphics Context
既然提到绘图,那自然有一个容器来包含绘制的结果,然后把这个结果渲染到屏幕上去,而Quartz 2D的容器就是CGContextRef数据模型。这种数据模型是C的结构体,存储了渲染到屏幕上需要的一切信息。
那么,最后 Graphics Context 可以渲染到哪里呢?
- Layer
- Window
- 打印机
- Bitmap(图片)
绘制模型
Quartz 2D采用painter’s model,意味着每一次绘制都是一层,然后按照顺序一层层的叠加到画板上。例如
数据类型
Quartz 2D中的数据类型都是透明的,也就是说用户只需要使用即可,不需要实际访问其中的变量。具体的数据类型包括
- CGPathRef 路径类型,用来绘制路径(注意带有ref后缀的一般都是绘制的画板)
- CGImageRef,绘制bitmap
- CGLayerRef,绘制layer,layer可复用,可离屏渲染
- CGPatternRef,重复绘制
- CGShadingRef和CGGradientRef,绘制渐变(例如颜色渐变)
- CGFunctionRef,定义回调函数,CGShadingRef和CGGradientRef的辅助类型
- CGColorRef and CGColorSpaceRef,定义如何处理颜色
- CGFontRef,绘制文字
- 其他类型(pdf这个系列不讲解,所以不会涉及)
绘制状态
在使用quartz
2d进行绘图的时候,经常需要设置颜色,字体,设置context的坐标原点变换,context旋转。这些影响的都是当前绘制状态。Context中利用堆栈的方式来保存绘制状态。调用CGContextSaveGState来保存当前绘制状态的copy到堆栈中,利用CGContextRestoreGState弹出堆栈最顶层的绘制状态,设置为当前的绘制状态。注意,不是所有的参数都会保存,以下表格中的参数会保存
坐标系
和UIKit的坐标系不一样,Quartz 2D的坐标系是在左下角的。
Quartz利用坐标系的旋转位移等操作来绘制复杂的动画。
但是有两个地方的坐标系是正常的UIKit坐标系
- UIView 的context
- 通过这个方法UIGraphicsBeginImageContextWithOptions返回的context
一个简单的Demo讲解
新建一个UIView的子类,然后重写drawRect
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextFillRect(context, rect);//先填充整个区域
CGRect testRect = CGRectMake(10, 10, 20, 20);
CGContextAddRect(context, testRect);
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);//修改画笔颜色
CGContextFillRect(context, testRect);//填充部分区域
}
然后,这样调用
LeoDemoView * demoView = [[LeoDemoView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[self.view addSubview:demoView];
效果
可以看到坐标系是正常的UIKit坐标系
然后,我们在在上面绘制一个文字”Leo”,在上述drawRect的最后添加,
NSString * toDraw = @"Leo";
[toDraw drawAtPoint:CGPointMake(CGRectGetWidth(rect)/2, CGRectGetHeight(rect)/2) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12],NSForegroundColorAttributeName:[UIColor greenColor]}];
可以看到,绘制是一层一层覆盖的,
最后,我们在右下角绘制一个红心,但是希望红心是反过来的。这里用到了上文的所说的绘制状态堆栈。继续在drawRect的最后添加如下代码
CGContextSaveGState(context);
CGContextTranslateCTM(context,rect.size.width,rect.size.height);
CGContextRotateCTM(context, M_PI);
NSString * redHeart = @"��";//MarkDown 显示不出红心
[redHeart drawAtPoint:CGPointMake(0, 0) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15]}];
CGContextRestoreGState(context);
}
效果
这里,初学者可能不懂到底是怎么回事了。我通过图解的方式一步步解释
这行代码把坐标系移动到右下角
CGContextTranslateCTM(context,rect.size.width,rect.size.height);
如图
接着把坐标系逆时针旋转180度
CGContextRotateCTM(context, M_PI);
这时候的坐标系
这时候,参考这个坐标系进行绘制,看到的就是反过来的。哇咔咔!
iOS 2D绘图详解(Quartz 2D)之概述的更多相关文章
- iOS 2D绘图详解(Quartz 2D)之路径(点,直线,虚线,曲线,圆弧,椭圆,矩形)
前言:一个路径可以包含由一个或者多个shape以及子路径subpath,quartz提供了很多方便的shape可以直接调用.例如:point,line,Arc(圆弧),Curves(曲线),Ellip ...
- iOS 2D绘图详解(Quartz 2D)之阴影和渐变(Shadow,Gradient)
前言:这个系列写道这里已经是第五篇了,本文会介绍下阴影和渐变的基础知识,以及一些基本的Demo Code展示,应该还会有两篇,介绍下Bitmap绘制以及Pattern等知识. Shadow shado ...
- iOS开发 绘图详解
Quartz概述 Quartz是Mac OS X的Darwin核心之上的绘图层,有时候也认为是CoreGraphics.共有两种部分组成 Quartz Compositor,合成视窗系统,管理和合 ...
- iOS 2D绘图详解(Quartz 2D)之Bitmap
什么是Bitmap? Bitmap叫做位图,每一个像素点由1-32bit组成.每个像素点包括多个颜色组件和一个Alpha组件(例如:RGBA). iOS中指出如下格式的图片 JPEG, GIF, PN ...
- iOS 2D绘图详解(Quartz 2D)之Transform(CTM,Translate,Rotate,Scale)
前言:Quartz默认采用设备无关的user space来进行绘图,当context(画板)建立之后,默认的坐标系原点以及方向也就确认了,可以通过CTM(current transformation ...
- iOS 2D绘图详解(Quartz 2D)之路径(stroke,fill,clip,subpath,blend)
Stroke-描边 影响描边的因素 线的宽度-CGContextSetLineWidth 交叉线的处理方式-CGContextSetLineJoin 线顶端的处理方式-CGContextSetLine ...
- iOS中-Qutarz2D详解及使用
在iOS中Qutarz2D 详解及使用 (一)初识 介绍 Quartz 2D是二维绘图引擎. 能完成的工作有: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...
- 【转】Android Canvas绘图详解(图文)
转自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1212/703.html Android Canvas绘图详解(图文) 泡 ...
- 转载]IOS LBS功能详解[0](获取经纬度)[1](获取当前地理位置文本 )
原文地址:IOS LBS功能详解[0](获取经纬度)[1](获取当前地理位置文本作者:佐佐木小次郎 因为最近项目上要用有关LBS的功能.于是我便做一下预研. 一般说来LBS功能一般分为两块:一块是地理 ...
随机推荐
- MFC ListControl用法
http://blog.csdn.net/lovton/article/details/6527208 1.建立一个对象m_LogList 步骤:在对话listcontrol控件右键点击添加变量-&g ...
- Seam carving 学习笔记
今天首次接触了图像编辑中的seam carving知识,感觉挺神奇的.虽然我自己可能理解的不是很深刻,但是记录下来,总是好的. seam carving直接翻译过来是“线裁剪”的意思.它的主要用途是对 ...
- oracle文件管理OMF
OMF是为了简化对数据文件的管理,靠参数DB_CREATE_FILE_DEST实现: 如果定义了DB_CREATE_FILE_DEST,则创建表空间就不需要制定数据文件位置.文件名称,数据文件会按照固 ...
- C++继承与派生的概念、什么是继承和派生
在C++中可重用性是通过继承(inheritance)这一机制来实现的.因此,继承是C++的一个重要组成部分. 前面介绍了类,一个类中包含了若干数据成员和成员函数.在不同的类中,数据成员和成员函数是不 ...
- Python 变量 对象 引用
1.变量 变量第一次赋值时被创建,变量在使用前必须赋值 变量本身没有类型,变量类型为它引用的对象类型: 变量在使用时被替换成它引用的对象 2.对象 对象本身具有计数和类型,变量引用对象,当对象的引用变 ...
- HDU5807 Keep In Touch DP
// HDU5807 Keep In Touch DP // 思路:直接暴力是O(n^6).所以要优化一下 // dp[i][j][k][0]:当前点i j k的方案数 // dp[i][j][k][ ...
- 在Toast里面显示图片
关于怎么在Toast里面显示图片,首先自定义一个toast,在自定义一个布局,这个布局你想让toast显示什么样的布局就定义什么样的,然后在自定的布局中放一个ImageView,在把自己自定义 ...
- java类加载与初始化
第一段: class A{ public A(){ this.list(); } public void list(){ System.out.println("in a list..&qu ...
- 第三百零三天 how can I 坚持
今天年会,运气还不错,竟然中了个小奖,一个榨汁机,已经很满足了. 今天加上了她,感觉挺合适,就怕一句话聊不来就带搭不理的了.她很好,懂得知足,不攀比. 弟弟今天把房子首付交了,把贷款办完就算安心了,目 ...
- eclipse svn切换账号登陆问题
1.当一个人有权限访问文件代码,而另一个账号无法访问该文件代码,要在eclipse上切换账号登陆有权限的账号时,eclipse会用缓存的账号,不会弹出从新输入新账号的窗口. 这样该怎么解决呢? 关闭e ...