项目有个需求须要UIButton上的背景色是渐变更画的效果,以下。git
CAGradientLayer 用于实现渐变效果,CABasicAnimation用于对Layer作动画
源码: https://github.com/LSnumber1/...
看gif图咱们发现动画是从右到左,颜色一直渐变向左滑动的,把效果拆解下,能够分为两部分:github
初始化一个CAGradientLayer,他的frame的宽高和UIButton的一致。app
var caGradientLayer = CAGradientLayer() caGradientLayer?.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
CAGradientLayer涉及到一个坐标,该坐标体系以左上角为圆点(0,0),右下角为终点(1,1)
![]()
CAGradientLayer的startPoint是绘制阶级颜色的起始点,对应的endPoint为绘制阶级颜色的终点动画
caGradientLayer?.startPoint = CGPoint(x: 0, y: 0) caGradientLayer?.endPoint = CGPoint(x: 1, y: 0)
定义个颜色坐标组,用于为绘制提供颜色,colors是全部变色的颜色组,另外定义一个变量colors2,用于按钮上一次只对两个颜色作渐变spa
let colors = [ UIColor.init(red: 162/255, green: 94/255, blue: 255/255, alpha: 1).cgColor, UIColor.init(red: 108/255, green: 153/255, blue: 255/255, alpha: 1).cgColor, UIColor.init(red: 105/255, green: 201/255, blue: 255/255, alpha: 1).cgColor, UIColor.init(red: 102/255, green: 235/255, blue: 221/255, alpha: 1).cgColor, UIColor.init(red: 103/255, green: 249/255, blue: 145/255, alpha: 1).cgColor, UIColor.init(red: 228/255, green: 250/255, blue: 139/255, alpha: 1).cgColor, UIColor.init(red: 255/255, green: 198/255, blue: 88/255, alpha: 1).cgColor, UIColor.init(red: 255/255, green: 120/255, blue: 102/255, alpha: 1).cgColor, UIColor.init(red: 162/255, green: 94/255, blue: 255/255, alpha: 1).cgColor ] let colors2 = [colors[0],colors[1]] caGradientLayer?.colors = colors2
把caGradientLayer放在UIButton上的layer层code
colorButton.layer.addSublayer(caGradientLayer!)
至此,已经对UIButton作了颜色渐变图片
动画咱们用CABasicAnimation,对layer层作动画。
定义一个progress用于记录颜色的下标,startColors记录动画开始时的颜色组,endColors记录动画结束时的颜色组。rem
var colorArray = caGradientLayer?.colors if endColors != nil { startColors = endColors }
每次启动动画时,咱们先把colorArray移除掉第一个颜色,而后在colors中选择下标为progress+2的颜色,把该颜色追加到colorArray中。get
colorArray?.removeFirst() colorArray?.append(colors[Int(progress) + 2]) endColors = colorArray
好比有A、B、C、D、E这几种颜色,颜色渐变是按照AB、BC、CD、DE这个顺序执行,这样保障了颜色顺畅的向左移动
建立动画以下animation
let animation = CABasicAnimation(keyPath: "colors") animation.fromValue = startColors animation.toValue = endColors animation.duration = 1 animation.fillMode = kCAFillModeForwards animation.isRemovedOnCompletion = false animation.delegate = self caGradientLayer?.add(animation, forKey: "animateGradient")
经过 fillMode设置为kCAFillModeForwards、 isRemovedOnCompletion设置为false,保证了一个动画结束后,再也不恢复到原状态,颜色组之间的切换会比较顺畅。
最后一步是监听动画的结束,当动画结束时,咱们应该立马改变caGradientLayer中的颜色值,以及progress,并启动新的动画
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { caGradientLayer?.colors = endColors gradientAnimation() progress += 1.0 if Int(progress + 2) >= colors.count { progress = 0 } }
以上实现动画循环播放是在动画中止时,开启新的动画,还有一种方式是利用Timer作,定时的去刷新颜色,也是一种实现方式。