iOS動畫之CAShapeLayer(一)提交動畫

checkButton1.gif

今天動畫的主要用CAShapeLayer和貝塞爾曲線做一個(gè)提交的動畫谭跨,也是沒有什么難度的

先簡單的介紹下CAShapeLayer

  1. CAShapeLayer繼承自CALayer,可使用CALayer的所有屬性
  2. CAShapeLayer需要和貝塞爾曲線配合使用才有意義让簿。
    Shape:形狀,貝塞爾曲線可以為其提供形狀检吆,而單獨(dú)使用CAShapeLayer是沒有任何意義的种玛。
  3. 使用CAShapeLayer與貝塞爾曲線可以實(shí)現(xiàn)不在view的DrawRect方法中畫出一些想要的圖形

關(guān)于CAShapeLayer和DrawRect的比較

DrawRect:DrawRect屬于CoreGraphic框架笑窜,占用CPU致燥,消耗性能大
CAShapeLayer:CAShapeLayer屬于CoreAnimation框架,通過GPU來渲染圖形怖侦,節(jié)省性能篡悟。動畫渲染直接提交給手機(jī)GPU,不消耗內(nèi)存

貝塞爾曲線與CAShapeLayer的關(guān)系

  1. CAShapeLayer中shape代表形狀的意思匾寝,所以需要形狀才能生效
  2. 貝塞爾曲線可以創(chuàng)建基于矢量的路徑
  3. 貝塞爾曲線給CAShapeLayer提供路徑搬葬,CAShapeLayer在提供的路徑中進(jìn)行渲染。路徑會閉環(huán)艳悔,所以繪制出了Shape
  4. 用于CAShapeLayer的貝塞爾曲線作為Path急凰,其path是一個(gè)首尾相接的閉環(huán)的曲線,即使該貝塞爾曲線不是一個(gè)閉環(huán)的曲線

以上文字來源于網(wǎng)絡(luò)猜年,哈哈

如果有同學(xué)對UIBezierPath不熟悉的請看這里

CAShapeLayer的介紹

上面的介紹也說了貝塞爾曲線給CAShapeLayer提供路徑抡锈,CAShapeLayer在提供的路徑中進(jìn)行渲染,把路徑用以形狀的形式展示出來乔外,CAShapeLayer最重要的屬性就是下面三個(gè):

 //動畫的路徑
@property(nullable) CGPathRef path;

//描述path路徑從哪里開始
@property CGFloat strokeStart;
//描述path路徑從哪里結(jié)束
@property CGFloat strokeEnd;
 這兩個(gè)值的范圍是[0,1]床三,

接下來我們先畫一個(gè)不會動的 對號 來學(xué)習(xí)一下 CAShapeLayer

UIBezierPath *bezierPath=[UIBezierPath bezierPath];
[bezierPath moveToPoint:CGPointMake(self.frame.size.width/4, self.frame.size.height/2)];
[bezierPath addLineToPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height/4*3)];
[bezierPath addLineToPoint:CGPointMake(self.frame.size.width/4*3, self.frame.size.height/3)];


CAShapeLayer *shape=[CAShapeLayer layer];


  shape.lineWidth=17;
  shape.fillColor=[UIColor clearColor].CGColor;
  shape.strokeColor=[UIColor colorWithRed:0.76f green:0.89f blue:0.89f alpha:1.00f].CGColor;
  shape.lineCap = kCALineCapRound;
  shape.lineJoin = kCALineJoinRound;

  shape.path=bezierPath.CGPath;
  [self.layer addSublayer:shape];

UIBezierPath只是告訴路徑給CAShapeLayer杨幼,具體這個(gè)shape什么樣子由CAShapeLayer來決定
所以一些屬于lineWidth撇簿,fillColor是在shape上設(shè)置的,在UIBezierPath上設(shè)置無效

補(bǔ)充:lineCap

  • kCALineCapButt: 默認(rèn)格式差购,不附加任何形狀;
  • kCALineCapRound: 在線段頭尾添加半徑為線段 lineWidth 一半的半圓四瘫;
  • kCALineCapSquare: 在線段頭尾添加半徑為線段 lineWidth 一半的矩形”
checkButton

CAShapeLayer的基本用法就是這樣接下來就是動畫了

動畫第一步長方形變圓形

先添加一個(gè)checkButton的cornerRadius變?yōu)閳A形的高度一半的動畫

注意
我們知道,使用 CAAnimation 如果不做額外的操作欲逃,動畫會在結(jié)束之后返回到初始狀態(tài)找蜜。或許你會這么設(shè)置:

radiusAnimation.fillMode = kCAFillModeForwards; radiusAnimation.removedOnCompletion = NO;

但這不是正確的方式稳析。正確的做法可以參考 WWDC 2011 中的 session 421 - Core Animation Essentials洗做。
Session 中推薦的做法是先顯式地改變 Model Layer 的對應(yīng)屬性,再應(yīng)用動畫迈着。這樣一來竭望,我們甚至省去了 toValue。
因?yàn)?cornerRadius 也是 Animatable 的裕菠,所以可以作為 KeyPath 進(jìn)行動畫咬清。首先顯式地設(shè)定屬性的終止?fàn)顟B(tài),為進(jìn)度條高度的 1/2 : ZMButtonSize().height/2. 設(shè)置好起始狀態(tài)奴潘。

