Swift - Core Graphics绘图框架详解3(绘制渐变、填充渐变色)
Quartz 2D 的渐变方式分为如下两种:
使用中我们可以直接绘制一个渐变,也可以将渐变填充到现有的图形路径上。下面通过样例分别进行演示。
- 线性渐变:渐变色以直线方式从开始位置逐渐向结束位置渐变
- 放射性渐变:以中心点为圆心从起始渐变色向四周辐射,直到终止渐变色
一、渐变的绘制
1,绘制线性渐变
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let frame = CGRect(x: 30, y: 30, width: 250, height: 100)
let cgView = CGView(frame: frame)
self.view.addSubview(cgView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
class CGView:UIView {
override init(frame: CGRect) {
super.init(frame: frame)
//设置背景色为透明,否则是黑色背景
self.backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
//获取绘图上下文
guard let context = UIGraphicsGetCurrentContext() else {
return
}
//使用rgb颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
//颜色数组(这里使用三组颜色作为渐变)fc6820
let compoents:[CGFloat] = [0xfc/255, 0x68/255, 0x20/255, 1,
0xfe/255, 0xd3/255, 0x2f/255, 1,
0xb1/255, 0xfc/255, 0x33/255, 1]
//没组颜色所在位置(范围0~1)
let locations:[CGFloat] = [0,0.5,1]
//生成渐变色(count参数表示渐变个数)
let gradient = CGGradient(colorSpace: colorSpace, colorComponents: compoents,
locations: locations, count: locations.count)!
//渐变开始位置
let start = CGPoint(x: self.bounds.minX, y: self.bounds.minY)
//渐变结束位置
let end = CGPoint(x: self.bounds.maxX, y: self.bounds.minY)
//绘制渐变
context.drawLinearGradient(gradient, start: start, end: end,
options: .drawsBeforeStartLocation)
}
}
2,绘制放射性渐变
class CGView:UIView {
override init(frame: CGRect) {
super.init(frame: frame)
//设置背景色为透明,否则是黑色背景
self.backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
//获取绘图上下文
guard let context = UIGraphicsGetCurrentContext() else {
return
}
//使用rgb颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
//颜色数组(这里使用三组颜色作为渐变)fc6820
let compoents:[CGFloat] = [0xfc/255, 0x68/255, 0x20/255, 1,
0xfe/255, 0xd3/255, 0x2f/255, 1,
0xb1/255, 0xfc/255, 0x33/255, 1]
//没组颜色所在位置(范围0~1)
let locations:[CGFloat] = [0,0.5,1]
//生成渐变色(count参数表示渐变个数)
let gradient = CGGradient(colorSpace: colorSpace, colorComponents: compoents,
locations: locations, count: locations.count)!
//渐变圆心位置(这里外圆内圆都用同一个圆心)
let center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
//外圆半径
let endRadius = min(self.bounds.width, self.bounds.height) / 2
//内圆半径
let startRadius = endRadius / 3
//绘制渐变
context.drawRadialGradient(gradient,
startCenter: center, startRadius: startRadius,
endCenter: center, endRadius: endRadius,
options: .drawsBeforeStartLocation)
}
}
二、渐变的填充
不管是线性渐变、还是放射性渐变,除了像上面那样直接绘制到背景上外,还可以填充绘制成任何的形状。
首先我们自定义一个要填充的 path,无论是什么形状都可以。接着将其加入到 Context 中,用来做 Clip。最后在绘制渐变即可。
1,填充矩形
通过 context.clip(to: CGRect) 和 context.clip(to: [CGRect]),我们可以很方便的设置矩形的 Clip。下面样例使用后一个方法,在视图上同时添加多个矩形 Clip。
class CGView:UIView {
override init(frame: CGRect) {
super.init(frame: frame)
//设置背景色为透明,否则是黑色背景
self.backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
//获取绘图上下文
guard let context = UIGraphicsGetCurrentContext() else {
return
}
//创建clip矩形
let rect1 = CGRect(x: 0, y: 0,
width: self.bounds.width/4, height: self.bounds.height/2)
let rect2 = CGRect(x: self.bounds.maxX/4, y: self.bounds.maxY/2,
width: self.bounds.width/4, height: self.bounds.height/2)
let rect3 = CGRect(x: self.bounds.maxX/2, y: 0,
width: self.bounds.width/4, height: self.bounds.height/2)
let rect4 = CGRect(x: self.bounds.maxX/4*3, y: self.bounds.maxY/2,
width: self.bounds.width/4, height: self.bounds.height/2)
context.clip(to: [rect1, rect2, rect3, rect4])
//使用rgb颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
//颜色数组(这里使用三组颜色作为渐变)fc6820
let compoents:[CGFloat] = [0xfc/255, 0x68/255, 0x20/255, 1,
0xfe/255, 0xd3/255, 0x2f/255, 1,
0xb1/255, 0xfc/255, 0x33/255, 1]
//没组颜色所在位置(范围0~1)
let locations:[CGFloat] = [0,0.5,1]
//生成渐变色(count参数表示渐变个数)
let gradient = CGGradient(colorSpace: colorSpace, colorComponents: compoents,
locations: locations, count: locations.count)!
//渐变开始位置
let start = CGPoint(x: self.bounds.minX, y: self.bounds.minY)
//渐变结束位置
let end = CGPoint(x: self.bounds.maxX, y: self.bounds.minY)
//绘制渐变
context.drawLinearGradient(gradient, start: start, end: end,
options: .drawsBeforeStartLocation)
}
}
2,填充不规则的图形
要实现不规则形状的填充,可以先创建对应的 path 并添加到上下文中,再通过 context.clip() 方法设置 Clip 即可。下面以实现一个菱形渐变为例。
class CGView:UIView {
override init(frame: CGRect) {
super.init(frame: frame)
//设置背景色为透明,否则是黑色背景
self.backgroundColor = UIColor.clear
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
//获取绘图上下文
guard let context = UIGraphicsGetCurrentContext() else {
return
}
//创建并设置路径
let path = CGMutablePath()
path.move(to: CGPoint(x: self.bounds.midX, y: self.bounds.minY))
path.addLine(to: CGPoint(x: self.bounds.maxX, y: self.bounds.midY))
path.addLine(to: CGPoint(x: self.bounds.midX, y: self.bounds.maxY))
path.addLine(to: CGPoint(x: self.bounds.minX, y: self.bounds.midY))
path.closeSubpath()
//添加路径到图形上下文
context.addPath(path)
context.clip()
//使用rgb颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
//颜色数组(这里使用三组颜色作为渐变)fc6820
let compoents:[CGFloat] = [0xfc/255, 0x68/255, 0x20/255, 1,
0xfe/255, 0xd3/255, 0x2f/255, 1,
0xb1/255, 0xfc/255, 0x33/255, 1]
//没组颜色所在位置(范围0~1)
let locations:[CGFloat] = [0,0.5,1]
//生成渐变色(count参数表示渐变个数)
let gradient = CGGradient(colorSpace: colorSpace, colorComponents: compoents,
locations: locations, count: locations.count)!
//渐变开始位置
let start = CGPoint(x: self.bounds.minX, y: self.bounds.minY)
//渐变结束位置
let end = CGPoint(x: self.bounds.maxX, y: self.bounds.minY)
//绘制渐变
context.drawLinearGradient(gradient, start: start, end: end,
options: .drawsBeforeStartLocation)
}
}
