swift实现颜色渐变以及转换动画
<p>本文是通过结合使用CAGradientLayer、CABasicAnimation以及CAAnimationDelegate来达到颜色渐变以及转换的动画,下面是今天要达成的效果图:</p><p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202201/2022126105505986.gif?2022026105548" /></p>
<p>首先创建一个CAGradientLayer和几个自己喜欢的颜色,让VC持有。</p>
<div class="jb51code"><pre class="brush:cpp;">let colorOne = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1).cgColor
let colorTwo = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1).cgColor
let colorThree = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1).cgColor
let gradient = CAGradientLayer()</pre></div>
<p>接下来为gradient赋值,将其frame等同于视图的大小,然后颜色先设置为colorOne和colorTwo,起始点和结束点分别为CGPoint(x:0, y:0)和CGPoint(x:1, y:1),并设置让其在后台线程异步绘制,最后添加到view的layer的sublayer中。</p>
<div class="jb51code"><pre class="brush:cpp;">gradient.frame = self.view.bounds
gradient.colors =
gradient.startPoint = CGPoint(x:0, y:0)
gradient.endPoint = CGPoint(x:1, y:1)
gradient.drawsAsynchronously = true
self.view.layer.insertSublayer(gradient, at: 0)</pre></div>
<p>现在运行后会得到下面的结果:</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202201/2022126105808607.jpg?2022026105821" /></p>
<p>颜色渐变是做到了,那么如何做到颜色渐变的转换呢?这里还是需要用到CABasicAnimation.<br />在gradient创建完之后,添加并调用一个方法animateGradient,在里面添加一个keyPath为colors的CABasicAnimation,设置动画时长为3s,设置结束值等一系列属性。</p>
<div class="jb51code"><pre class="brush:cpp;">func animateGradient() {
let gradientChangeAnimation = CABasicAnimation(keyPath: "colors")
gradientChangeAnimation.duration = 3.0
gradientChangeAnimation.toValue =
gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards
gradientChangeAnimation.isRemovedOnCompletion = false
gradient.add(gradientChangeAnimation, forKey: "gradientChangeAnimation")
}</pre></div>
<p>这里就完成了转换动画。但是这里有个问题就是这里只转换了一次,无法转换多次颜色。那么这里就需要设置好toValue,让每次的toValue都不一样。<br />创建一个currentGradient和gradientSet让VC持有。</p>
<div class="jb51code"><pre class="brush:cpp;">var currentGradient: Int = 0
var gradientSet = []()</pre></div>
<p>在animateGradient中每次调用的时候,都对currentGradient的值进行判断和处理。</p>
<div class="jb51code"><pre class="brush:cpp;">if currentGradient < gradientSet.count - 1 {
currentGradient += 1
} else {
currentGradient = 0
}</pre></div>
<p>并修改gradientChangeAnimation的toValue:</p>
<div class="jb51code"><pre class="brush:cpp;">let gradientChangeAnimation = CABasicAnimation(keyPath: "colors")
gradientChangeAnimation.duration = 3.0
gradientChangeAnimation.toValue = gradientSet
gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards
gradientChangeAnimation.isRemovedOnCompletion = false
gradientChangeAnimation.repeatCount = Float.infinity
gradient.add(gradientChangeAnimation, forKey: "gradientChangeAnimation")</pre></div>
<p>这里运行后发现还是不行,还是只有一种颜色的转换,这是因为这里只调用了一次animateGradient()。那么如何在合适的时机,也就是动画结束的时候再调用一次animateGradient呢?这里就需要用到CAAnimationDelegate。<br />在CAAnimationDelegate的animationDidStop方法中重新调用animateGradient。注意这里的gradient.colors 也要改变,否则就会一直是到其他颜色的变换。</p>
<div class="jb51code"><pre class="brush:cpp;">func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
// if our gradient animation ended animating, restart the animation by changing the color set
if flag {
gradient.colors = gradientSet
animateGradient()
}
}</pre></div>
<p>完整代码:</p>
<div class="jb51code"><pre class="brush:cpp;">import UIKit
class ViewController: UIViewController, CAAnimationDelegate {
let colorOne = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1).cgColor
let colorTwo = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1).cgColor
let colorThree = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1).cgColor
let gradient = CAGradientLayer()
var currentGradient: Int = 0
var gradientSet = []()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
NotificationCenter.default.addObserver(self, selector: #selector(handleEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
createGradientView()
}
@objc private func handleEnterForeground() {
animateGradient()
}
func animateGradient() {
// cycle through all the colors, feel free to add more to the set
if currentGradient < gradientSet.count - 1 {
currentGradient += 1
} else {
currentGradient = 0
}
// animate over 3 seconds
let gradientChangeAnimation = CABasicAnimation(keyPath: "colors")
gradientChangeAnimation.duration = 3.0
gradientChangeAnimation.toValue = gradientSet
gradientChangeAnimation.fillMode = CAMediaTimingFillMode.forwards
gradientChangeAnimation.isRemovedOnCompletion = false
//gradientChangeAnimation.repeatCount = Float.infinity
gradientChangeAnimation.delegate = self
gradient.add(gradientChangeAnimation, forKey: "gradientChangeAnimation")
}
func createGradientView() {
// overlap the colors and make it 3 sets of colors
gradientSet.append()
gradientSet.append()
gradientSet.append()
// set the gradient size to be the entire screen
gradient.frame = self.view.bounds
gradient.colors = gradientSet
gradient.startPoint = CGPoint(x:0, y:0)
gradient.endPoint = CGPoint(x:1, y:1)
gradient.drawsAsynchronously = true
self.view.layer.insertSublayer(gradient, at: 0)
animateGradient()
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
// if our gradient animation ended animating, restart the animation by changing the color set
if flag {
gradient.colors = gradientSet
animateGradient()
}
}
}</pre></div>
<p>以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持琼殿技术社区。</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>Swift实现表格视图单元格多选</li><li>Swift自定义UITableViewCell背景色</li><li>swift实现随机背景色</li><li>Swift Set集合及常用方法详解总结</li><li>Swift进阶教程Mirror反射示例详解</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]