static CGSize ZMButtonSize() {
return CGSizeMake(100, 100);
}
  • self.layer.cornerRadius=ZMButtonSize().height/2;
    CABasicAnimation *cornerRadiusAnimation=[CABasicAnimation animationWithKeyPath:@"cornerRadius"];
    cornerRadiusAnimation.delegate=self;
    cornerRadiusAnimation.duration=0.2;
    cornerRadiusAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    cornerRadiusAnimation.fromValue=@(self.frame.size.height/2);

    [self.layer addAnimation:cornerRadiusAnimation forKey:@"cornerRadiusAnimation"];

在Animation的代理方法里動畫一開始讓checkButton的bounds改變

-(void)animationDidStart:(CAAnimation *)anim
{

   if([[self.layer animationForKey:@"cornerRadiusAnimation"] isEqual:anim])
 {
    
    [UIView animateWithDuration:0.6f delay:0.0f usingSpringWithDamping:0.6 initialSpringVelocity:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        self.bounds = CGRectMake(0, 0, ZMButtonSize().height, ZMButtonSize().height);
        self.backgroundColor=[UIColor colorWithRed:1.00f green:0.80f blue:0.56f alpha:1.00f];
    } completion:^(BOOL finished) {
        [self.layer removeAllAnimations];
        
        [self checkAnimation];
        
    }];

 }

}

動畫第二步畫會動的對號

在checkButton的bounds改變完成是在checkButton上畫一個(gè)對號

這時(shí)候就用到了CAShapeLayer的 strokeStart, strokeEnd旧烧,在動畫時(shí)設(shè)置KeyPath:為"strokeEnd",從0到1,這樣一個(gè)動畫的對號就出來了画髓。

CAShapeLayer *shape=[CAShapeLayer layer];


UIBezierPath *bezierPath=[UIBezierPath bezierPath];
[bezierPath moveToPoint:CGPointMake(self.frame.size.width/4, self.frame.size.height/2)];
[bezierPath addLineToPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height/4*3)];
[bezierPath addLineToPoint:CGPointMake(self.frame.size.width/4*3, self.frame.size.height/3)];



//UIBezierPath只是告訴路徑給CAShapeLayer掘剪,具體這個(gè)shpe什么樣子由CAShapeLayer來決定
//所以一些屬于lineWidth,fillColor是在shpe上設(shè)置的奈虾,在UIBezierPath上設(shè)置無效

shape.lineWidth=17;
shape.fillColor=[UIColor clearColor].CGColor;
shape.strokeColor=[UIColor colorWithRed:0.76f green:0.89f blue:0.89f alpha:1.00f].CGColor;
shape.lineCap = kCALineCapRound;
shape.lineJoin = kCALineJoinRound;

shape.path=bezierPath.CGPath;
[self.layer addSublayer:shape];


CABasicAnimation *checkAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
checkAnimation.duration = 0.5f;
checkAnimation.fromValue = @(0.0f);
checkAnimation.toValue = @(1.0f);
checkAnimation.delegate = self;
[shape addAnimation:checkAnimation forKey:@"checkAnimation"];

理論上夺谁,所有描線的動畫你都可以用這種方式先指定一個(gè) path 然后改變 strokeEnd, strokeStart 來實(shí)現(xiàn)廉赔。

如果感覺這篇文章對您有所幫助,順手點(diǎn)個(gè)喜歡匾鸥,謝謝啦
代碼放在了GitHub上大家可以下載蜡塌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市勿负,隨后出現(xiàn)的幾起案子馏艾,更是在濱河造成了極大的恐慌,老刑警劉巖奴愉,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琅摩,死亡現(xiàn)場離奇詭異,居然都是意外死亡锭硼,警方通過查閱死者的電腦和手機(jī)房资,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來檀头,“玉大人志膀,你說我怎么就攤上這事”钋埽” “怎么了溉浙?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蒋荚。 經(jīng)常有香客問我戳稽,道長,這世上最難降的妖魔是什么期升? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任惊奇,我火速辦了婚禮,結(jié)果婚禮上播赁,老公的妹妹穿的比我還像新娘颂郎。我一直安慰自己,他們只是感情好容为,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布乓序。 她就那樣靜靜地躺著,像睡著了一般坎背。 火紅的嫁衣襯著肌膚如雪替劈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天得滤,我揣著相機(jī)與錄音陨献,去河邊找鬼。 笑死懂更,一個(gè)胖子當(dāng)著我的面吹牛眨业,可吹牛的內(nèi)容都是我干的急膀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼龄捡,長吁一口氣:“原來是場噩夢啊……” “哼脖阵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起墅茉,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呜呐,沒想到半個(gè)月后就斤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蘑辑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年洋机,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片洋魂。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡绷旗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出副砍,到底是詐尸還是另有隱情衔肢,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布豁翎,位于F島的核電站角骤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏心剥。R本人自食惡果不足惜邦尊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望优烧。 院中可真熱鬧蝉揍,春花似錦、人聲如沸畦娄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熙卡。三九已至捍掺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間再膳,已是汗流浹背挺勿。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喂柒,地道東北人不瓶。 一個(gè)月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓禾嫉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蚊丐。 傳聞我的和親對象是個(gè)殘疾皇子熙参,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

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