項目有個需求須要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作,定時的去刷新顏色,也是一種實現方式。