前言
QeartzCore是iOS中的圖層框架沛鸵,Quartz Core 的渲染能力可以像三維一樣對二維圖像進行任意操縱,在這個框架中我們可以對試圖的圖層進行定制,以實現(xiàn)我們想要的效果曲掰。
下面看一下這個框架中的類文件有哪些:
CALayer就是QeartzCore框架中的一個類疾捍,CALayer是個與UIView很類似的概念,同樣有backgroundColor栏妖、frame等相似的屬性乱豆,我們可以將UIView看做一種特殊的CALayer。但實際上UIView是對CALayer封裝吊趾,在CALayer的基礎上再添加交互功能宛裕。UIView的顯示必須依賴于CALayer。我們同樣可以跟新建view一樣新建一個layer论泛,然后添加到某個已有的layer上揩尸,同樣可以對layer調整大小、位置屁奏、透明度等岩榆。一般來說,layer可以有兩種用途:一是對view相關屬性的設置坟瓢,包括圓角勇边、陰影、邊框等參數(shù)载绿,更詳細的參數(shù)請點擊這里粥诫;二是實現(xiàn)對view的動畫操控。因此對一個view進行動畫崭庸,本質上是對該view的.layer進行動畫操縱怀浆。CALayer的設計主要是了為了內容展示和動畫操作,CALayer本身并不包含在UIKit中怕享,它不能響應事件执赡。
一個UIView上的圖層關系大概是這樣的:
CALayer常用的屬性
CALayer 最常用的兩個子類:
-
CAGradientLayer(用于顏色漸變的實現(xiàn))
// 創(chuàng)建 UIView 用來承載漸變色 UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 50, 200)]; [self.view addSubview:myView]; // 創(chuàng)建 CAGradientLayer 對象 CAGradientLayer *gradientLayer = [CAGradientLayer layer]; // 設置 gradientLayer 的 Frame gradientLayer.frame = myView.bounds; // 創(chuàng)建漸變色數(shù)組,需要轉換為CGColor顏色 gradientLayer.colors = @[(id)[UIColor redColor].CGColor, (id)[UIColor yellowColor].CGColor, (id)[UIColor blueColor].CGColor]; #// 設置三種顏色變化點函筋,取值范圍 0.0~1.0 gradientLayer.locations = @[@(0.1f) ,@(0.4f)]; #// 設置漸變顏色方向沙合,左上點為(0,0), 右下點為(1,1) gradientLayer.startPoint = CGPointMake(0, 0); gradientLayer.endPoint = CGPointMake(0, 1); // 添加漸變色到創(chuàng)建的 UIView 上去 [myView.layer addSublayer:gradientLayer];
其中:fillMode主要是決定顯示layer在動畫完成后的狀態(tài)..一般和removedOnCompletion一起使用..
如果fillmode是..kCAFillModeRemoved 或..kCAFillModeBackwards...
不管removedOnCompletion是yes還是no,都會回到原始狀態(tài)..一般用在重復的動畫里..比如圖片旋轉5圈..你做一圈的功能.然后重復5次..就行了..
kCAFillModeForwards 或 kCAFillModeBoth模式下...如果..removedOnCompletion 是yes,動畫完成后會回到原始狀態(tài)..removedOnCompletion是NO的話..動畫完成后會保持狀態(tài)..保持狀態(tài)只是保持可見層(presentation)的狀態(tài)...layer本身的狀態(tài)不會改變.
CAShapeLayer
CAShapeLayer顧名思義,繼承于CALayer跌帐。 每個CAShapeLayer對象都代表著將要被渲染到屏幕上的一個任意的形狀(shape)首懈。具體的形狀由其path(類型為CGPathRef)屬性指定。 普通的CALayer是矩形谨敛,所以需要frame屬性究履。CAShapeLayer初始化時也需要指定frame值(也可以不指定狂鞋,只要path路徑設置正確就行)贬墩,但它本身沒有形狀勇劣,它的形狀來源于其屬性path 炕置。CAShapeLayer有不同于CALayer的屬性硫戈,它從CALayer繼承而來的屬性在繪制時是不起作用的足陨。
在使用Core Animation開發(fā)動畫的本質就是將CALayer中的內容轉化為位圖從而供硬件操作琴拧。
CAShapeLayer有著幾點很重要:
- 它依附于一個給定的path,必須給與path,而且,即使path不完整也會自動首尾相接
- strokeStart以及strokeEnd代表著在這個path中首部蝌借、尾部所占整個路徑的百分比位置,strokeEnd 需要大于 strokeStart吟吝,控制這倆值的大小菱父,結合CABasicAnimation 即可實現(xiàn) CAShapeLayer的繪圖動畫。
- CAShapeLayer動畫僅僅限于沿著邊緣的動畫效果,它實現(xiàn)不了填充效果
我們可以使用CAShapeLayer與UIBezierPath可以實現(xiàn)不在view的drawRect方法中就畫出一些想要的圖形爸黄。大致步驟如下:
1滞伟、新建UIBezierPath對象bezierPath
2揭鳞、新建CAShapeLayer對象caShapeLayer
3炕贵、將bezierPath的CGPath賦值給caShapeLayer的path,即caShapeLayer.path = bezierPath.CGPath
4野崇、把caShapeLayer添加到某個顯示該圖形的layer中
#值得注意的是称开,CAShapeLayer 在初始化的時候可以不指定 Frame,其位置和形狀由UIBezierPath決定乓梨。
#比如末端是矩形還是圓形鳖轰,都是 UIBezierPath的設置,而且fillColor 也是 UIBezierPath區(qū)域內的顏色扶镀。LineWidth 是在邊界上繪制的寬度蕴侣,而且 繪制的寬度被邊界一分為二。
#如果LineWidth 為0 臭觉,strokeColor設置后也是沒有效果的昆雀。
這面這個例子就是使用 CAShapeLayer與UIBezierPath以及CABasicAnimation結合在一起,實現(xiàn)的動態(tài)畫圖蝠筑。
#核心實現(xiàn)代碼
//頭
CAShapeLayer *headLayer = [CAShapeLayer layer];
UIBezierPath *headPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(self.view.frame.size.width/2-80, 0, 160, 160) cornerRadius:80];
[self setLayer:headLayer path:headPath delay:delay*0];
- (void)setLayer:(CAShapeLayer *)layer path:(UIBezierPath *)path delay:(CFTimeInterval)delay
{
layer.path = path.CGPath;
layer.fillColor = [UIColor clearColor].CGColor;
layer.strokeColor = [UIColor lightGrayColor].CGColor;
__weak typeof(self) weakSelf = self;
# 由代碼可知狞膘,動畫的先后執(zhí)行時間順序是通過 dispatch_after 實現(xiàn)的。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf.displayView.layer addSublayer:layer];
[weakSelf addAnimation:layer duration:LanPangZiDuration];
});
}
- (void)addAnimation:(CAShapeLayer *)layer duration:(CFTimeInterval)duration
{
switch (_animationType) {
case AnimationTypeNone:
break;
case AnimationTypeOne:
[self addAnimationOneOnLayer:layer duration:duration];
break;
case AnimationTypeTwo:
[self addAnimationTwoOnLayer:layer duration:duration];
break;
case AnimationTypeThree:
[self addAnimationThreeOnLayer:layer duration:duration];
break;
default:
break;
}
}
#pragma mark - 利用layer的 strokeEnd什乙、strokeStart和lineWidth 屬性添加CA動畫
- (void)addAnimationOneOnLayer:(CAShapeLayer *)layer duration:(CFTimeInterval)duration
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
animation.fromValue = @(0);
animation.toValue = @(1);
animation.duration = duration;
[layer addAnimation:animation forKey:nil];
}
核心動畫
下面是核心動畫的幾個類:
下面我們從上圖的協(xié)議以及類的屬性入手挽封,分析一下上圖結構:
-
CAMediaTiming 協(xié)議中定義了時間,速度臣镣,重復次數(shù)等辅愿。
屬性定義如下: beginTime -> 用來設置動畫延時,若想延遲1秒忆某,就設置為CACurrentMediaTime()+1点待,其中CACurrentMediaTime()為圖層當前時間。 duration -> 動畫的持續(xù)時間褒繁。 speed -> 動畫速率亦鳞,決定動畫時間的倍率。當speed為2時,動畫時間為設置的duration的1/2燕差。 timeOffset -> 動畫時間偏移量遭笋。比如設置動畫時長為3秒,當設置timeOffset為1.5時徒探,當前動畫會從中間位置開始瓦呼,并在到達指定位置時,走完之前跳過的前半段動畫测暗。 repeatCount -> 動畫的重復次數(shù)央串。 repeatDuration -> 動畫的重復時間。 autoreverses -> 動畫由初始值到最終值后碗啄,是否反過來回到初始值的動畫质和。如果設置為YES,就意味著動畫完成后會以動畫的形式回到初始值稚字。 fillMode -> 決定當前對象在非動畫時間段的行為.比如動畫開始之前饲宿,動畫結束之后。 其實不只是CAAnimation遵循CAMediaTiming協(xié)議胆描,熟悉底層結構的小伙伴們應該知道CALayer也遵循這個協(xié)議瘫想,所有在一定程度上我們可以通過控制layer本身的協(xié)議屬性來控制動畫節(jié)奏。
-
CAAnimation 核心動畫基礎類昌讲,不能直接使用国夜。除了CAMediaTiming協(xié)議中的方法,增加了CAAnimationDelegate的代理屬性等短绸。
具體如下: timingFunction -> 控制動畫的節(jié)奏车吹。 系統(tǒng)提供的包括:kCAMediaTimingFunctionLinear (勻速), kCAMediaTimingFunctionEaseIn (慢進快出)鸠按, kCAMediaTimingFunctionEaseOut (快進慢出)礼搁, kCAMediaTimingFunctionEaseInEaseOut (慢進慢出,中間加速)目尖, kCAMediaTimingFunctionDefault (默認)馒吴, 當然也可通過自定義創(chuàng)建CAMediaTimingFunction。 delegate -> 代理瑟曲。 removedOnCompletion -> 是否讓圖層保持顯示動畫執(zhí)行后的狀態(tài)饮戳,默認為YES,也就是動畫執(zhí)行完畢后從涂層上移除洞拨,恢復到執(zhí)行前的狀態(tài)扯罐,如果設置為NO,并且設置fillMode為kCAFillModeForwards烦衣,則保持動畫執(zhí)行后的狀態(tài)歹河。
-
CATransition 轉場動畫掩浙,系統(tǒng)提供了很多酷炫效果。
屬性如下: type -> 轉場動畫類型秸歧。 subtype -> 轉場動畫方向厨姚。 startProgress -> 動畫起點進度(整體的百分比)。 endProgress -> 動畫終點進度(整體的百分比)键菱。 filter -> 自定義轉場谬墙。
-
CAAnimationGroup
顧名思義,這是一個動畫組,它允許多個動畫組合在一起并行顯示.比如這里設置了兩個動畫, 把他們加在動畫組里,一起顯示.例如你有幾個動畫,在動畫執(zhí)行的過程中需要同時修改動畫的某些屬性,這時候就可以使用CAAnimationGroup. duration 動畫持續(xù)時間,值得一提的是,如果添加到group里的子動畫不設置此屬性,group里的duration會統(tǒng)一設置動畫(包括子動畫)的duration屬性;但是如果子動畫設置了duration屬性,那么group的duration屬性的值不應該小于每個子動畫中duration屬性的值,否則會造成子動畫顯示不全就停止了動畫. autoreverses 動畫完成后自動重新開始,默認為NO. repeatCount 動畫重復次數(shù),默認為0. animations 動畫組(數(shù)組類型),把需要同時運行的動畫加到這個數(shù)組里. addAnimation:forKey 這個方法的forKey參數(shù)是一個字符串,這個字符串可以隨意設 如果你需要在動畫group執(zhí)行結束后保存動畫效果的話,設置 fillMode 屬性,并且把 removedOnCompletion 設置為NO;
-
CAPropertyAnimation 屬性動畫,針對對象的可動畫屬性進行效果的設置经备,不可直接使用拭抬。
添加屬性具體如下: keyPath -> CALayer的某個屬性名,并通過這個屬性的值進行修改侵蒙,達到相應的動畫效果造虎。 additive -> 屬性動畫是否以當前動畫效果為基礎,默認為NO蘑志。 cumulative -> 指定動畫是否為累加效果累奈,默認為NO贬派。 valueFunction -> 此屬性配合CALayer的transform屬性使用急但。
-
CAKeyframeAnimation 關鍵幀動畫,同樣通過keyPath對應屬性進行控制搞乏,但它可以通過values或者path進行多個階段的控制波桩。CAKeyframeAnimation是CApropertyAnimation的子類,跟CABasicAnimation的區(qū)別是:CABasicAnimation只能從一個數(shù)值(fromValue)變到另一個數(shù)值(toValue)请敦,而CAKeyframeAnimation會使用一個NSArray保存這些數(shù)值镐躲。
屬性如下: values -> 關鍵幀組成的數(shù)組,動畫會依次顯示其中的每一幀侍筛。 path -> 關鍵幀路徑萤皂,動畫進行的要素,優(yōu)先級比values高匣椰,但是只對CALayer的anchorPoint和position起作用裆熙。 keyTimes -> 每一幀對應的時間,如果不設置禽笑,則各關鍵幀平分設定時間入录。 timingFunctions -> 每一幀對應的動畫節(jié)奏。 calculationMode -> 動畫的計算模式佳镜,系統(tǒng)提供了對應的幾種模式僚稿。 tensionValues -> 動畫張力控制。 continuityValues -> 動畫連續(xù)性控制蟀伸。 biasValues -> 動畫偏差率控制蚀同。 rotationMode -> 動畫沿路徑旋轉方式缅刽,系統(tǒng)提供了兩種模式。
-
CABasicAnimation基礎動畫蠢络,通過keyPath對應屬性進行控制拷恨,需要設置fromValue以及toValue。 CABasicAnimation提供了最基礎的動畫屬性設置谢肾,是簡單的keyframe動畫性能腕侄。
CABasicAnimation可以看做是一種CAKeyframeAnimation的簡單動畫,因為它只有頭尾的關鍵幀(keyframe)芦疏。添加屬性如下: fromValue -> keyPath相應屬性的初始值冕杠。 toValue -> keyPath相應屬性的結束值。 byValue -> 在不設置toValue時酸茴, toValue = fromValue + byValue分预,也就是在當前的位置上增加多少。
關于核心動畫里面的時間暫停薪捍,繼續(xù)的問題可以看我另一篇文章:實踐-跑馬燈效果及實現(xiàn)過程解析
-
CASpringAnimation 帶有初始速度以及阻尼指數(shù)等物理參數(shù)的屬性動畫笼痹。我們可以把它看成在不絕對光滑的地面上,一個彈簧拴著別小球酪穿,那么我們可以這么理解他的屬性:
mass -> 小球質量凳干,影響慣性。 stiffness -> 彈簧的勁度系數(shù)被济。 damping -> 阻尼系數(shù)救赐,地面的摩擦力。 initialVelocity -> 初始速度只磷,相當于給小球一個初始速度(可正可負经磅,方向不同) settlingDuration -> 結算時間,根據(jù)上述參數(shù)計算出的預計時間钮追,相對于你設置的時間预厌,這個時間比較準確。
屬性解析:
- values:就是上述的NSArray對象元媚。里面的元素稱為”關鍵幀”(keyframe)轧叽。動畫對象會在指定的時間(duration)內,依次顯示values數(shù)組中的每一個關鍵幀
- path:可以設置一個CGPathRef\CGMutablePathRef,讓層跟著路徑移動惠毁。path只對CALayer的anchorPoint和position起作用犹芹。如果你設置了path,那么values將被忽略
- keyTimes:可以為對應的關鍵幀指定對應的時間點,其取值范圍為0到1.0,keyTimes中的每一個時間值都對應values中的每一幀.當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的
calculationMode:
const kCAAnimationLinear//線性鞠绰,默認
const kCAAnimationDiscrete//離散腰埂,無中間過程(沒有中間圓滑的過渡),但keyTimes設置的時間依舊生效蜈膨,物體跳躍地出現(xiàn)在各個關鍵幀上
const kCAAnimationPaced//平均屿笼,keyTimes跟timeFunctions失效
const kCAAnimationCubic//平均牺荠,同上
const kCAAnimationCubicPaced//平均,同上
便利構造函數(shù) animationWithKeyPath: KeyPath需要一個字符串類型的參數(shù),實際上是一個 鍵-值編碼協(xié)議的擴展,
參數(shù)必須是CALayer的某一項屬性,你的代碼會對應的去改變該屬性的效果 具體可以填寫什么請參考上面的URL,切勿亂填!
例如這里填寫的是 @"transform.rotation.z" 意思就是圍繞z軸旋轉,旋轉的單位是弧度.這個動畫的效果是把view旋轉到最小,再旋轉回來.你也可以填寫@"opacity" 去修改透明度...以此類推.修改layer的屬性,可以用這個類.
toValue 動畫結束的值.
CABasicAnimation自己只有三個屬性(都很重要)(其他屬性是繼承來的),分別為:
fromValue(開始值),
toValue(結束值),
byValue(偏移值), 這三個屬性最多只能同時設置兩個;
他們之間的關系如下:
如果同時設置了fromValue和toValue,那么動畫就會從fromValue過渡到toValue;
如果同時設置了fromValue和byValue,那么動畫就會從fromValue過渡到fromValue + byValue;
如果同時設置了byValue 和toValue,那么動畫就會從toValue - byValue過渡到toValue;
如果只設置了fromValue,那么動畫就會從fromValue過渡到當前的value;
如果只設置了toValue ,那么動畫就會從當前的value過渡到toValue;
如果只設置了byValue ,那么動畫就會從從當前的value過渡到當前value + byValue.
可以這么理解,當你設置了三個中的一個或多個,系統(tǒng)就會根據(jù)以上規(guī)則使用插值算法計算出一個時間差并同時開啟一個Timer.Timer的間隔也就是這個時間差,通過這個Timer去不停地刷新keyPath的值.而實際上,keyPath的值(layer的屬性)在動畫運行這一過程中,是沒有任何變化的,它只是調用了GPU去完成這些顯示效果而已. 在這個動畫里,是設置了要旋轉到的弧度,根據(jù)以上規(guī)則,動畫將會從它當前的弧度專旋轉到我設置的弧度.
duration 動畫持續(xù)時間
timingFunction 動畫起點和終點之間的插值計算,也就是說它決定了動畫運行的節(jié)奏,是快還是慢,還是先快后慢...
一些常用的animationWithKeyPath值的總結
#都是 CAShapeLayer 或者 CALayer 的屬性
strokeStart #一條Path的起始
strokeEnd #一條Path的終止的位置
transform.scale 比例轉化 @(0.8)
transform.scale.x 寬的比例 @(0.8)
transform.scale.y 高的比例 @(0.8)
transform.translation.x 往x軸方向移動
transform.translation.y 往y軸方向移動
transform.rotation.x 圍繞x軸旋轉 @(M_PI)
transform.rotation.y 圍繞y軸旋轉 @(M_PI)
transform.rotation.z 圍繞z軸旋轉 @(M_PI)
cornerRadius 圓角的設置 @(50)
backgroundColor 背景顏色的變化 (id)[UIColor purpleColor].CGColor
bounds 大小驴一,中心不變 [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
position 位置(中心點的改變) [NSValue valueWithCGPoint:CGPointMake(300, 300)];
contents 內容休雌,比如UIImageView的圖片 imageAnima.toValue = (id)[UIImage imageNamed:@"to"].CGImage;
opacity 透明度 @(0.7)
contentsRect.size.width 橫向拉伸縮放 @(0.4)最好是0~1之間的
其他很不錯的文章:
iOS動畫篇_CoreAnimation(超詳細解析核心動畫)
CoreAnimation編程指南
談談iOS Animation
原IOS開發(fā)UI篇--IOS動畫(Core Animation)總結
本文考慮到簡潔就不上代碼了,具體的代碼實現(xiàn)的效果可以到我GitHub去下載查看肝断,喜歡的話杈曲,請star 一下。