讓CALayer的shadowPath跟隨bounds一起做動畫改變

前言

在iOS開發(fā)中,我們經(jīng)常需要給視圖添加陰影效果锈玉,最簡單的方法就是通過設(shè)置CALayer的shadowColor爪飘、shadowOpacity、shadowOffset和shadowRadius這幾個屬性可以很方便的為 UIView 添加陰影效果拉背。但是如果單用這幾個屬性會導(dǎo)致離屏渲染(Offscreen Rendering)师崎,而且CoreAnimation在每一幀繪制陰影的時候都需要遞歸遍歷所有sublayer的alpha通道從而精確的計(jì)算出陰影的輪廓,這是非常消耗性能的椅棺,從而導(dǎo)致了動畫的卡頓犁罩。

為了盡可能地減小離屏渲染帶來的性能影響,我們可以利用CALayer的另外一個屬性shadowPath两疚,這個屬性的官方文檔是這么描述的:

If you specify a value for this property, the layer creates its shadow using the specified path instead of the layer’s composited alpha channel. The path you provide defines the outline of the shadow. It is filled using the non-zero winding rule and the current shadow color, opacity, and blur radius.

可以看到設(shè)置了這個屬性以后CALayer在創(chuàng)建其shadow的時候不在遍歷sublayer的alpha通道床估,而是直接用這個屬性所指定的路徑作為陰影的輪廓,這樣就減少了非常多的計(jì)算量诱渤。

然而這里會有一個問題丐巫,shadowPath并不會跟隨CALayer的bounds屬性進(jìn)行變化,所以在layer的bounds產(chǎn)生變化以后需要手動更新shadowPath才能讓其適配新的bounds。

為了解決這個問題递胧,在使用AutoLayout以前碑韵,因?yàn)閎ounds都是手動計(jì)算出來的,我們可以很容易的直接設(shè)定新的shadowPath缎脾,而使用了AutoLayout以后祝闻,我們則只能在UIView的layoutSubivews方法中才能獲得更新后的bounds。

而且文檔中還做了如下描述:

Unlike most animatable properties, this property (as with all CGPathRef animatable properties) does not support implicit animation.

這說明該變量是不支持隱式動畫的遗菠,也就是說當(dāng)我們直接設(shè)置CALayer的shadowPath屬性后联喘,系統(tǒng)并不會自動的提交隱式的CATransaction動畫。

為了解決了這個問題辙纬,我們需要通過CABasicAnimation顯示地指定shadowPath的動畫效果豁遭,同時為了和bounds的動畫效果保持一致,我們需要獲取bounds的動畫屬性牲平。

考慮了以上兩點(diǎn)問題以后堤框,我們就可以用如下方法實(shí)現(xiàn)讓CALayer的shadowPath跟隨bounds一起做動畫改變。

要特別注意一點(diǎn)的是纵柿,在iOS8以后bounds的隱式動畫默認(rèn)是開啟additive模式的蜈抓,而CALayer的shadowPath屬性并不支持additive模式,所以如果在前一個shadowPath動畫執(zhí)行完畢前如果提交了新的動畫昂儒,使用本方法將會看到shadowPath和bounds的動畫不一致的現(xiàn)象沟使。在Demo中可快速點(diǎn)擊改變Bounds的按鈕來復(fù)現(xiàn)該現(xiàn)象。

實(shí)現(xiàn)方法

為實(shí)現(xiàn)本文的思路渊跋,我們需要創(chuàng)建一個一個UIView的子類并且重寫其layoutSubivew方法腊嗡。

