iOS - Core Graphics

iOS绘图系统简介

iOS绘图系统结构.png
  1. UIKit:最常用的视图框架,如UIView、UIButton等UIKit元素
  2. Core Animation:提供强大的2D和3D动画效果
  3. OpenGL Embeded System/OpenGL:主要用于游戏绘制,但它是一套编程规范,具体由设备制造商实现
  4. Core Graphics:主要绘图系统,常用于绘制自定义视图,纯C的API,使用Quartz2D做引擎
  5. Graphics Hardware:GPU处理纹理叠加等图像渲染问题,相比较于CPU,浮点运算能力更强

*Core Image:给图片提供各种滤镜处理,比如高斯模糊、锐化等

绘图周期

iOS在运行循环(run loop)中整合所有的绘图请求,并一次将它们绘制出来。
不能在主线程中进行复杂的操作,否则会造成主线程的卡顿。
不能在主线程之外的主视图上下文中绘制,只要不是在主视图上下文中绘制,一些UIKit方法是可以在后台线程中使用的。比如可以在任意线程上使用CGBitmapCreateContext创建CGBitmapContext对象并在里面绘图。

1. 视图绘制

调用UIView中的drawRect方法。如果一个视图调用setNeedsDisplay方法,它就被标记为重新绘制,并且会在下一次绘图周期中重新绘制,也就是会自动调用drawRect方法。

2. 视图布局

调用UIView中的layoutSubviews方法。如果视图中的子视图布局发生变化,需要重新排列,UIKit会自动调用setNeedsLayout方法,也就是对于发生变化的视图逐层次调用layoutSubviews方法。比如frame发生变化、滚动视图等。

你不应该手动调用drawRect:方法!如果你想调用drawRect:方法更新视图,只需发送setNeedsDisplay方法。这将使得drawRect:方法会在下一个适当的时间调用。当然,不要覆盖drawRect:方法除非你知道这样做绝对合法。比方说,在UIImageView子类中覆盖drawRect:方法是不合法的,你将得不到你绘制的图形。

Context

Core Graphics API所有的操作都在上下文中进行,获得一个图形上下文是我们完成绘图任务的第一步,你可以将图形上下文理解为一块画布

  1. 两大绘图框架:UIKit和Core Graphics
  2. 三种获得图形上下文的方法:(drawRect:、drawRect: inContext:、UIGraphicsBeginImageContextWithOptions)

UIKit

像UIImage、NSString(绘制文本)、UIBezierPath(绘制形状)、UIColor都知道如何绘制自己。这些类提供了功能有限但使用方便的方法来让我们完成绘图任务。一般情况下,UIKit就是我们所需要的。

使用UiKit,你只能在当前上下文中绘图,所以如果你当前处于UIGraphicsBeginImageContextWithOptions函数或drawRect:方法中,你就可以直接使用UIKit提供的方法进行绘图。如果你持有一个context:参数,那么使用UIKit提供的方法之前,必须将该上下文参数转化为当前上下文。幸运的是,调用UIGraphicsPushContext 函数可以方便的将context:参数转化为当前上下文,记住最后别忘了调用UIGraphicsPopContext函数恢复上下文环境。

Core Graphics

这是一个绘图专用的API族,它经常被称为QuartZ或QuartZ 2D。Core Graphics是iOS上所有绘图功能的基石,包括UIKit。

使用Core Graphics之前需要指定一个用于绘图的图形上下文(CGContextRef),这个图形上下文会在每个绘图函数中都会被用到。如果你持有一个图形上下文context:参数,那么你等同于有了一个图形上下文,这个上下文也许就是你需要用来绘图的那个。如果你当前处于UIGraphicsBeginImageContextWithOptions函数或drawRect:方法中,并没有引用一个上下文。为了使用Core Graphics,你可以调用UIGraphicsGetCurrentContext函数获得当前的图形上下文。

6种绘图形式

  1. 在UIView的子类方法drawRect:中绘制一个蓝色圆
let path = UIBezierPath(ovalIn: CGRect(x: 100, y: 0, width: 100, height: 100))
UIColor.red.setFill()
path.fill()
  1. 在UIView的子类方法drawRect:中使用Core Graphics实现绘制蓝色圆
