返回 导航

Swift

hangge.com

Swift - Core Graphics绘图框架详解3(绘制渐变、填充渐变色)

作者:hangge | 2016-11-21 09:00
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)
    }
}
评论

全部评论(0)

回到顶部