在iOS中常用的框架是Quartz 2D,它是Core Graphics框架的一部分,是一个强大的二维图像绘制引擎。我们日常开发所用到的UIKit的组件都是由Core Graphics框架进行绘制的。当我们导入UIKit框架时,会自动导入Core Graphics框架。

在iOS中绘图一般分为以下几个步骤:

1.获取绘图上下文

2.创建并设置路径

3.将路径添加到上下文

4.设置上下文的状态

5.绘制路径

6.释放路径

图形上下文中CGContextRef代表图形输出设备,也就是绘制的位置,包含绘制图形的一些设备信息,Quartz 2D中的所有对象,都最终都必须要添加到图形上下文,这样一来,我们在绘制图形的时候就不必关系具体的设备信息。


基本图形绘制

在UIKit中,已经默认为我们准备好一个图形上下文对象,在UIView的drawrect方法中,我们可以通过通过UIKit封装函数UIGraphicsGetCurrentContext()方法获取到图形上下文(注:在其它方法中无法获取),然后只需要按照绘制图形的步骤一步步执行即可,下面重写view的drawrect方法,在view上添加两条线:

override func draw(_ rect: CGRect) {
// 1.获取图形上下文对象
let contextRef = UIGraphicsGetCurrentContext() // 2.创建路径对象
let path = CGMutablePath()
path.move(to: CGPoint(x: 10, y: 10))
path.addLine(to: CGPoint(x: 100, y: 100)) // 这一段代码是绘制曲线,lengths 表示的是 虚线的每段长度为5,每段间距为1,phase 如果填2,则表示虚线的第一个线段的长度为 5 - 2
let a : CGFloat = 5
let b : CGFloat = 1
let lengths = [a,b]
contextRef?.setLineDash(phase: 2, lengths: lengths) path.move(to: CGPoint(x: 5, y: 20))
path.addLine(to: CGPoint(x: 100, y: 100)) // 3.添加到图像上下文
contextRef?.addPath(path) // 4.设置图形上下文状态属性
contextRef?.setStrokeColor(UIColor.red.cgColor) // 边框颜色
contextRef?.setFillColor(UIColor.blue.cgColor) // 填充颜色,可以在封闭路径中使用
contextRef?.setLineWidth(2) // 线条宽度 // 5.绘制
contextRef?.strokePath()
}

封闭图形绘制

上面的绘图方式显得有些麻烦,其实Core Graphics内部对创建路径对象添加到上下文这两步操作进行了封装,可以一步完成,下面我们用线段绘制一个简单的矩形:

//  1.获取图像上下文
let contextRef = UIGraphicsGetCurrentContext() // 2.开始绘制一个正方形
contextRef?.move(to: CGPoint(x: 10, y: 10))
contextRef?.addLine(to: CGPoint(x: 110, y: 10))
contextRef?.addLine(to: CGPoint(x: 110, y: 110))
contextRef?.addLine(to: CGPoint(x: 10, y: 110))
// 第四条线我们可以直接使用这个方法绘制
contextRef?.closePath() // 3.设置相关状态
contextRef?.setLineWidth(2)
contextRef?.setStrokeColor(UIColor.red.cgColor)
contextRef?.setFillColor(UIColor.blue.cgColor) // 4.开始绘制 .既有边框(路径),又有填充
contextRef?.drawPath(using: .fillStroke)

绘制一个矩形

上面的代码已经相对来说简化了不少,除了路径之外,矩形,椭圆也都有相应的绘制方法。

// ----------- 使用addRect方法绘制 ------------

        //  1.获取图像上下文
let contextRef = UIGraphicsGetCurrentContext()
// 2.路径
contextRef?.addRect(CGRect(x: 10, y: 10, width: 100, height: 100))
// 3.状态
contextRef?.setFillColor(UIColor.blue.cgColor)
contextRef?.setStrokeColor(UIColor.red.cgColor)
// 4.绘制
contextRef?.drawPath(using: .fillStroke)

  

// ----------- 使用UI方法绘制 ------------

        //  绘制一个填充色为红色的矩形
UIColor.red.setFill()
UIRectFill(CGRect(x: 10, y: 10, width: 100, height: 100)) // 绘制一个边框为蓝色的矩形
UIColor.blue.setStroke()
UIRectFrame(CGRect(x: 20, y: 20, width: 100, height: 100))

 绘制一个圆