let context = UIGraphicsGetCurrentContext()
context?.addEllipse(in: CGRect(x: 0, y: 0, width: 100, height: 100))
context?.setFillColor(UIColor.blue.cgColor)
context?.fillPath()
  1. 在UIView子类的drawLayer:inContext:方法中实现绘图任务。drawLayer:inContext:方法是一个绘制图层内容的代理方法。为了能够调用drawLayer:inContext:方法,我们需要设定图层的代理对象。但要注意,不应该将UIView对象设置为显示层的委托对象,这是因为UIView对象已经是隐式层的代理对象,再将它设置为另一个层的委托对象就会出问题。轻量级的做法是:编写负责绘图形的代理类
  1. 使用Core Graphics在drawLayer:inContext:方法中实现
  1. 使用UIKit实现
UIGraphicsBeginImageContextWithOptions(CGSize(width: 100, height: 100), true, 1)
    
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100))
UIColor.orange.setFill()
path.fill()
        
let image = UIGraphicsGetImageFromCurrentImageContext()

UIGraphicsEndImageContext()
  1. 使用Core Graphics实现
UIGraphicsBeginImageContextWithOptions(CGSize(width: 100, height: 100), true, 0)
        
let context = UIGraphicsGetCurrentContext()
context?.addEllipse(in: CGRect(x: 0, y: 0, width: 100, height: 100))
context?.setFillColor(UIColor.blue.cgColor)
context?.fillPath()

let image = UIGraphicsGetImageFromCurrentImageContext()

UIGraphicsEndImageContext()

UIImage常用的绘图操作

Core Graphics坐标系统

  1. UIKit点坐标系
  2. Core Grphics坐标系
    Core Graphics源于Mac OS X系统,在Mac OS X中,坐标原点在左下方并且正y坐标是朝上的,而在iOS中,原点坐标是在左上方并且正y坐标是朝下的。在大多数情况下,这不会出现任何问题,因为图形上下文的坐标系统是会自动调节补偿的。但是创建和绘制一个CGImage对象时就会暴露出倒置问题。
  3. 单位坐标系

透明、不透明、隐藏

视图上有三个比较容易混淆的属性:alpha(透明)、opaque(不透明)和hidden(隐藏)。下面就进行一下深入的区分。

alpha属性决定了视图会通过像素显示多少信息。alpha为1表示所有的视图信息都在像素上表现出来,而alpha为0表示没有视图信息能在像素上表示出来。

opaque,将视图标记为opaque,便是向绘图系统许诺即将绘制的每一个像素都要使用全不透明的颜色,这便允许绘图系统忽略被覆盖在下面的视图,这样可以改善性能,尤其是在进行变形的时候。与opaque紧密相关的是clearsContextBeforeDrawing。它的默认值是YES,会在调用drawRect之前将上下问设置为透明黑底。这样会避免视图中产生的任何垃圾数据。

hidden为YES的话,表示视图根本不会被绘制。

隐藏和透明视图不接受触摸事件,如果想创建一个透明视图并且接受触摸事件,可以这样来进行设置,设置它的alpha为1、opaque为NO且backgroundColor为你活[UIColor clearColor],来接手触摸事件。

Core Graphics上下文属性设置

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

推荐阅读更多精彩内容

  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎。它提供了低...
    ShanJiJi阅读 1,523评论 0 20
  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作为绘图引擎。它提供了低...
    木马不在转阅读 957评论 0 0
  • 原文地址:http://www.cocoachina.com/industry/20140115/7703.htm...
    默默_David阅读 6,102评论 0 1
  • 我开玩笑的时候,你当真了,你开玩笑的时候,我也当真了。我们彼此说“真心话”的时候,谁都以为只是开玩笑。 最近最火的...
    一个人写阅读 170评论 0 0
  • 初见阿容的时候,大抵是觉得他眉目是极好看的。呵。好看二字对阿颜来说已是评价极高。至于后来的相识,一眼相中的却是名字...
    纪听白阅读 335评论 0 0