Swift - CAGradientLayer使用详解2(环形渐变进度条、渐变文字)
作者:hangge | 2017-08-31 08:10
在前文中,我简单地介绍了 CAGradientLayer 的使用(点击查看)。当时绘制的都是矩形渐变,其实配合各种 mask(遮罩),我们可以实现多种形状、样式的渐变。
(2)使用样例
源码下载:hangge_1770.zip
一、渐变圆环进度条
1,效果图
(1)下面实现一个用于温度显示的环形进度条。同一般的环形进度条不同,它的进度轨道是有渐变色的。随着温度的升高(进度值增加),颜色从蓝色慢慢渐变到黄色,最终渐变到红色。
(2)当进度值改变的时候,进度条前进或后退都有动画效果。
2,实现原理
(1)整个进度条组件分成进度条后面的轨道,以及覆盖在上方的具有渐变色的进度条。这里主要讲讲后者的实现。
(2)首先使用 CAShapeLayer 配合 UIBezierPath 绘制一个圆弧,这个便是进度条。进度条长短百分比我们可以通过 CAShapeLayer 的 strokeEnd 属性来实现。
(3)接着我们使用 CAGradientLayer 绘制一个渐变层。由于 CAGradientLayer 不能顺着弧线进行渐变,只能指定两个点之间进行渐变。所以我们先分别绘制左右两部分的渐变:
- 左半部分:颜色从上往下是黄色渐变到蓝色。
- 右半部分:颜色从上往下是黄色渐变到红色。
(4)最后将渐变层的遮罩设置成前面由 CAShapeLayer 创建的进度弧线,这样一个带有渐变色的进度圆弧就完成了。
3,样例代码
(1)TemperatureMeter.swift(进度条组件)
import UIKit class TemperatureMeter: UIView { //进度条所在圆的直径 let progressDiameter:CGFloat = 80 //进度条线条宽度 let progressWidth:CGFloat = 4 //进度条轨道颜色 let trackColor = UIColor.lightGray //渐变进度条 var progressLayer:CAShapeLayer! //进度文本标签 var label:UILabel! override init(frame: CGRect) { super.init(frame: frame) //创建进度文本标签 label = UILabel(frame:CGRect(x:0, y:0, width:bounds.width, height:progressDiameter)) label.textAlignment = .center label.text = "0℃" self.addSubview(label) //轨道以及上面进度条的路径(在组件内部水平居中) let path = UIBezierPath(arcCenter: CGPoint(x: bounds.midX, y: 40), radius: (progressDiameter-progressWidth)/2, startAngle: toRadians(degrees: -210), endAngle: toRadians(degrees: 30), clockwise: true) //绘制进度条背景轨道 let trackLayer = CAShapeLayer() trackLayer.frame = self.bounds trackLayer.fillColor = UIColor.clear.cgColor //设置轨道颜色 trackLayer.strokeColor = trackColor.cgColor //设置轨道透明度 trackLayer.opacity = 0.25 //轨道使用圆角线条 trackLayer.lineCap = kCALineCapRound //轨道线条的宽度 trackLayer.lineWidth = progressWidth //设置轨道路径 trackLayer.path = path.cgPath //将轨道添加到视图层中 self.layer.addSublayer(trackLayer) //绘制进度条 progressLayer = CAShapeLayer() progressLayer.frame = self.bounds progressLayer.fillColor = UIColor.clear.cgColor progressLayer.strokeColor = UIColor.black.cgColor progressLayer.lineCap = kCALineCapRound progressLayer.lineWidth = progressWidth progressLayer.path = path.cgPath //进度条默认结束位置是0 progressLayer.strokeEnd = 0 //将进度条添加到视图层中 self.layer.addSublayer(progressLayer) //绘制左侧的渐变层(从上往下是:由黄变蓝) let gradientLayer1 = CAGradientLayer() gradientLayer1.frame = CGRect(x:0, y:0, width:self.frame.width/2, height:progressDiameter/4 * 3 + progressWidth) gradientLayer1.colors = [UIColor.yellow.cgColor, UIColor.green.cgColor, UIColor.cyan.cgColor, UIColor.blue.cgColor] gradientLayer1.locations = [0.1,0.4,0.6,1] //绘制右侧的渐变层(从上往下是:由黄变红) let gradientLayer2 = CAGradientLayer() gradientLayer2.frame = CGRect(x:self.frame.width/2, y:0, width:self.frame.width/2, height:progressDiameter/4 * 3 + progressWidth) gradientLayer2.colors = [UIColor.yellow.cgColor, UIColor.red.cgColor] gradientLayer2.locations = [0.1,0.8] //用于存放左右两侧的渐变层,并统一添加到视图层中 let gradientLayer = CALayer() gradientLayer.addSublayer(gradientLayer1) gradientLayer.addSublayer(gradientLayer2) self.layer.addSublayer(gradientLayer) //将渐变层的遮罩设置为进度条 gradientLayer.mask = progressLayer } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } //设置进度(可以设置是否播放动画,以及动画时间) func setPercent(percent:CGFloat, animated:Bool = true) { //改变进度条终点,并带有动画效果(如果需要的话) CATransaction.begin() CATransaction.setDisableActions(!animated) CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)) progressLayer.strokeEnd = percent/100.0 CATransaction.commit() //设置文本标签值 label.text = "\(Int(percent))℃" } //把角度转换成弧度 func toRadians(degrees:CGFloat) -> CGFloat { return .pi*(degrees)/180.0 } }
(2)使用样例
import UIKit class ViewController: UIViewController { //滑块组件 @IBOutlet weak var slider: UISlider! //温度计组件 var meter:TemperatureMeter! override func viewDidLoad() { super.viewDidLoad() //创建并添加温度计组件 meter = TemperatureMeter(frame: CGRect(x: 40, y: 80, width: 80, height: 80)) self.view.addSubview(meter) } //滑块值改变响应 @IBAction func sliderDidchange(_ sender: Any) { //设置进度 meter.setPercent(percent: CGFloat(slider.value)) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
源码下载:hangge_1770.zip
二、渐变文字
1,效果图
“hangge.com”这个标签文字使用的是渐变色,从上往下由黄色渐变到橙色。
2,实现原理
(1)首先分别创建渐变层和文本标签。
(2)接着将渐变层的 mask 设置为文本标签即可。
3,样例代码
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //创建用于放置文本标签和渐变层的view let container = UIView(frame:CGRect(x:10, y:40, width:300, height:70)) self.view.addSubview(container) //创建文本标签 let label = UILabel(frame:CGRect(x:0, y:0, width:300, height:70)) label.text = "hangge.com" label.font = UIFont.boldSystemFont(ofSize: 52.0) container.addSubview(label) //创建渐变层 //定义渐变的颜色(从黄色渐变到橙色) let topColor = UIColor(red: 0xfe/255, green: 0xd3/255, blue: 0x2f/255, alpha: 1) let buttomColor = UIColor(red: 0xfc/255, green: 0x68/255, blue: 0x20/255, alpha: 1) let gradientColors = [topColor.cgColor, buttomColor.cgColor] //定义每种颜色所在的位置 let gradientLocations:[NSNumber] = [0.0, 1.0] //创建CAGradientLayer对象并设置参数 let gradientLayer = CAGradientLayer() gradientLayer.colors = gradientColors gradientLayer.locations = gradientLocations //设置其CAGradientLayer对象的frame,并插入container的layer gradientLayer.frame = label.frame container.layer.insertSublayer(gradientLayer, at: 0) //将渐变层的遮罩设置为label gradientLayer.mask = label.layer } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
全部评论(2)
加油加油
站长回复:谢谢你的支持和鼓励,我会继续更新下去的,欢迎常来看看。
默默支持,希望一直坚持下去
站长回复:谢谢你的支持,我会坚持下去的。