本文是通过结合使用cagradientlayer、cabasicanimation以及caanimationdelegate来达到颜色渐变以及转换的动画,下面是今天要达成的效果图:
首先创建一个cagradientlayer和几个自己喜欢的颜色,让vc持有。
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()
接下来为gradient赋值,将其frame等同于视图的大小,然后颜色先设置为colorone和colortwo,起始点和结束点分别为cgpoint(x:0, y:0)和cgpoint(x:1, y:1),并设置让其在后台线程异步绘制,最后添加到view的layer的sublayer中。
gradient.frame = self.view.bounds gradient.colors = [colorone,colortwo] gradient.startpoint = cgpoint(x:0, y:0) gradient.endpoint = cgpoint(x:1, y:1) gradient.drawsasynchronously = true self.view.layer.insertsublayer(gradient, at: 0)
现在运行后会得到下面的结果:
颜色渐变是做到了,那么如何做到颜色渐变的转换呢?这里还是需要用到cabasicanimation.
在gradient创建完之后,添加并调用一个方法animategradient,在里面添加一个keypath为colors的cabasicanimation,设置动画时长为3s,设置结束值等一系列属性。
func animategradient() { let gradientchangeanimation = cabasicanimation(keypath: "colors") gradientchangeanimation.duration = 3.0 gradientchangeanimation.tovalue = [colortwo,colorthree] gradientchangeanimation.fillmode = camediatimingfillmode.forwards gradientchangeanimation.isremovedoncompletion = false gradient.add(gradientchangeanimation, forkey: "gradientchangeanimation") }
这里就完成了转换动画。但是这里有个问题就是这里只转换了一次,无法转换多次颜色。那么这里就需要设置好tovalue,让每次的tovalue都不一样。
创建一个currentgradient和gradientset让vc持有。
var currentgradient: int = 0 var gradientset = [[cgcolor]]()
在animategradient中每次调用的时候,都对currentgradient的值进行判断和处理。
if currentgradient < gradientset.count - 1 { currentgradient = 1 } else { currentgradient = 0 }
并修改gradientchangeanimation的tovalue:
let gradientchangeanimation = cabasicanimation(keypath: "colors") gradientchangeanimation.duration = 3.0 gradientchangeanimation.tovalue = gradientset[currentgradient] gradientchangeanimation.fillmode = camediatimingfillmode.forwards gradientchangeanimation.isremovedoncompletion = false gradientchangeanimation.repeatcount = float.infinity gradient.add(gradientchangeanimation, forkey: "gradientchangeanimation")
这里运行后发现还是不行,还是只有一种颜色的转换,这是因为这里只调用了一次animategradient()。那么如何在合适的时机,也就是动画结束的时候再调用一次animategradient呢?这里就需要用到caanimationdelegate。
在caanimationdelegate的animationdidstop方法中重新调用animategradient。注意这里的gradient.colors 也要改变,否则就会一直是[colorone, colortwo]到其他颜色的变换。
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[currentgradient] animategradient() } }
完整代码:
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 = [[cgcolor]]() 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[currentgradient] 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([colorone, colortwo]) gradientset.append([colortwo, colorthree]) gradientset.append([colorthree, colorone]) // set the gradient size to be the entire screen gradient.frame = self.view.bounds gradient.colors = gradientset[currentgradient] 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[currentgradient] animategradient() } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。