//  1.获取图形上下文
let contextRef = UIGraphicsGetCurrentContext() // 2.先规定一个矩形
let rect = CGRect(x: 10, y: 10, width: 100, height: 100) // 3.添加内切圆
contextRef?.addEllipse(in: rect) // 内切圆 // 4.设置填充色
contextRef?.setFillColor(UIColor.red.cgColor) // 5.绘制
contextRef?.drawPath(using: .fill)

 绘制一个弧形

//  1.获取图形上下文
let contextRef = UIGraphicsGetCurrentContext() // 2.添加弧度
let center = CGPoint(x: 100, y: 100) // 圆心坐标
     contextRef.moveTo(center)         //  加上这句代码就可以绘制出一个扇形
let radius : CGFloat = 50 // 半径
let startAngle : CGFloat = 0 // 开始弧度制
let endAngle : CGFloat = CGFloat(Double.pi/4) // 结束弧度制
let clockwise = true // 是否逆时针
contextRef?.addArc(center: center, radius: CGFloat(radius), startAngle: startAngle, endAngle: endAngle, clockwise: clockwise) // 3.设置填充色
contextRef?.setFillColor(UIColor.red.cgColor) // 4.绘制
contextRef?.drawPath(using: .fill)

  


渐变色填充

在上面的Demo中我们可以看到如何设置填充颜色,事实上很多时候纯色的填充并不能满足我们的足球,例如有的时候我们需要绘制一些图形可能需要设置一个漂亮的背景,如果UI MM不给切图的话,这个时候我们可能就会选择渐变填充的方式。

Quartz 2D的渐变方式分为两种:

a.线性渐变线:渐变色以直线方式从开始位置逐渐向结束位置渐变

b.径向渐变:以中心点为圆心从起始渐变色向四周辐射,直到终止渐变色。

要做渐变则必须先设置从开始位置到结束位置的渐变颜色,UI MM可定对于渐变色设置并不陌生,只需要在指定位置指定不同的颜色,剩下的事情交给系统处理就行。如下图,在起始位置,3/10位置,结束位置指定了三种颜色就形成了由三种颜色组成的渐变色。

另外,在iOS中绘制渐变还需要注意一点就是指定颜色空间,所谓颜色空间就是不同颜色在不同的维度上取值,最终组成一种颜色的过程。就拿RGB来说,如果将红色,绿色,蓝色看成是x、y、z轴坐标系,那么在三个坐标上分别取0-255范围内的不同值则可以组成各类颜色。当然,不同颜色空间的坐标系也是不同的,也就是说颜色表示的方式是不同的,常用的颜色空间除了RGB还有CMYK(印刷业常用这种颜色模式)、Gray.

在使用Quartz 2D绘图时我们的颜色除了使用常规的方法(如CGContextSetRGBFillColor(CGContextRef context, CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)方法)设置RGB和透明度之外,有时还会遇到颜色参数是一个数组情况。如使用颜色空间填充时用到的CGContextSetFillColor(CGContextRef context, const CGFloat *components)方法,这个时候components数组中具体是如何存储颜色就要根据颜色空间而定,如果颜色空间使用RGB,则数组中的元素四个为一组,分别是red、green、blue、alpha;如果使用的是CMYK颜色空间,那么数组中的元素五个为一组,分别是cyan、magenta、yellow、black、alpha。

下面,分别使用一下这两种渐变的方式:

1.线性渐变

override func draw(_ rect: CGRect) {

        //  获取上下文
let contextRef = UIGraphicsGetCurrentContext() // 使用RGB颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB() // 指定渐变色
/*
colorSpace : 颜色空间
colorComponents : 颜色数组,由于指定了为RGB颜色空间,那么四个数组元素就表示一个颜色(red\green\blue\alpha),如果有三个颜色,那么这个数组中就要有 3 * 4 个元素。
locations : 颜色所在的位置 0 - 1,这个数组的个数不小于颜色的个数
count : 渐变的个数,等于locations的count
*/ let colorComponents : [CGFloat] = [248.0/255.0,86.0/255.0,86.0/255.0,1,
249.0/255.0,127.0/255.0,127.0/255.0,1,
1.0,1.0,1.0,1.0]
let locations : [CGFloat] = [0,0.3,1.0] let gradient = CGGradient(colorSpace: colorSpace, colorComponents: colorComponents, locations: locations, count: 3) // 绘制线性颜色渐变
/*
start : 起始坐标
end : 结束坐标
options :绘制方式,kCGGradientDrawsBeforeStartLocation 开始位置之前就进行绘制,到结束位置之后不再绘制,
kCGGradientDrawsAfterEndLocation开始位置之前不进行绘制,到结束点之后继续填充
*/
contextRef?.drawLinearGradient(gradient!, start: CGPoint(x : 0, y : 20), end: CGPoint(x : 0, y : self.frame.size.height - 40), options: .drawsBeforeStartLocation) }

