《iOS動(dòng)畫》讀書筆記·前序
《iOS動(dòng)畫》讀書筆記·顯示層動(dòng)畫
《iOS動(dòng)畫》讀書筆記·內(nèi)容層動(dòng)畫
《iOS動(dòng)畫》讀書筆記·轉(zhuǎn)場(chǎng)動(dòng)畫
UIView和CALayer的區(qū)別:
(1)UIView繼承UIResponder
歼跟,因此UIView可以處理響應(yīng)事件,而CALayer繼承NSObject
饲漾,所以它只負(fù)責(zé)內(nèi)容的創(chuàng)建、繪制。
(2)UIView負(fù)責(zé)對(duì)內(nèi)容的管理职辅,而CALayer負(fù)責(zé)對(duì)內(nèi)容的繪制
(3)UIView中的位置屬性只有frame蹬挺,bounds,center
澈圈,而CALayer除了這些之外還有anchorPoint彬檀,position
(4)通過修改CALayer可以實(shí)現(xiàn)UIView無法實(shí)現(xiàn)的很多高級(jí)功能
Core Animation核心動(dòng)畫
Core Animation
為iOS核心動(dòng)畫,它提供了一組豐富的API可以用于制作各種高級(jí)炫酷的動(dòng)畫效果瞬女。CoreAnimation
來自iOS的QuartzCore.framework
框架窍帝,它具備以下特點(diǎn):
(1)直接作用于CALayer圖層上
(2)Core Animation的執(zhí)行過程在后臺(tái)執(zhí)行,不阻塞主線程
(3)可用CALayer絕大多數(shù)屬性繪制高級(jí)動(dòng)畫效果
Core Animation
下各種常用動(dòng)畫類的繼承關(guān)系圖
-
@protocol CAMediaTiming
有很多動(dòng)畫公共的屬性诽偷,比如常見的duration / speed / repeatCount
等 -
CAAnimation
主要用于實(shí)現(xiàn)動(dòng)畫的委托代理方法坤学,比如動(dòng)畫的開始事件和結(jié)束事件 -
CAPropertyAnimation
為動(dòng)畫屬性,分為CABasicAnimation
基礎(chǔ)動(dòng)畫和CAKeyframeAnimation
關(guān)鍵幀動(dòng)畫 -
CAAnimationGroup
組合動(dòng)畫
-CATransition
轉(zhuǎn)場(chǎng)動(dòng)畫
CABasicAnimation基礎(chǔ)動(dòng)畫合集
(1)位置動(dòng)畫
posion
注意animation.toValue屬性表明改變了控件的位置报慕,所以給一個(gè)新的position的x,y坐標(biāo) animation.byValue表明在控件原來位置的基礎(chǔ)上深浮,沿x,y坐標(biāo)分別移動(dòng)了多少
(2)縮放動(dòng)畫
transform.scale.x / transform.scale.y
,scale有x,y
兩個(gè)屬性表明當(dāng)前UI控件的width/height的縮放系數(shù)
(3)旋轉(zhuǎn)動(dòng)畫
transform.rotation
(4)位移動(dòng)畫
transform.translation.x / transform.translation.y
表示在x/y
方向上移動(dòng)
(5)邊框動(dòng)畫
animation.keyPath = "borderWidth"
(6)顏色漸變
animation.keyPath = "backgroundColor"
animation.keyPath = "borderColor"
(7)淡入淡出
animation.keyPath = "opacity"
(8)陰影漸變
animation.keyPath = "shadowOffset"
這里就不舉具體的例子了卖子,可以參考這篇→_→核心動(dòng)畫-Core Animation
Core Animation:
關(guān)鍵字 CAKeyframeAnimation
CAKeyframeAnimation
:是CALayer
層下的關(guān)鍵幀動(dòng)畫類略号,實(shí)現(xiàn)類似UIView的關(guān)鍵幀動(dòng)畫效果(前面有介紹)。ACKeyframeAnimation
是CAPropertyAnimation
的一個(gè)子類洋闽,與CABasicAnimation
原理類似玄柠,都是通過修改當(dāng)前CALayer
圖層的value
屬性實(shí)現(xiàn)動(dòng)畫效果。不同的是CABasicAnimation
一般只使用fromeValue/toValue/byValue
诫舅,即只能修改一個(gè)value
值羽利。而CAKeyframeAnimation
則可以修改一組value
值來實(shí)現(xiàn)對(duì)動(dòng)畫的更精確細(xì)膩的控制。
CAAnimation Group
:組合動(dòng)畫刊懈,把各種動(dòng)畫組合起來形成各種效果
CAKeyframeAnimation
動(dòng)畫屬性要點(diǎn):
(1)values
數(shù)組類型这弧,數(shù)組中的每個(gè)元素描述了一個(gè)關(guān)鍵幀的相關(guān)屬性娃闲。比如描述關(guān)鍵幀位置的動(dòng)畫時(shí),values描述的是位置信息匾浪;比如描述關(guān)鍵幀縮放動(dòng)畫時(shí)皇帮,values描述的是縮放比例信息
(2)keyTimes
關(guān)鍵幀在動(dòng)畫周期默認(rèn)是勻速的。如果設(shè)置了該屬性蛋辈,那么每個(gè)關(guān)鍵幀顯示的周期為keyTimes*duration
(3)path
控制動(dòng)畫路徑属拾,通過設(shè)置CGPathRef/CGMutablePathRef
可以讓動(dòng)畫按照自己繪制的路徑運(yùn)行
案例
具體示例代碼看這里→_→https://github.com/SPIREJ/AnimationLayerSwift
1、CAEmitterCell粒子火焰效果
關(guān)鍵字:CAEmitterLayer / ACEmitterCell
粒子系統(tǒng)由兩部分組成:
CAEmitterLayer
CAEmitterCell
(1)CAEmitterLayer
為粒子發(fā)射圖層冷溶。該圖層主要用于控制粒子展現(xiàn)范圍渐白、粒子發(fā)射位置、粒子發(fā)射形狀逞频、渲染模式等纯衍。通過CAEmitterCell構(gòu)建的發(fā)射單元都受到CAEmitterLayer圖層節(jié)制。
(2)CAEmitterCell
粒子發(fā)射單元苗胀,控制粒子的移動(dòng)速度襟诸、方向、范圍等等基协,這些屬性可以制作酷炫的粒子特效動(dòng)畫
class EmitterFireVC: UIViewController {
let emitterCell = CAEmitterCell() //粒子單元cell
let emitterLayer = CAEmitterLayer()//粒子發(fā)射圖層
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.black;
// Do any additional setup after loading the view.
self.navigationItem.title = "粒子火焰效果"
emitterCell.name = "fire"http://粒子單元名稱
emitterCell.emissionLongitude = CGFloat(Double.pi)//該d粒子系統(tǒng)在xy平面的發(fā)射角度
emitterCell.velocity = -1//粒子速度1励堡,負(fù)表示沿y反方向運(yùn)動(dòng)
emitterCell.velocityRange = 50//粒子速度范圍
emitterCell.emissionRange = 1.1//粒子發(fā)射角度
emitterCell.yAcceleration = -200//粒子y方向的加速度分量
emitterCell.scaleSpeed = 0.3//縮放比例,超大火苗
emitterCell.birthRate = 500//粒子數(shù)
emitterCell.lifetime = 1//粒子生命周期
// 火焰顏色
emitterCell.color = UIColor(red: 0.8, green: 0.4, blue: 0.2, alpha: 0.1).cgColor
// 必須要設(shè)置粒子的“種子”內(nèi)容
emitterCell.contents = UIImage(named: "fire.png")!.cgImage
emitterLayer.position = self.view.center//粒子發(fā)射位置
emitterLayer.emitterSize = CGSize(width: 50, height: 10)//當(dāng)前火苗大小
// 當(dāng)前粒子渲染模式 和 發(fā)射源模式
emitterLayer.renderMode = .additive
emitterLayer.emitterMode = .outline
emitterLayer.emitterShape = .line
// 粒子單元部署到粒子發(fā)射圖層中
emitterLayer.emitterCells = [emitterCell]
self.view.layer.addSublayer(emitterLayer)
}
// 粒子速度
@IBAction func velocityChanged(_ sender: UISlider) {
// 重置粒子速度
emitterLayer.setValue(sender.value, forKeyPath: "emitterCells.fire.velocity")
}
// 粒子數(shù)
@IBAction func birthRateChanged(_ sender: UISlider) {
// 重置粒子生成速度堡掏,即粒子數(shù)
emitterLayer.setValue(sender.value, forKeyPath: "emitterCells.fire.birthRate")
}
}
2应结、CAEmitterCell粒子霓虹效果
關(guān)鍵字:CAEmitterLayer / ACEmitterCell
class EmitterNenoVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationItem.title = "霓虹效果"
self.view.backgroundColor = UIColor.black
let emitterCell = CAEmitterCell()
emitterCell.name = "neonlight"
emitterCell.emissionLongitude = CGFloat(Double.pi*2)// emissionLongitude:x-y 平面的 發(fā) 射方向
emitterCell.velocity = 50// 粒子速度
emitterCell.velocityRange = 50// 粒子速度范圍
emitterCell.scaleSpeed = -0.2// 縮放比例 超大火苗
emitterCell.scale = 0.1//縮放比例
//R G B alpha的顏色速度漸變效果
emitterCell.redSpeed = -0.2
emitterCell.greenSpeed = -0.1
emitterCell.blueSpeed = 0.1
emitterCell.alphaSpeed = -0.2
emitterCell.birthRate = 100//粒子生成速度
emitterCell.lifetime = 4//粒子生命周期
emitterCell.color = UIColor.white.cgColor//粒子背景顏色
//粒子效果內(nèi)容
emitterCell.contents = UIImage(named: "neonlight.png")!.cgImage
let emitterLayer = CAEmitterLayer()
emitterLayer.position = self.view.center// 粒子發(fā)射位置
emitterLayer.emitterSize = CGSize(width: 2, height: 2)// 控制粒子大小
emitterLayer.renderMode = CAEmitterLayerRenderMode.backToFront//著色(渲染)模式
emitterLayer.emitterMode = CAEmitterLayerEmitterMode.outline// 控制發(fā)射源模式 即形狀
emitterLayer.emitterShape = CAEmitterLayerEmitterShape.circle//形狀
emitterLayer.emitterCells = [emitterCell]
self.view.layer.addSublayer(emitterLayer)
}
}
3、CAGradientLayer 顏色梯度/位置梯度
CAGradientLayer
可以拆解為三個(gè)主要組成部分
CA
:CoreAnimation的縮寫泉唁,表明使用的是iOS框架下的核心動(dòng)畫部分
Gradient
:梯度的意思鹅龄,描述當(dāng)前動(dòng)畫的特點(diǎn),實(shí)現(xiàn)一些梯度功能的動(dòng)畫效果亭畜。比如位置的梯度變化扮休、顏色的梯度漸變等
Layer
:當(dāng)前動(dòng)畫作用在Layer內(nèi)容層
-
CALayer坐標(biāo)系
frame坐標(biāo)系與“梯度”坐標(biāo)系對(duì)應(yīng)關(guān)系
屬性
-
colors
var colors: [AnyObject]?
一個(gè)內(nèi)部是CGColorRef
的數(shù)組,規(guī)定所有的梯度所顯示的顏色,默認(rèn)為nil
-
locations
var locations: [NSNumber]?
一個(gè)內(nèi)部是NSNumber
的可選數(shù)組,規(guī)定所有的顏色梯度的區(qū)間范圍,選值只能在0到1之間
,并且數(shù)組的數(shù)據(jù)必須單增,默認(rèn)值為nil
-
endPoint
var endPoint: CGPoint
圖層顏色繪制的終點(diǎn)坐標(biāo),也就是階梯圖層繪制的結(jié)束點(diǎn),默認(rèn)值是(0.5,1.0)
-
startPoint
var startPoint: CGPoint
與endPoint
相互對(duì)應(yīng),就是繪制階梯圖層的起點(diǎn)坐標(biāo),繪制顏色的起點(diǎn),默認(rèn)值是(0.5,0.0)
-
type
var type:String
繪制類型,默認(rèn)值是kCAGradientLayerAxial
,也就是線性繪制,各個(gè)顏色階層直接的變化是線性的
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = UIColor.black
let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 200))
view.center = self.view.center
self.view.addSubview(view)
let gradientLayer:CAGradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 0, y: 1)
gradientLayer.colors = [UIColor.clear.cgColor,UIColor.white.cgColor,UIColor.clear.cgColor]
gradientLayer.locations = [0.0, 0.5, 1.0]
view.layer.addSublayer(gradientLayer)
let gradientAnimation:CABasicAnimation = CABasicAnimation()
gradientAnimation.keyPath = "colors"
gradientAnimation.fromValue = [UIColor.clear.cgColor,UIColor.white.cgColor,UIColor.clear.cgColor]
gradientAnimation.toValue = [UIColor.blue.cgColor,UIColor.red.cgColor,UIColor.cyan.cgColor]
//另一種方式 位置
//gradientLayer.locations = [0.0, 0.05, 0.1]
//gradientAnimation.keyPath = "locations"
//gradientAnimation.fromValue = [0.0, 0.05, 0.1]
//gradientAnimation.toValue = [0.9, 0.95, 1.0]
gradientAnimation.duration = 3.0
// 動(dòng)畫結(jié)束后保持結(jié)束后的狀態(tài)
gradientAnimation.isRemovedOnCompletion = false
gradientAnimation.fillMode = .forwards
gradientLayer.add(gradientAnimation, forKey: nil)
CAGradientLayer
結(jié)合CoreAnimation
可以實(shí)現(xiàn)很多酷炫的效果,有興趣的朋友可以自行研究
4拴鸵、CAReplicatorLayer圖層復(fù)制
#關(guān)鍵字 CAReplicatorLayer
主要用于圖層的快速復(fù)制玷坠,并且復(fù)制會(huì)保持被復(fù)制圖層的各種基礎(chǔ)屬性及動(dòng)畫
基本屬性
instanceCount
var instanceCount: Int
拷貝圖層的次數(shù),包括其所有的子圖層,默認(rèn)值是1,也就是沒有任何子圖層被復(fù)制instanceDelay
var instanceDelay: CFTimeInterval
在短時(shí)間內(nèi)的復(fù)制延時(shí),一般用在動(dòng)畫上(支持動(dòng)畫的延時(shí))instanceTransform
var instanceTransform: CATransform3D
復(fù)制圖層在被創(chuàng)建時(shí)產(chǎn)生的和上一個(gè)復(fù)制圖層的位移(位移的錨點(diǎn)是CAReplicatorlayer的中心點(diǎn))preservesDepth
var preservesDepth: Bool
如果設(shè)置為YES,圖層將保持于CATransformLayer類似的性質(zhì)和相同的限制instanceColor
var instanceColor: CGColor?
設(shè)置多個(gè)復(fù)制圖層的顏色,默認(rèn)位白色instanceRedOffset
var instanceRedOffset: Float
設(shè)置每個(gè)復(fù)制圖層相對(duì)上一個(gè)復(fù)制圖層的紅色偏移量instanceGreenOffset
var instanceGreenOffset: Float
設(shè)置每個(gè)復(fù)制圖層相對(duì)上一個(gè)復(fù)制圖層的綠色偏移量instanceBlueOffset
var instanceBlueOffset: Float
設(shè)置每個(gè)復(fù)制圖層相對(duì)上一個(gè)復(fù)制圖層的藍(lán)色偏移量instanceAlphaOffset
var instanceAlphaOffset: Float
設(shè)置每個(gè)復(fù)制圖層相對(duì)上一個(gè)復(fù)制圖層的透明度偏移量
(1) 圖層復(fù)制 - 雷達(dá)效果
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = UIColor.white
// 背景視圖
let bgView = UIView(frame: CGRect(x: 0, y: 0, width: kWidth, height: 200))
bgView.center = self.view.center
bgView.backgroundColor = UIColor.lightGray
self.view.addSubview(bgView)
// 動(dòng)畫原圖層,就是不斷變大的那個(gè)圓
let animationLayer = CAShapeLayer()
animationLayer.backgroundColor = UIColor.red.cgColor
animationLayer.bounds = CGRect(x: 0, y: 0, width: 20, height: 20)
animationLayer.cornerRadius = 10
animationLayer.position = CGPoint(x: kWidth/2.0, y: 100)
// 動(dòng)畫 - 放大
let transformScaleAnim = CABasicAnimation(keyPath: "transform")
let value = NSValue.init(caTransform3D:CATransform3DMakeScale(10, 10, 1))
transformScaleAnim.toValue = value
// 動(dòng)畫 - 透明度
let alphaAnim = CABasicAnimation(keyPath: "opacity")
alphaAnim.toValue = 0
// 加入到動(dòng)畫組
let animGroup = CAAnimationGroup()
animGroup.animations = [transformScaleAnim, alphaAnim]
animGroup.duration = 2
animGroup.repeatCount = HUGE
animationLayer.add(animGroup, forKey: nil)
// 復(fù)制圖層
let replicatorLayer = CAReplicatorLayer()
replicatorLayer.addSublayer(animationLayer)
replicatorLayer.instanceCount = 3 //復(fù)制圖層數(shù)
replicatorLayer.instanceDelay = 0.3//復(fù)制間隔時(shí)間
// 加載到視圖中顯示
bgView.layer.addSublayer(replicatorLayer)
}
(2) 圖層復(fù)制 - 加載動(dòng)畫效果
func ui_circle() {
// 背景視圖
let bgView = UIView(frame: CGRect(x: 0, y: 0, width: kWidth, height: 200))
bgView.center = self.view.center
bgView.backgroundColor = UIColor.lightGray
self.view.addSubview(bgView)
// 動(dòng)畫原圖層劲藐,就是不斷轉(zhuǎn)圈的圓
let animationLayer = CAShapeLayer()
animationLayer.backgroundColor = UIColor.red.cgColor
animationLayer.bounds = CGRect(x: 0, y: 0, width: 20, height: 20)
animationLayer.cornerRadius = 10
animationLayer.position = CGPoint(x: kWidth/2.0, y: 50)
animationLayer.transform = CATransform3DMakeScale(0, 0, 0)//初始隱藏
// 動(dòng)畫 - 縮放
let transformAnim = CABasicAnimation(keyPath: "transform")
transformAnim.duration = 2
transformAnim.repeatCount = HUGE
transformAnim.fromValue = NSValue.init(caTransform3D: CATransform3DMakeScale(1, 1, 1))
transformAnim.toValue = NSValue.init(caTransform3D: CATransform3DMakeScale(0.1, 0.1, 0.1))
animationLayer.add(transformAnim, forKey: nil)
// 復(fù)制圖層
let replicatorLayer = CAReplicatorLayer()
replicatorLayer.frame = bgView.bounds
replicatorLayer.addSublayer(animationLayer)
replicatorLayer.instanceCount = 10 //復(fù)制圖層數(shù)
replicatorLayer.instanceDelay = 0.2//復(fù)制間隔時(shí)間
replicatorLayer.instanceTransform = CATransform3DMakeRotation(CGFloat(Double.pi*2/Double(10)), 0, 0, 1.0)
// 加載到視圖中顯示
bgView.layer.addSublayer(replicatorLayer)
}
完整示例代碼https://github.com/SPIREJ/AnimationLayerSwift
如果您有興趣的話
上一節(jié)《iOS動(dòng)畫》讀書筆記·顯示層動(dòng)畫
下一節(jié)《iOS動(dòng)畫》讀書筆記·轉(zhuǎn)場(chǎng)動(dòng)畫