iOS核心動(dòng)畫(huà)小結(jié)(swift)

本文所有示例代碼都是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)行速度容诬。

Core Animation常用類繼承關(guā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)提供五種值選擇,分別是:

    1. kCAMediaTimingFunctionLinear 線性動(dòng)畫(huà)
    2. kCAMediaTimingFunctionEaseIn 先慢后快(慢進(jìn)快出)
    3. kCAMediaTimingFunctionEaseOut 先塊后慢(快進(jìn)慢出)
    4. kCAMediaTimingFunctionEaseInEaseOut 先慢后快再慢
    5. 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)作躲叼。
    1. 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)
    2. kCAFillModeForwards 當(dāng)動(dòng)畫(huà)結(jié)束后,layer會(huì)一直保持著動(dòng)畫(huà)最后的狀態(tài)
    3. kCAFillModeBackwards 在動(dòng)畫(huà)開(kāi)始前或听,只需要將動(dòng)畫(huà)加入了一個(gè)layer探孝,layer便立即進(jìn)入動(dòng)畫(huà)的初始狀態(tài)并等待動(dòng)畫(huà)開(kāi)始。
    4. 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")

位移動(dòng)畫(huà)

另外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層旋恼。

基礎(chǔ)動(dòng)畫(huà)

三吏口、關(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)痊夭。

組合動(dòng)畫(huà)

五、過(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à)的百分比)
過(guò)渡動(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í)效果不同:


keyPath為bounds

keyPath為position

keyPath為position.y

代碼:本文所有的示例代碼都在https://github.com/andyRon/iOS-Animation

參考:
IOSAnimationDemo
iOS動(dòng)畫(huà)詳解(學(xué)習(xí)動(dòng)畫(huà)看這一篇就夠了)
一篇文章搞定 CASpringAnimation 彈簧動(dòng)畫(huà)
Core Animation 官方手冊(cè)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末包颁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子压真,更是在濱河造成了極大的恐慌娩嚼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滴肿,死亡現(xiàn)場(chǎng)離奇詭異岳悟,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)嘴高,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門竿音,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人拴驮,你說(shuō)我怎么就攤上這事春瞬。” “怎么了套啤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵宽气,是天一觀的道長(zhǎng)随常。 經(jīng)常有香客問(wèn)我,道長(zhǎng)萄涯,這世上最難降的妖魔是什么绪氛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮涝影,結(jié)果婚禮上枣察,老公的妹妹穿的比我還像新娘。我一直安慰自己燃逻,他們只是感情好序目,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著伯襟,像睡著了一般猿涨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上姆怪,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天叛赚,我揣著相機(jī)與錄音,去河邊找鬼稽揭。 笑死俺附,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的溪掀。 我是一名探鬼主播昙读,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼膨桥!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起唠叛,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤只嚣,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后艺沼,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體册舞,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年障般,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了调鲸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挽荡,死狀恐怖藐石,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情定拟,我是刑警寧澤于微,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響株依,放射性物質(zhì)發(fā)生泄漏驱证。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一恋腕、第九天 我趴在偏房一處隱蔽的房頂上張望抹锄。 院中可真熱鬧,春花似錦荠藤、人聲如沸伙单。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)车份。三九已至,卻和暖如春牡彻,著一層夾襖步出監(jiān)牢的瞬間扫沼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工庄吼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缎除,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓总寻,卻偏偏與公主長(zhǎng)得像器罐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渐行,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容