UIButton 背景色漸變更畫

項目有個需求須要UIButton上的背景色是漸變更畫的效果,以下。git

圖片描述

實現原理

CAGradientLayer 用於實現漸變效果,CABasicAnimation用於對Layer作動畫
源碼: https://github.com/LSnumber1/...

思路

看gif圖咱們發現動畫是從右到左,顏色一直漸變向左滑動的,把效果拆解下,能夠分爲兩部分:github

  1. 實現顏色的階梯變化
  2. 對實現的階梯顏色作動畫

顏色階級漸變

初始化一個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作,定時的去刷新顏色,也是一種實現方式。
相關文章
相關標籤/搜索