UIButton 背景色渐变动画

项目有个需求需要UIButton上的背景色是渐变动画的效果,如下。

这里写图片描述

实现原理

CAGradientLayer 用于实现渐变效果,CABasicAnimation用于对Layer做动画
源码:https://github.com/LSnumber1/ButtonColorGradientAnimation

思路

看gif图我们发现动画是从右到左,颜色一直渐变向左滑动的,把效果拆解下,可以分为两部分:

  1. 实现颜色的阶梯变化
  2. 对实现的阶梯颜色做动画

颜色阶级渐变

初始化一个CAGradientLayer,他的frame的宽高和UIButton的一致。

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,用于按钮上一次只对两个颜色做渐变

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层

colorButton.layer.addSublayer(caGradientLayer!)

至此,已经对UIButton做了颜色渐变

这里写图片描述

对实现的阶梯颜色做动画

动画我们用CABasicAnimation,对layer层做动画。
定义一个progress用于记录颜色的下标,startColors记录动画开始时的颜色组,endColors记录动画结束时的颜色组。

        var colorArray = caGradientLayer?.colors

        if endColors != nil {
            startColors = endColors
        }

每次启动动画时,我们先把colorArray移除掉第一个颜色,然后在colors中选择下标为progress+2的颜色,把该颜色追加到colorArray中。

        colorArray?.removeFirst()
        colorArray?.append(colors[Int(progress) + 2])
        endColors = colorArray

比如有A、B、C、D、E这几种颜色,颜色渐变是按照AB、BC、CD、DE这个顺序执行,这样保障了颜色顺畅的向左移动

创建动画如下

        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做,定时的去刷新颜色,也是一种实现方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值