Swift下‘有趣的’渐变和遮罩
很长时间没有写文章了,人变懒惰了。
很早之前看见一个公式:每天进步一点点,一年下来,你会发现进步很多。每天不进步,一年下来就会倒退很多。“逆水行舟,不进则退”,说的就是这个道理。
好了,闲话不多说。 今天的主角是
CAGradientLayer
。我将这篇文章归类为iOS Animation,因为在后续的教程中,我将会讲解如何利用CAGradientLayer创建动画`后续会有系列教程,敬请期待。
一、开始
文章中使用的开发环境是xcode9.1 , 用的是swift语言。关于CAGradientLayer是什么,这里就不做过多解释了,想要了解的朋友们,可以自己下去看苹果文档,或者百度一下。 最终效果键本文最后面附的图 完整项目下载地址.
- 1.1 首先我们在viewDidAppear()方法中创建一个渐变。
let gradient = CAGradientLayer() // 创建一个渐变层
gradient.frame = view.bounds // 设置frame(全屏显示)
gradient.startPoint = CGPoint(x: 0, y: 0) // 设置开始点
gradient.endPoint = CGPoint(x: 1, y: 1) // 设置结束点
可能有朋友会有疑问,开始点和结束点为什么是 (0, 0)和(1, 1)呢? 别急,看看下图就知道了。
开始点和结束点
当我们运行代码后,发现什么都没有。 当然啦,你要设置渐变色,首先你得设置CAGradientLayer的颜色,最重要的一步,你还要把它添加到View的layer上面。下图是显示效果
- 1.2 将gradient添加到控制器视图的layer上
// 设置渐变色(这里需要传递一个color数组)
gradient.colors = [UIColor(red: 0.0, green: 1.0, blue: 0.752, alpha: 1.0).cgColor,
UIColor(red: 0.949, green: 0.03, blue: 0.913, alpha: 1.0).cgColor]
// 将gradient添加到控制器视图的layer上
view.layer.addSublayer(gradient)
[图片上传失败...(image-c1eb26-1511180450498)]
效果图
看,是不是很漂亮?你也可以设置你自己喜欢的颜色。
二、渐变和UILabel结合
接下来,我们看看,当渐变和UILabel结合会是什么样子的。
按住键盘上的control+command 点击CAGradientLayer,会跳到它的定义。我们发现CAGradientLayer是继承CALayer的,CALayer有一个mask属性,mask属性???什么鬼?
CALayer的头文件关于mask的说明,mask实际上layer内容的一个遮罩,如果我们把mask是透明的,实际看到的layer是完全透明的,也就是说只有mask的内容不透明的部分和layer叠加的部分才会显示出来。
为了方便,我直接在storyBoard上拖了一个UILabel,并设置gradient.mask = label.layer;
。 再次运行项目可以看到的单词“文本”不是以其原始的黑色显示,而是在显示上文中我们设置的渐变颜色。为了使效果更酷,我们添加了一些动画,让其看起来更加有趣。
// UILabel动画, 需要传入一个字符串
func animateText(text: String) {
// text的长度大于0才会运行这个动画
if text.characters.count > 0 {
// startIndex : 第一个字符的位置
// text.index(after: text.startIndex) 给定位置之后的字符位置
// 下面两句的组合起来完成了本动画:label的文本从传入的字符串的第一个字符开始,每隔0.05秒添加一个字符到label上面,直至结束。
label.text = "\(label.text!)\(text.substring(to: text.index(after: text.startIndex)))"
delay(0.05, task: { // delay 是封装的一个延时方法,后面工程中会给出这部分封装的代码。
self.animateText(text: text.substring(from: text.index(after: text.startIndex)))
})
} else {
// 结束Label动画,如果要做别的操作,在这里添加代码
}
}
关于上面动画的说明:每0.05秒添加一个字符到label上,直到有字符添加。 它会自己递归地调用,所以你只需要用全文调用一次,然后让它自己工作。别忘记了在 viewDidAppear方法中调用 animateText(text: "需要显示的内容") 这个方法。下面是运行效果:
效果图
是不是很酷?😎😎😎。 我们还可以为gradient添加更多的mask,比如说添加一个按钮动画:
func addButtonRing() {
let side: CGFloat = 60.0
let button = CAShapeLayer() // CAShapeLayer 绘制圆环
button.position = CGPoint(x: label.bounds.width * 0.5 - side/2, y: label.bounds.height * 0.85) // 设置圆环的位置
button.strokeColor = UIColor.black.cgColor // 设置圆环边框的颜色
button.fillColor = UIColor.clear.cgColor // 设置圆环的填充颜色
button.path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: side, height: side)).cgPath // 设置路径
button.lineWidth = 1.0 // 边框宽度
button.opacity = 0.5 // 透明度
label.layer.addSublayer(button) // 将圆环添加到label的layer上面
// 缩放动画
let scale = CABasicAnimation(keyPath: "transform.scale") // 创建缩放动画
scale.fromValue = 1.0 // 开始值
scale.toValue = 0.67 // 结束值
scale.duration = 2.0 // 动画时间
scale.repeatCount = Float.infinity // 重复次数
scale.autoreverses = true // 逆向运行动画
button.add(scale, forKey: nil) // 为圆环添加动画
}
写好上面这些代码后,我们在哪里调用呢? 别急,还记得上面为UILabel添加动画的那个方法吗?(animateText),只需要在else里面调用这个方法就行了。
func animateText(text: String) {
if text.characters.count > 0 {
...
} else {
// 结束Label动画,如果要做别的操作,在这里添加代码
// 添加几个就是几个圆环
delay(0.1, task: {self.addButtonRing()})
delay(1.2, task: {self.addButtonRing()}) delay(2.4, task: {self.addButtonRing()})
}
}
现在让我们来看一下成果吧,见证奇迹的时候到了,哇咔咔。
效果图
我们还可以为它加一个imageView的遮罩,比如像这样, 最终效果见下图:
let imageView = UIImageView(image: UIImage(named: "dog3"))
imageView.center.x = label.bounds.width/2
label.addSubview(imageView)
效果图
图片的颜色也发生了渐变。