swift實現(xiàn)顏色漸變以及轉(zhuǎn)換動畫
本文是通過結(jié)合使用CAGradientLayer、CABasicAnimation以及CAAnimationDelegate來達(dá)到顏色漸變以及轉(zhuǎn)換的動畫,下面是今天要達(dá)成的效果圖:
首先創(chuàng)建一個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等同于視圖的大小,然后顏色先設(shè)置為colorOne和colorTwo,起始點和結(jié)束點分別為CGPoint(x:0, y:0)和CGPoint(x:1, y:1),并設(shè)置讓其在后臺線程異步繪制,最后添加到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)
現(xiàn)在運行后會得到下面的結(jié)果:
顏色漸變是做到了,那么如何做到顏色漸變的轉(zhuǎn)換呢?這里還是需要用到CABasicAnimation.
在gradient創(chuàng)建完之后,添加并調(diào)用一個方法animateGradient,在里面添加一個keyPath為colors的CABasicAnimation,設(shè)置動畫時長為3s,設(shè)置結(jié)束值等一系列屬性。
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") ? ? ? }
這里就完成了轉(zhuǎn)換動畫。但是這里有個問題就是這里只轉(zhuǎn)換了一次,無法轉(zhuǎn)換多次顏色。那么這里就需要設(shè)置好toValue,讓每次的toValue都不一樣。
創(chuàng)建一個currentGradient和gradientSet讓VC持有。
var currentGradient: Int = 0 var gradientSet = [[CGColor]]()
在animateGradient中每次調(diào)用的時候,都對currentGradient的值進(jìn)行判斷和處理。
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")
這里運行后發(fā)現(xiàn)還是不行,還是只有一種顏色的轉(zhuǎn)換,這是因為這里只調(diào)用了一次animateGradient()。那么如何在合適的時機(jī),也就是動畫結(jié)束的時候再調(diào)用一次animateGradient呢?這里就需要用到CAAnimationDelegate。
在CAAnimationDelegate的animationDidStop方法中重新調(diào)用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() ? ? ? ? } ? ? } ? ?? }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot3.0集成Redis緩存的實現(xiàn)示例
緩存就是一個存儲器,常用 Redis作為緩存數(shù)據(jù)庫,本文主要介紹了SpringBoot3.0集成Redis緩存的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下2024-03-03Objective-c代碼如何移植為Swift代碼 Objective-c代碼轉(zhuǎn)移到Swift過程介紹
這篇文章主要介紹了Objective-c代碼如何移植為Swift代碼,Objective-c代碼轉(zhuǎn)移到Swift過程介紹,需要的朋友可以參考下2014-07-07用Swift構(gòu)建一個簡單的iOS郵件應(yīng)用的方法
這篇文章主要介紹了用Swift構(gòu)建一個簡單的iOS郵件應(yīng)用的方法,包括查看和標(biāo)記已讀等基本的郵件應(yīng)用功能,需要的朋友可以參考下2015-07-07