2.径向渐变

override func draw(_ rect: CGRect) {

        //  获取上下文
let contextRef = UIGraphicsGetCurrentContext() // 使用RGB颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB() // 指定渐变色
/*
colorSpace : 颜色空间
colorComponents : 颜色数组,由于指定了为RGB颜色空间,那么四个数组元素就表示一个颜色(red\green\blue\alpha),如果有三个颜色,那么这个数组中就要有 3 * 4 个元素。
locations : 颜色所在的位置 0 - 1,这个数组的个数不小于颜色的个数
count : 渐变的个数,等于locations的count
*/ let colorComponents : [CGFloat] = [248.0/255.0,86.0/255.0,86.0/255.0,1,
249.0/255.0,127.0/255.0,127.0/255.0,1,
1.0,1.0,1.0,1.0]
let locations : [CGFloat] = [0,0.3,1.0] let gradient = CGGradient(colorSpace: colorSpace, colorComponents: colorComponents, locations: locations, count: 3) /*绘制径向渐变
context:图形上下文
gradient:渐变色
startCenter:起始点位置
startRadius:起始半径(通常为0,否则在此半径范围内容无任何填充)
endCenter:终点位置(通常和起始点相同,否则会有偏移)
endRadius:终点半径(也就是渐变的扩散长度)
options:绘制方式,kCGGradientDrawsBeforeStartLocation 开始位置之前就进行绘制,但是到结束位置之后不再绘制,
kCGGradientDrawsAfterEndLocation开始位置之前不进行绘制,但到结束点之后继续填充
*/
let center = CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2)
contextRef?.drawRadialGradient(gradient!, startCenter: center, startRadius: 0, endCenter: center, endRadius: 30, options: .drawsAfterEndLocation) }

 3.渐变填充

上面我们只是绘制渐变到图形上下文,实际开发中有时候我们还需要填充对应的渐变色,例如现在绘制了一个矩形,如何填充成渐变色呢?在此可以利用渐变裁切来完成(当然利用层CALayer更加方便),特别说明一下区域裁切并不仅仅适用于渐变填充,对于其他图形绘制仍然适用,并且注意裁切只能限于矩形裁切。

override func draw(_ rect: CGRect) {

        //  获取上下文
let contextRef = UIGraphicsGetCurrentContext() // 使用RGB颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB() //裁切还可以使用UIKit中对应的方法
UIRectClip(CGRect(x: 0, y: 20, width: self.frame.size.width, height: self.frame.size.height - 40)) // 指定渐变色
/*
colorSpace : 颜色空间
colorComponents : 颜色数组,由于指定了为RGB颜色空间,那么四个数组元素就表示一个颜色(red\green\blue\alpha),如果有三个颜色,那么这个数组中就要有 3 * 4 个元素。
locations : 颜色所在的位置 0 - 1,这个数组的个数不小于颜色的个数
count : 渐变的个数,等于locations的count
*/ let colorComponents : [CGFloat] = [248.0/255.0,86.0/255.0,86.0/255.0,1,
249.0/255.0,127.0/255.0,127.0/255.0,1,
1.0,1.0,1.0,1.0]
let locations : [CGFloat] = [0,0.3,1.0] let gradient = CGGradient(colorSpace: colorSpace, colorComponents: colorComponents, locations: locations, count: 3) // 绘制线性颜色渐变
/*
start : 起始坐标
end : 结束坐标
options :绘制方式,kCGGradientDrawsBeforeStartLocation 开始位置之前就进行绘制,到结束位置之后不再绘制,
kCGGradientDrawsAfterEndLocation开始位置之前不进行绘制,到结束点之后继续填充
*/
contextRef?.drawLinearGradient(gradient!, start: CGPoint(x : 0, y : 20), end: CGPoint(x : 0, y : self.frame.size.height - 40), options: .drawsBeforeStartLocation) }

  

