本文所有示例代碼都是Swift4拯钻,參看文末鏈接
Core Animation是IOS和OS X平臺(tái)上負(fù)責(zé)圖形渲染與動(dòng)畫(huà)的基礎(chǔ)框架褂策。Core Animation可以作用與動(dòng)畫(huà)視圖或者其他可視元素竟宋,為你完成了動(dòng)畫(huà)所需的大部分繪畫(huà)工作缀拭。你只需要配置少量的動(dòng)畫(huà)參數(shù)(如開(kāi)始點(diǎn)的位置和結(jié)束點(diǎn)的位置)即可使用Core Animation的動(dòng)畫(huà)效果谆吴。Core Animation將大部分實(shí)際的繪圖任務(wù)交給了圖形硬件來(lái)處理煎谍,圖形硬件會(huì)加速圖形渲染的速度。這種自動(dòng)化的圖形加速技術(shù)讓動(dòng)畫(huà)擁有更高的幀率并且顯示效果更加平滑握牧,不會(huì)加重CPU的負(fù)擔(dān)而影響程序的運(yùn)行速度容诬。
上圖少了iOS9才引入的CASpringAnimation
, 它繼承至CABasicAnimation
一、常用屬性
這些屬性一般是在基類CAAnimation
和協(xié)議CAMediaTiming
中沿腰,是幾種動(dòng)畫(huà)類共用的屬性览徒。
duration : 動(dòng)畫(huà)的持續(xù)時(shí)間
beginTime : 動(dòng)畫(huà)的開(kāi)始時(shí)間
repeatCount : 動(dòng)畫(huà)的重復(fù)次數(shù)
autoreverses :動(dòng)畫(huà)結(jié)束時(shí)是否執(zhí)行逆動(dòng)畫(huà)
-
timingFunction : 控制動(dòng)畫(huà)的顯示節(jié)奏系統(tǒng)提供五種值選擇,分別是:
- kCAMediaTimingFunctionLinear 線性動(dòng)畫(huà)
- kCAMediaTimingFunctionEaseIn 先慢后快(慢進(jìn)快出)
- kCAMediaTimingFunctionEaseOut 先塊后慢(快進(jìn)慢出)
- kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
- kCAMediaTimingFunctionDefault 默認(rèn)颂龙,也屬于中間比較快
delegate : 動(dòng)畫(huà)代理习蓬。能夠檢測(cè)動(dòng)畫(huà)的執(zhí)行和結(jié)束,在動(dòng)畫(huà)執(zhí)行和結(jié)束做一些處理措嵌。
public protocol CAAnimationDelegate : NSObjectProtocol {
@available(iOS 2.0, *)
optional public func animationDidStart(_ anim: CAAnimation)
@available(iOS 2.0, *)
optional public func animationDidStop(_ anim: CAAnimation, finished flag: Bool)
}
- fillMode 動(dòng)畫(huà)在開(kāi)始和結(jié)束時(shí)的動(dòng)作躲叼。
- kCAFillModeRemoved 這個(gè)是默認(rèn)值,也就是說(shuō)當(dāng)動(dòng)畫(huà)開(kāi)始前和動(dòng)畫(huà)結(jié)束后企巢,動(dòng)畫(huà)對(duì)layer都沒(méi)有影響枫慷,動(dòng)畫(huà)結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài)
- kCAFillModeForwards 當(dāng)動(dòng)畫(huà)結(jié)束后,layer會(huì)一直保持著動(dòng)畫(huà)最后的狀態(tài)
- kCAFillModeBackwards 在動(dòng)畫(huà)開(kāi)始前或听,只需要將動(dòng)畫(huà)加入了一個(gè)layer探孝,layer便立即進(jìn)入動(dòng)畫(huà)的初始狀態(tài)并等待動(dòng)畫(huà)開(kāi)始。
- kCAFillModeBoth 這個(gè)其實(shí)就是上面兩個(gè)的合成.動(dòng)畫(huà)加入后開(kāi)始之前誉裆,layer便處于動(dòng)畫(huà)初始狀態(tài)顿颅,動(dòng)畫(huà)結(jié)束后layer保持動(dòng)畫(huà)最后的狀態(tài)
二、基礎(chǔ)動(dòng)畫(huà)(CABasicAnimation)
基礎(chǔ)動(dòng)畫(huà)就是從一個(gè)狀態(tài)值(fromValue)變換成另一個(gè)狀態(tài)值(toValue)足丢,特有的屬性:
- fromValue 所改變屬性的起始值
- toValue 所改變屬性的結(jié)束時(shí)的值
- byValue 所改變屬性相同起始值的改變量
下面的代碼是一個(gè)簡(jiǎn)單位置移動(dòng)動(dòng)畫(huà):
let moveView = UIView(frame: CGRect(x: 20, y: 240, width: 70, height: 70))
moveView.center = CGPoint(x: 40, y: 200)
moveView.backgroundColor = UIColor.red
view.addSubview(moveView)
let moveAnim = CABasicAnimation(keyPath: "position")
moveAnim.fromValue = NSValue(cgPoint: CGPoint(x: 40, y: 240))
moveAnim.toValue = NSValue(cgPoint: CGPoint(x: 300, y: 240))
moveAnim.duration = 2
moveAnim.repeatCount = Float.infinity
moveAnim.autoreverses = true
moveView.layer.add(moveAnim, forKey: "moveAnim")
另外
CABasicAnimation
還可以做旋轉(zhuǎn)粱腻、比例縮放、背景顏色變化斩跌、內(nèi)容(圖片)變化绍些、透明度變化、圓角變化耀鸦、指定大小變化等動(dòng)畫(huà)遇革。(這些我都寫(xiě)了一些示例代碼,鏈接在文末)這些動(dòng)畫(huà)的代碼形式基本都差不多揭糕,先建立視圖,然后創(chuàng)建
CABasicAnimation
類型動(dòng)畫(huà)對(duì)象锻霎,并指定不同的fromValue
著角、toValue
等屬性,最后把動(dòng)畫(huà)對(duì)象加入到視圖的CALayer
層旋恼。
三吏口、關(guān)鍵幀動(dòng)畫(huà)(CAKeyframeAnimation)
按照指定的一串值進(jìn)行動(dòng)畫(huà),好像拍電影一樣的一幀一幀的效果。
- values: 動(dòng)畫(huà)對(duì)象會(huì)在指定的時(shí)間(duration)內(nèi)冰更,依次顯示values數(shù)組中的每一個(gè)關(guān)鍵幀
- path : 可以設(shè)置一個(gè)CGPathRef\CGMutablePathRef,讓層跟著路徑移動(dòng)产徊。path只對(duì)CALayer的anchorPoint和position起作用。設(shè)置了path蜀细,那么values將被忽略舟铜。
- keyTimes : 可以為對(duì)應(yīng)的關(guān)鍵幀指定對(duì)應(yīng)的時(shí)間點(diǎn),其取值范圍為0到1.0,keyTimes中的每一個(gè)時(shí)間值都對(duì)應(yīng)values中的每一幀。當(dāng)keyTimes沒(méi)有設(shè)置的時(shí)候,各個(gè)關(guān)鍵幀的時(shí)間是平分的奠衔。
- rotationMode : 旋轉(zhuǎn)樣式
CABasicAnimation可看做是最多只有2個(gè)關(guān)鍵幀(開(kāi)始和結(jié)束)的CAKeyframeAnimation
下面的代碼通過(guò)values
做成抖動(dòng)的動(dòng)畫(huà):
let anima = CAKeyframeAnimation(keyPath: "transform.rotation")
anima.values = [-Double.pi/180*4,Double.pi/180*4, -Double.pi/180*4]
anima.repeatCount = Float.infinity
animView.layer.add(anima, forKey: "shake")
使用path
配合貝塞爾曲線就可以做成如下效果:
代碼
let tempView = UIView(frame: CGRect(x: 50, y: 100, width: 250, height: 500))
let bezierPath = UIBezierPath(ovalIn: tempView.frame)
let orbitAnim = CAKeyframeAnimation(keyPath: "position")
orbitAnim.duration = 5
orbitAnim.path = bezierPath.cgPath
orbitAnim.calculationMode = kCAAnimationPaced
orbitAnim.fillMode = kCAFillModeForwards
orbitAnim.repeatCount = Float.infinity
orbitAnim.rotationMode = kCAAnimationRotateAutoReverse
animView.layer.add(orbitAnim, forKey: "orbitAnim")
let shapeLayer = CAShapeLayer()
shapeLayer.strokeColor = UIColor.purple.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 0.5
shapeLayer.lineJoin = kCALineJoinRound
shapeLayer.lineCap = kCALineCapRound
shapeLayer.path = bezierPath.cgPath
view.layer.addSublayer(shapeLayer)
四谆刨、組動(dòng)畫(huà)(CAAnimationGroup)
組動(dòng)畫(huà)顧名思義就是把不同的動(dòng)畫(huà)組合起來(lái),比如下面的代碼:
// 位移
let anima1 = CABasicAnimation(keyPath: "position")
anima1.fromValue = NSValue(cgPoint: CGPoint(x: 40, y: 240))
anima1.toValue = NSValue(cgPoint: CGPoint(x: 300, y: 240))
// 縮放
let anima2 = CABasicAnimation(keyPath: "transform.scale")
anima2.fromValue = NSNumber.init(value: 0.8)
anima2.toValue = NSNumber.init(value: 2.0)
// 旋轉(zhuǎn)
let anima3 = CABasicAnimation(keyPath: "transform.rotation")
anima3.toValue = Double.pi*4
// 組合
let groupAnimation = CAAnimationGroup()
groupAnimation.animations = [anima1, anima2, anima3]
groupAnimation.duration = 3.0
animView.layer.add(groupAnimation, forKey: nil)
組合后的動(dòng)畫(huà)效果就是在移動(dòng)的同時(shí)归斤,也在縮放和旋轉(zhuǎn)痊夭。
五、過(guò)渡動(dòng)畫(huà)(CATransition)
CATransition用于做過(guò)渡動(dòng)畫(huà)或者轉(zhuǎn)場(chǎng)動(dòng)畫(huà)脏里,能夠?yàn)閷犹峁┮瞥銎聊缓鸵迫肫聊坏膭?dòng)畫(huà)效果她我。
- type:動(dòng)畫(huà)過(guò)渡類型
四個(gè)系統(tǒng)公開(kāi)的
系統(tǒng)公開(kāi)API | 效果說(shuō)明 | 是否支持方向 |
---|---|---|
kCATransitionFade | 淡出效果 | 是 |
kCATransitionMoveIn | 新視圖移動(dòng)到舊視圖上 | 是 |
kCATransitionPush | 新視圖推出舊視圖 | 是 |
kCATransitionReveal | 移開(kāi)舊視圖顯示新視圖 | 是 |
其他還有一些非系統(tǒng)公開(kāi)的過(guò)渡類型:
["cube", "suckEffect", "rippleEffect", "pageCurl", "pageUnCurl", "oglFlip"]
- subtype : 過(guò)渡動(dòng)畫(huà)的動(dòng)畫(huà)方向
kCATransitionFromRight 從右側(cè)進(jìn)入
kCATransitionFromLeft 從左側(cè)進(jìn)入
kCATransitionFromTop 從頂部進(jìn)入
kCATransitionFromBottom 從底部進(jìn)入
- startProgress:動(dòng)畫(huà)起點(diǎn)(在整體動(dòng)畫(huà)的百分比)
- endProgress:動(dòng)畫(huà)終點(diǎn)(在整體動(dòng)畫(huà)的百分比)
六、彈簧動(dòng)畫(huà) CASpringAnimation
常用屬性
- mass: 模擬的是質(zhì)量,影響圖層運(yùn)動(dòng)時(shí)的彈簧慣性番舆,質(zhì)量越大酝碳,彈簧拉伸和壓縮的幅度越大 默認(rèn)值:1 ;
- stiffness:剛度系數(shù)(勁度系數(shù)/彈性系數(shù)),剛度系數(shù)越大合蔽,形變產(chǎn)生的力就越大击敌,運(yùn)動(dòng)越快。默認(rèn)值: 100 拴事;
- damping:阻尼系數(shù)沃斤,阻止彈簧伸縮的系數(shù),阻尼系數(shù)越大刃宵,停止越快衡瓶。默認(rèn)值:10;
- initialVelocity:初始速率牲证,動(dòng)畫(huà)視圖的初始速度大小哮针。默認(rèn)值:0 ;
速率為正數(shù)時(shí)坦袍,速度方向與運(yùn)動(dòng)方向一致十厢,速率為負(fù)數(shù)時(shí),速度方向與運(yùn)動(dòng)方向相反捂齐; - settlingDuration:估算時(shí)間 返回彈簧動(dòng)畫(huà)到停止時(shí)的估算時(shí)間蛮放,根據(jù)當(dāng)前的動(dòng)畫(huà)參數(shù)估算;
實(shí)例:
// 不同的keypath奠宜,不同的效果
let springAnimation = CASpringAnimation(keyPath: "position.y")
if springAnimation.keyPath == "position" {
springAnimation.fromValue = NSValue.init(cgPoint: self.jellyView.layer.position)
springAnimation.toValue = NSValue.init(cgPoint: point)
} else if springAnimation.keyPath == "position.x" {
springAnimation.fromValue = self.jellyView.layer.position.x
springAnimation.toValue = point.x
} else if springAnimation.keyPath == "position.y" {
springAnimation.fromValue = self.jellyView.layer.position.y
springAnimation.toValue = point.y
} else if springAnimation.keyPath == "bounds" {
springAnimation.fromValue = NSValue.init(cgRect: CGRect(x: point.x, y: point.y, width: 60, height: 60))
springAnimation.toValue = NSValue.init(cgRect: self.jellyView.frame)
}
springAnimation.mass = 5
springAnimation.stiffness = 100
springAnimation.damping = 10
springAnimation.initialVelocity = 10
springAnimation.duration = springAnimation.settlingDuration
springAnimation.isRemovedOnCompletion = false
self.jellyView.layer.add(springAnimation, forKey: "springAnimation")
keyPath不同時(shí)效果不同:
代碼:本文所有的示例代碼都在https://github.com/andyRon/iOS-Animation
參考:
IOSAnimationDemo
iOS動(dòng)畫(huà)詳解(學(xué)習(xí)動(dòng)畫(huà)看這一篇就夠了)
一篇文章搞定 CASpringAnimation 彈簧動(dòng)畫(huà)
Core Animation 官方手冊(cè)