// Subclass of UIView
- (void)layoutSubviews {
    [super layoutSubviews];
    if (self.shouldAnimateShadowPath) {
        CAAnimation *animation = [self.layer animationForKey:@"bounds.size"];
        if (animation) {
            // 通過CABasicAnimation類來為shadowPath添加動畫
            CABasicAnimation *shadowPathAnimation = [CABasicAnimation animationWithKeyPath:@"shadowPath"];
            // 根據(jù)bounds的動畫屬性設(shè)置shadowPath的動畫屬性
            shadowPathAnimation.timingFunction = animation.timingFunction;
            shadowPathAnimation.duration = animation.duration;
            // iOS8 bounds的隱式動畫默認(rèn)開啟了additive屬性,當(dāng)前一次bounds change的動畫還在進(jìn)行中時拾酝,
            // 新的bounds change動畫將會被疊加在之前的上燕少,從而讓動畫更加順滑
            // 然而shadowPath并不支持additive animation,所以當(dāng)多個動畫疊加蒿囤,將會看到shadowPath和bounds動畫不一致的現(xiàn)象
            // shadowPathAnimation.additive = YES;
            
            // 設(shè)置shadowAnimation的新值客们,未設(shè)置from,則from屬性將默認(rèn)為當(dāng)前shadowPath的狀態(tài)
            shadowPathAnimation.toValue = [UIBezierPath bezierPathWithRect:self.layer.bounds];
            
            // 將動畫添加至layer的渲染樹
            [self.layer addAnimation:shadowPathAnimation forKey:@"shadowPath"];
        }
        // 根據(jù)蘋果文檔指出的材诽,顯式動畫只會影響動畫效果底挫,而不會影響屬性的的值,所以這兩為了持久化shadowPath的改變需要進(jìn)行屬性跟新
        // 同時也處理了bounds非動畫改變的情況
        self.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.layer.bounds].CGPath;
    }
}

Demo

本文Demo地址為ShadowPathAnimationDemo

disableShadowPathAnimation.gif

可以看到當(dāng)關(guān)閉shadowPath動畫脸侥,也就是不執(zhí)行上述代碼的時候建邓,當(dāng)view的bounds改變以后shadowPath還為原來的值,并未跟隨bounds進(jìn)行改變睁枕。

enableShadowPathAnimation.gif

可以看到當(dāng)打開shadowPath動畫官边,也就是要執(zhí)行了上述代碼時沸手,當(dāng)view的bounds改變以后shadowPath能夠跟隨一起改變,而且動畫效果相同拒逮。


本文個人博客地址: http://wty.im/2016/09/26/let-shadow-path-animate-with-layer-bounds/
Github: https://github.com/wty21cn/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末罐氨,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子滩援,更是在濱河造成了極大的恐慌,老刑警劉巖塔嬉,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件玩徊,死亡現(xiàn)場離奇詭異,居然都是意外死亡谨究,警方通過查閱死者的電腦和手機(jī)恩袱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胶哲,“玉大人畔塔,你說我怎么就攤上這事⊙煊欤” “怎么了澈吨?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長寄摆。 經(jīng)常有香客問我谅辣,道長,這世上最難降的妖魔是什么婶恼? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任桑阶,我火速辦了婚禮,結(jié)果婚禮上勾邦,老公的妹妹穿的比我還像新娘蚣录。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布娃兽。 她就那樣靜靜地躺著案淋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪公壤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天椎椰,我揣著相機(jī)與錄音厦幅,去河邊找鬼。 笑死慨飘,一個胖子當(dāng)著我的面吹牛确憨,可吹牛的內(nèi)容都是我干的译荞。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼休弃,長吁一口氣:“原來是場噩夢啊……” “哼吞歼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起塔猾,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤篙骡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丈甸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糯俗,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年睦擂,在試婚紗的時候發(fā)現(xiàn)自己被綠了得湘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡顿仇,死狀恐怖淘正,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情臼闻,我是刑警寧澤鸿吆,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站些阅,受9級特大地震影響伞剑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜市埋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一黎泣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缤谎,春花似錦抒倚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至频敛,卻和暖如春项郊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背斟赚。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工着降, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拗军。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓任洞,卻偏偏與公主長得像蓄喇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子交掏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評論 2 351

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

  • 在iOS中隨處都可以看到絢麗的動畫效果妆偏,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺ios動畫全貌盅弛。在這里你可以看...
    每天刷兩次牙閱讀 8,471評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果钱骂,實(shí)現(xiàn)這些動畫的過程并不復(fù)雜,今天將帶大家一窺iOS動畫全貌挪鹏。在這里你可以看...
    F麥子閱讀 5,104評論 5 13
  • Core Animation其實(shí)是一個令人誤解的命名罐柳。你可能認(rèn)為它只是用來做動畫的,但實(shí)際上它是從一個叫做Laye...
    小貓仔閱讀 3,694評論 1 4
  • 轉(zhuǎn)載:http://www.cnblogs.com/jingdizhiwa/p/5601240.html 1.ge...
    F麥子閱讀 1,539評論 0 1
  • 轉(zhuǎn)載:http://www.reibang.com/p/32fcadd12108 每個UIView有一個伙伴稱為l...
    F麥子閱讀 6,170評論 0 13