CALayer 圖層和context
圖層是用來裝載顯示內(nèi)容的容器,而context就是要顯示的內(nèi)容崎逃。
一個(gè)view有一個(gè)根layer台丛,只有它的子layer的屬性改變才有隱式動(dòng)畫效果善榛。
CGContextSaveGState及CGContextRestoreGState
使用Quartz時(shí)涉及到一個(gè)圖形上下文,其中圖形上下文中包含一個(gè)保存過的圖形狀態(tài)堆棧苹熏。在Quartz創(chuàng)建圖形上下文時(shí)碟贾,該堆棧是空的。CGContextSaveGState函數(shù)的作用是將當(dāng)前圖形狀態(tài)推入堆棧轨域。之后袱耽,您對(duì)圖形狀態(tài)所做的修改會(huì)影響隨后的描畫操作,但不影響存儲(chǔ)在堆棧中的拷貝干发。在修改完成后朱巨,您可以通過CGContextRestoreGState函數(shù)把堆棧頂部的狀態(tài)彈出,返回到之前的圖形狀態(tài)枉长。這種推入和彈出的方式是回到之前圖形狀態(tài)的快速方法冀续,避免逐個(gè)撤消所有的狀態(tài)修改;這也是將某些狀態(tài)(比如裁剪路徑)恢復(fù)到原有設(shè)置的唯一方式必峰。
使用自定義圖層繪圖
1. 自定義一個(gè)CALayer類洪唐,重寫drawInContext:(CGContextRef)ctx
2. 在UIview中把這個(gè)layer加到view的根layer上。并調(diào)用[layer setNeedsDisplay];
drawRect: 和drawLayer: 這兩個(gè)方法比較
1. 這兩個(gè)方法都是UIview的方法吼蚁,且都是拿到context凭需,對(duì)其進(jìn)行修改。
2. 前者是當(dāng)view 調(diào)用setNeedsDisplay時(shí)觸發(fā)的肝匆。而后者是首先layer的代理重寫drawLayer粒蜈,然后只要[layer setNeedsDisplay ]則drawLayer 就會(huì)被觸發(fā)。
3.如果一個(gè)view有多個(gè)圖層术唬,當(dāng)[view setNeedsDisplay]會(huì)調(diào)用drawRect: inContext薪伏;也就是說view會(huì)分別去取每一個(gè)layer的context然后繪制到相應(yīng)的layer上滚澜。
基礎(chǔ)動(dòng)畫
1.創(chuàng)建并初始化basicAnimation動(dòng)畫粗仓,然后設(shè)置動(dòng)畫屬性
2.設(shè)置動(dòng)畫屬性初始值(可以省略)、結(jié)束值以及其他動(dòng)畫屬性
3.將動(dòng)畫添加到圖層
利用事務(wù)關(guān)閉子圖層的隱式動(dòng)畫
說明:我們知道在對(duì)子圖層的屬性設(shè)置時(shí),產(chǎn)生的動(dòng)畫是隱式動(dòng)畫借浊。有時(shí)在動(dòng)畫結(jié)束以后我又改變了圖層的屬性塘淑,但是這時(shí)改變屬性我不要這個(gè)隱式動(dòng)畫,那么就用事務(wù)來關(guān)閉它蚂斤。
//開啟事務(wù)
[CATransaction?begin];
//禁用隱式動(dòng)畫
[CATransaction?setDisableActions:YES];
_layer.position=[[anim?valueForKey:@"KCBasicAnimationLocation"]?CGPointValue];
//提交事務(wù)
[CATransaction?commit];
動(dòng)畫的暫停和恢復(fù)
#pragma mark 動(dòng)畫暫停
-(void)animationPause{
//取得指定圖層動(dòng)畫的媒體時(shí)間存捺,后面參數(shù)用于指定子圖層,這里不需要
CFTimeInterval?interval=[_layer?convertTime:CACurrentMediaTime()?fromLayer:nil];
//設(shè)置時(shí)間偏移量曙蒸,保證暫停時(shí)停留在旋轉(zhuǎn)的位置
[_layer?setTimeOffset:interval];
//速度設(shè)置為0捌治,暫停動(dòng)畫
_layer.speed=0;
}
#pragma?mark?動(dòng)畫恢復(fù)
-(void)animationResume{
//獲得暫停的時(shí)間
CFTimeInterval?beginTime=?CACurrentMediaTime()-?_layer.timeOffset;
//設(shè)置偏移量
_layer.timeOffset=0;
//設(shè)置開始時(shí)間
_layer.beginTime=beginTime;
//設(shè)置動(dòng)畫速度,開始運(yùn)動(dòng)
_layer.speed=1.0;
}
注意:
動(dòng)畫暫停針對(duì)的是圖層而不是圖層中的某個(gè)動(dòng)畫纽窟。
要做無限循環(huán)的動(dòng)畫肖油,動(dòng)畫的removedOnCompletion屬性必須設(shè)置為NO,否則運(yùn)行一次動(dòng)畫就會(huì)銷毀臂港。
關(guān)鍵幀動(dòng)畫
1. 通過設(shè)置不同的屬性值進(jìn)行關(guān)鍵幀控制
2. 通過繪制路徑進(jìn)行關(guān)鍵幀控制森枪。
后者優(yōu)先級(jí)高于前者,如果設(shè)置了路徑則屬性值就不再起作用审孽。
具體請(qǐng)看本文結(jié)尾的文章推薦县袱。
組動(dòng)畫:略
轉(zhuǎn)場(chǎng)動(dòng)畫
利用轉(zhuǎn)場(chǎng)動(dòng)畫,只用一個(gè)UIImageView就能實(shí)現(xiàn)無限滾動(dòng)佑力。見文章底部的推薦式散。
逐幀動(dòng)畫
利用CADisplayLink,重復(fù)往layer.content 里面添加圖片打颤。
CADisplayLink是一個(gè)計(jì)時(shí)器杂数,但是同NSTimer不同的是,CADisplayLink的刷新周期同屏幕完全一致瘸洛。例如在iOS中屏幕刷新周期是60次/秒揍移,CADisplayLink刷新周期同屏幕刷新一致也是60次/秒,這樣一來使用它完成的逐幀動(dòng)畫(又稱為“時(shí)鐘動(dòng)畫”)完全感覺不到動(dòng)畫的停滯情況反肋。
UIView動(dòng)畫封裝
[UIView animateWithDuration:5.0 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
? ? ? ? _imageView.center=location;
? ? } completion:^(BOOL finished) {
? ? ? ? NSLog(@"Animation end.");
? }];
//開始動(dòng)畫[UIView?commitAnimations];
感謝:iOS開發(fā)之讓你的應(yīng)用“動(dòng)”起來 - CocoaChina 蘋果開發(fā)中文站?
CADisplayLink是一個(gè)計(jì)時(shí)器那伐,但是同NSTimer不同的是,CADisplayLink的刷新周期同屏幕完全一致石蔗。例如在iOS中屏幕刷新周期是60次/秒罕邀,CADisplayLink刷新周期同屏幕刷新一致也是60次/秒,這樣一來使用它完成的逐幀動(dòng)畫(又稱為“時(shí)鐘動(dòng)畫”)完全感覺不到動(dòng)畫的停滯情況养距。
UIView動(dòng)畫封裝