Core Graphics框架的更多相关文章

  1. 在drawRect:方法中绘制图片,文字以及Core Graphics 框架的了解

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 } p.p2 { margin: 0.0px 0. ...

  2. Core Graphics框架是Quartz的核心,也是内容描画的基本接口。

    Core Graphics框架是Quartz的核心,也是内容描画的基本接口.

  3. iOS绘图UIBezierPath 和 Core Graphics框架

    前言 iOS系统本身提供了两套绘图的框架,即UIBezierPath 和 Core Graphics.而前者所属UIKit,其实是对Core Graphics框架关于path的进一步封装,所以使用起来 ...

  4. Core Graphics框架 利用Quartz 2D绘图

    首先,什么是Core Graphics和Quartz 2D? Core Graphics:是基于Quartz 2D绘图引擎的一个C语言的API绘图框架.它也是iOS开发中最基本的框架(Framewor ...

  5. UIKit,Core Data , Core Graphics, Core Animation,和OpenGLES框架

    iOS的主要框架介绍   框架是一个目录,这个目录包含了共享库,访问共享库里代码的头文件,和其它的图片和声音的资源文件.一个共享库定义的方法或函数可以被应用程序调用. IOS提供了很多你可以在应用程序 ...

  6. iOS绘图—— UIBezierPath 和 Core Graphics

    前言 iOS系统本身提供了两套绘图的框架,即UIBezierPath 和 Core Graphics.而前者所属UIKit,其实是对Core Graphics框架关于path的进一步封装,所以使用起来 ...

  7. iOS绘图系统UIKit与Core Graphics

    概述 iOS主要的绘图系统有UIKit,Core Graphics,Core Animation,Core Image,Open GL等,本片博文主要介绍UIKit与Core Graphics的绘图系 ...

  8. Core Graphics 定制UIVIew 处理图片

    许多UIView的子类,如UIButton或UILabel,它们的形状都是系统固定的.但是,对于一些特殊的情况,我们需要绘制产品狗想要的图形.那么等待我们的只有两个选择:第一,可以使用UIImageV ...

  9. [译]Modern Core Graphics with Swift系列

    第一篇 想象一下你已经完成了你的app并且运行的很好,但是界面看上去太土,你可以在PS里面画好多不同尺寸的自定义控件,Apple并没有4x的retina屏幕. 或者你已经未雨绸缪,在代码中使用Core ...

随机推荐

  1. HTML中的行内元素和框元素详解

    定义 传统的块级元素定义中只是说明了在文档流中形成了一个块,在前后加换行,这里有些笼统. 其实框元素是指宏观上的框元素,它包括3种类型:1.本身就是块级元素 2.dispaly被设置为类block 3 ...

  2. Multimodal —— 看图说话(Image Caption)任务的论文笔记(二)引入attention机制

    在上一篇博客中介绍的论文"Show and tell"所提出的NIC模型采用的是最"简单"的encoder-decoder框架,模型上没有什么新花样,使用CNN ...

  3. vue-axios配置token,上传图片

    vue1.0用 vue-resource 目前不维护了 vue2.0用 axios 使用 1.安装axios, npm install axios 2.在main.js中配置 import axios ...

  4. 41. leetcode 53. Maximum Subarray

    53. Maximum Subarray Find the contiguous subarray within an array (containing at least one number) w ...

  5. 关于ajax请求rul时意外结束符号

    最终解决办法:web.config 中添加节点 <webServices>     <protocols>         <add name="HttpPos ...

  6. Vmware虚拟机安装win7系统教程

    第一步:下载虚拟机 可以下载VMware虚拟机,这里用的是Vmware12专业版,百度网盘直通车密码:c3mt密钥:5A02H-AU243-TZJ49-GTC7K-3C61N 第二部:安装 第三部:做 ...

  7. Unity 坐标 转换 详解 World世界坐标 Screen屏幕坐标 View视口坐标 GUI坐标 NGUI坐标 localPosition相对父级坐标

    在制作游戏中我们经常会遇到这样一个需求: 在人物模型的上面显示 名字.称号 一类的文字或者图片 如下图 人物模型属于是Camera1   UI Title信息属于NGUI Camera2 如下图 这时 ...

  8. 【机器学习PAI实践二】人口普查统计

    一.背景 感谢大家关注玩转数据系列文章,我们希望通过在阿里云机器学习平台上提供demo数据并搭建相关的实验流程的方式来帮助大家学习如何通过算法来挖掘数据中的价值.本系列文章包含详细的实验流程以及相关的 ...

  9. 读书笔记 之《Thinking in Java》(对象、集合)

    一.前言: 本来想看完书再整理下自己的笔记的,可是书才看了一半发现笔记有点多,有点乱,就先整理一份吧,顺便复习下前面的知识,之后的再补上. 真的感觉,看书是个好习惯啊,难怪人家说"书籍是人类 ...

  10. 修改maven的默认JDK

    在我们实际使用IDEA开发maven项目的时候,创建maven项目的默认版本是jdk1.5,当然我们可以通过其他手段去修改module的JDK版本,或JDK的编译级别等等,但是如果每次你都这样修改,那 ...