先附上文中的Demo逗嫡,需要的朋友可以下載看一下
先簡(jiǎn)單說(shuō)一下CALayer
-
iOS 的動(dòng)畫都是基于 CALayer 的喷好,每個(gè)UIView都對(duì)應(yīng)有一個(gè)CALayer累贤。
所以修改UIView的屬性所呈現(xiàn)的動(dòng)畫都是CALayer實(shí)現(xiàn)的遗遵。CALayer不能響應(yīng)事件痹屹。下圖是UIView和CALyer的關(guān)系
iOS中可以實(shí)現(xiàn)動(dòng)畫的方式老赤,有不對(duì)的地方敬請(qǐng)指正
- UIView動(dòng)畫
//Duration 動(dòng)畫持續(xù)時(shí)間
//animations 動(dòng)畫過(guò)程
[UIView animateWithDuration:<#(NSTimeInterval)#> animations:<#^(void)animations#>];
//block里是動(dòng)畫完成的回調(diào)
[UIView animateWithDuration:<#(NSTimeInterval)#> animations:<#^(void)animations#> completion:<#^(BOOL finished)completion#>];
//delay 等待時(shí)間
//options 動(dòng)畫類型
[UIView animateWithDuration:<#(NSTimeInterval)#> delay:<#(NSTimeInterval)#> options:<#(UIViewAnimationOptions)#> animations:<#^(void)animations#> completion:<#^(BOOL finished)completion#>];
//彈性動(dòng)畫
//damping:阻尼轮洋,范圍0-1,阻尼越接近于0抬旺,彈性效果越明顯
//velocity:彈性復(fù)位的速度
[UIView animateWithDuration:<#(NSTimeInterval)#> delay:<#(NSTimeInterval)#> usingSpringWithDamping:<#(CGFloat)#> initialSpringVelocity:<#(CGFloat)#> options:<#(UIViewAnimationOptions)#> animations:<#^(void)animations#> completion:<#^(BOOL finished)completion#>];
//關(guān)鍵幀動(dòng)畫
[UIView animateKeyframesWithDuration:<#(NSTimeInterval)#> delay:<#(NSTimeInterval)#> options:<#(UIViewKeyframeAnimationOptions)#> animations:<#^(void)animations#> completion:<#^(BOOL finished)completion#>];
-
CoreAnimation
核心動(dòng)畫
CAAnimation:核心動(dòng)畫的基礎(chǔ)類弊予,不能直接使用,負(fù)責(zé)動(dòng)畫運(yùn)行時(shí)間开财、速度的控制汉柒,本身實(shí)現(xiàn)了CAMediaTiming協(xié)議。
CAPropertyAnimation:屬性動(dòng)畫的基類(通過(guò)屬性進(jìn)行動(dòng)畫設(shè)置责鳍,注意是可動(dòng)畫屬性)碾褂,不能直接使用。
CAAnimationGroup:動(dòng)畫組历葛,動(dòng)畫組是一種組合模式設(shè)計(jì)正塌,可以通過(guò)動(dòng)畫組來(lái)進(jìn)行所有動(dòng)畫行為的統(tǒng)一控制嘀略,組中所有動(dòng)畫效果可以并發(fā)執(zhí)行。
CATransition:轉(zhuǎn)場(chǎng)動(dòng)畫乓诽,主要通過(guò)濾鏡進(jìn)行動(dòng)畫效果設(shè)置帜羊。
CABasicAnimation:基礎(chǔ)動(dòng)畫,通過(guò)屬性修改進(jìn)行動(dòng)畫參數(shù)控制鸠天,只有初始狀態(tài)和結(jié)束狀態(tài)讼育。
CAKeyframeAnimation:關(guān)鍵幀動(dòng)畫,同樣是通過(guò)屬性進(jìn)行動(dòng)畫參數(shù)控制稠集,但是同基礎(chǔ)動(dòng)畫不同的是它可以有多個(gè)狀態(tài)控制奶段。
基礎(chǔ)動(dòng)畫、關(guān)鍵幀動(dòng)畫都屬于屬性動(dòng)畫剥纷,就是通過(guò)修改屬性值產(chǎn)生動(dòng)畫效果忧饭,開(kāi)發(fā)人員只需要設(shè)置初始值和結(jié)束值,中間的過(guò)程動(dòng)畫(又叫“補(bǔ)間動(dòng)畫”)由系統(tǒng)自動(dòng)計(jì)算產(chǎn)生筷畦。和基礎(chǔ)動(dòng)畫不同的是關(guān)鍵幀動(dòng)畫可以設(shè)置多個(gè)屬性值词裤,每?jī)蓚€(gè)屬性中間的補(bǔ)間動(dòng)畫由系統(tǒng)自動(dòng)完成,因此從這個(gè)角度而言基礎(chǔ)動(dòng)畫又可以看成是有兩個(gè)關(guān)鍵幀的關(guān)鍵幀動(dòng)畫鳖宾。
- 下面利用CABasicAnimation實(shí)現(xiàn)一個(gè)簡(jiǎn)單的縮放動(dòng)畫
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.duration=.3;
scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
scaleAnimation.fromValue = @(1);
scaleAnimation.toValue = @(1.5);
scaleAnimation.fillMode = kCAFillModeForwards;
scaleAnimation.removedOnCompletion = NO;
[view.layer addAnimation:scaleAnimation forKey:@"transformscale"];
**注意點(diǎn)** 如果fillMode=kCAFillModeForwards和removedOnComletion=NO吼砂,那么在動(dòng)畫執(zhí)行完畢后,圖層會(huì)保持顯示動(dòng)畫執(zhí)行后的狀態(tài)鼎文。但在實(shí)質(zhì)上渔肩,圖層的屬性值還是動(dòng)畫執(zhí)行前的初始值,并沒(méi)有真正被改變拇惋。
- CAKeyframeAnimation用法和CABasicAnimation類似周偎,多了一個(gè)values屬性
- CAAnimationGroup動(dòng)畫組可以把基礎(chǔ)動(dòng)畫和關(guān)鍵幀動(dòng)畫加入進(jìn)animations屬性
在實(shí)際項(xiàng)目中很多需求使用UIView動(dòng)畫或者基本動(dòng)畫就可以實(shí)現(xiàn),比如下面比較常用的縮放和彈性動(dòng)畫效果
炫酷的動(dòng)畫
如果想實(shí)現(xiàn)更炫酷一點(diǎn)的動(dòng)畫撑帖,如雷達(dá)蓉坎,波紋,咻一咻效果胡嘿,時(shí)鐘蛉艾,帶動(dòng)畫的指示器等就需要用到UIBezierPath和CAShapeLayer,CAReplicatorLayer等知識(shí)。
下面簡(jiǎn)單的說(shuō)一下CAShapeLayer和CAReplicatorLayer
CAShapeLayer
普通CALayer在被初始化時(shí)是需要給一個(gè)frame值的,這個(gè)frame值一般都與給定view的bounds值一致,它本身是有形狀的,而且是矩形. CAShapeLayer在初始化時(shí)也需要給一個(gè)frame值,但是,它本身沒(méi)有形狀,它的形狀來(lái)源于你給定的一個(gè)path,然后它去取CGPath值,它與CALayer有著很大的區(qū)別
CAShapeLayer有著幾點(diǎn)很重要:
1. 它依附于一個(gè)給定的path,必須給與path,而且,即使path不完整也會(huì)自動(dòng)首尾相接
2. strokeStart以及strokeEnd代表著在這個(gè)path中所占用的百分比
3. CAShapeLayer動(dòng)畫僅僅限于沿著邊緣的動(dòng)畫效果,它實(shí)現(xiàn)不了填充效果
// **創(chuàng)建一個(gè)shapeLayer**
CAShapeLayer *layer = [CAShapeLayer layer];
layer.frame = showView.bounds; // 與showView的frame一致
layer.strokeColor = [UIColor greenColor].CGColor; // 邊緣線的顏色
layer.fillColor = [UIColor clearColor].CGColor; // 閉環(huán)填充的顏色
layer.lineCap = kCALineCapSquare; // 邊緣線的類型
layer.path = path.CGPath; // 從貝塞爾曲線獲取到形狀
layer.lineWidth = 4.0f; // 線條寬度
layer.strokeStart = 0.0f;
layer.strokeEnd = 0.1f;
// **將layer添加進(jìn)圖層**
[showView.layer addSublayer:layer];
- CAReplicatorLayer
CAReplicatorLayer可以復(fù)制自己子層的layer,并且復(fù)制的出來(lái)的layer和原來(lái)的子layer擁有相同的動(dòng)效
貝塞爾曲線UIBezierPath
UIBezierPath主要是用來(lái)繪制路徑的衷敌,分為一階勿侯、二階.....n階。一階是直線缴罗,二階以上才是曲線助琐。而最終路徑的顯示還是得依靠CALayer
初始化方法一共7種
//方法1:構(gòu)造bezierPath對(duì)象,一般用于自定義路徑面氓。
[UIBezierPath bezierPath];
//方法2:根據(jù)某個(gè)CGRect繪制路徑兵钮。
[UIBezierPath bezierPathWithRect:<#(CGRect)#>];
//方法3:根據(jù)某個(gè)CGRect繪制內(nèi)切圓或橢圓(CGRect是正方形即為圓沟堡,為長(zhǎng)方形則為橢圓)。
[UIBezierPath bezierPathWithOvalInRect:<#(CGRect)#>];
//方法4:根據(jù)某個(gè)路徑繪制路徑矢空。
[UIBezierPath bezierPathWithCGPath:<#(nonnull CGPathRef)#>];
//方法5:繪制每個(gè)角都是圓角的矩形航罗,參數(shù)2是半徑。
[UIBezierPath bezierPathWithRoundedRect:<#(CGRect)#> cornerRadius:<#(CGFloat)#>];
//方法6:繪制帶圓角的矩形路徑屁药,參數(shù)2哪個(gè)角粥血,參數(shù)3,橫酿箭、縱向半徑复亏。
[UIBezierPath bezierPathWithRoundedRect:<#(CGRect)#> byRoundingCorners:<#(UIRectCorner)#> cornerRadii:<#(CGSize)#>];
//方法7:繪制圓弧路徑,參數(shù)1是中心點(diǎn)位置缭嫡,參數(shù)2是半徑缔御,參數(shù)3是開(kāi)始的弧度值,參數(shù)4是結(jié)束的弧度值妇蛀,參數(shù)5是是否順時(shí)針(YES是順時(shí)針?lè)较蚋唬琋O逆時(shí)針)。
[UIBezierPath bezierPathWithArcCenter:<#(CGPoint)#> radius:<#(CGFloat)#> startAngle:<#(CGFloat)#> endAngle:<#(CGFloat)#> clockwise:<#(BOOL)#>];
```
自定義路徑常用api
- (void)moveToPoint:(CGPoint)point; // 移到某個(gè)點(diǎn)
- (void)addLineToPoint:(CGPoint)point; // 繪制直線
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2; //繪制貝塞爾曲線
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint; // 繪制規(guī)則的貝塞爾曲線
- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise
// 繪制圓形曲線
- (void)appendPath:(UIBezierPath *)bezierPath; // 拼接曲線
---
![AnimationdemoGif2.gif](http://upload-images.jianshu.io/upload_images/292993-199ead8881b0c3e1.gif?imageMogr2/auto-orient/strip)
* 實(shí)現(xiàn)代碼
//波紋评架,咻一咻眷茁,雷達(dá)效果
-
(void)setup
{
_testView=[[UIView alloc] initWithFrame:CGRectMake(30, 300, 100, 100)];
[self.view addSubview:_testView];_testView.layer.backgroundColor = [UIColor clearColor].CGColor;
CAShapeLayer *pulseLayer = [CAShapeLayer layer];
pulseLayer.frame = _testView.layer.bounds;
pulseLayer.path = [UIBezierPath bezierPathWithOvalInRect:pulseLayer.bounds].CGPath;
pulseLayer.fillColor = [UIColor redColor].CGColor;//填充色
pulseLayer.opacity = 0.0;CAReplicatorLayer *replicatorLayer = [CAReplicatorLayer layer];
replicatorLayer.frame = _testView.bounds;
replicatorLayer.instanceCount = 4;//創(chuàng)建副本的數(shù)量,包括源對(duì)象。
replicatorLayer.instanceDelay = 1;//復(fù)制副本之間的延遲
[replicatorLayer addSublayer:pulseLayer];
[_testView.layer addSublayer:replicatorLayer];CABasicAnimation *opacityAnima = [CABasicAnimation animationWithKeyPath:@"opacity"];
opacityAnima.fromValue = @(0.3);
opacityAnima.toValue = @(0.0);CABasicAnimation *scaleAnima = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleAnima.fromValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 0.0, 0.0, 0.0)];
scaleAnima.toValue = [NSValue valueWithCATransform3D:CATransform3DScale(CATransform3DIdentity, 1.0, 1.0, 0.0)];CAAnimationGroup *groupAnima = [CAAnimationGroup animation];
groupAnima.animations = @[opacityAnima, scaleAnima];
groupAnima.duration = 4.0;
groupAnima.autoreverses = NO;
groupAnima.repeatCount = HUGE;
[pulseLayer addAnimation:groupAnima forKey:@"groupAnimation"];
}
//利用UIBezierPath和CAShapeLayer實(shí)現(xiàn)不規(guī)則的圖形纵诞,并帶有動(dòng)畫效果上祈,可以在折線圖中使用
-(void)myTest{
UIView *line=[[UIView alloc] initWithFrame:CGRectMake(0, 100, 400, 1)];
line.backgroundColor=[UIColor grayColor];
[self.view addSubview:line];
_testView1=[[UIImageView alloc] initWithFrame:CGRectMake(0, 100, 300, 200)];
_testView1.userInteractionEnabled=YES;
[self.view addSubview:_testView1];
//貝塞爾曲線,以下是4個(gè)角的位置,相對(duì)于_testView1
CGPoint point1= CGPointMake(10, 80);
CGPoint point2= CGPointMake(10, 200);
CGPoint point3= CGPointMake(300, 200);
CGPoint point4= CGPointMake(300, 80);
_path=[UIBezierPath bezierPath];
[_path moveToPoint:point1];//移動(dòng)到某個(gè)點(diǎn)浙芙,也就是起始點(diǎn)
[_path addLineToPoint:point2];
[_path addLineToPoint:point3];
[_path addLineToPoint:point4];
[_path addQuadCurveToPoint:point1 controlPoint:CGPointMake(150, -30)];
CAShapeLayer *shapeLayer=[CAShapeLayer layer];
shapeLayer.path=_path.CGPath;
shapeLayer.fillColor=[UIColor clearColor].CGColor;//填充顏色
shapeLayer.strokeColor=[UIColor orangeColor].CGColor;//邊框顏色
[_testView1.layer addSublayer:shapeLayer];
//動(dòng)畫
CABasicAnimation *pathAniamtion = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
pathAniamtion.duration = 3;
pathAniamtion.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
pathAniamtion.fromValue = [NSNumber numberWithFloat:0.0f];
pathAniamtion.toValue = [NSNumber numberWithFloat:1.0];
pathAniamtion.autoreverses = NO;
[shapeLayer addAnimation:pathAniamtion forKey:nil];
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickk:)];
[_testView1 addGestureRecognizer:tap];
}
-(void)clickk:(UITapGestureRecognizer *)tap{
CGPoint point=[tap locationInView:_testView1];
if ([_path containsPoint:point]) {
NSLog(@"點(diǎn)擊不規(guī)則圖形");
}
}
---
**補(bǔ)充一--基本動(dòng)畫設(shè)置參數(shù)**
在動(dòng)畫方法中有一個(gè)option參數(shù)登刺,UIViewAnimationOptions類型,它是一個(gè)枚舉類型嗡呼,動(dòng)畫參數(shù)分為三類纸俭,可以組合使用:
1.常規(guī)動(dòng)畫屬性設(shè)置(可以同時(shí)選擇多個(gè)進(jìn)行設(shè)置)
`UIViewAnimationOptionLayoutSubviews:動(dòng)畫過(guò)程中保證子視圖跟隨運(yùn)動(dòng)。
UIViewAnimationOptionAllowUserInteraction:動(dòng)畫過(guò)程中允許用戶交互晤锥。
UIViewAnimationOptionBeginFromCurrentState:所有視圖從當(dāng)前狀態(tài)開(kāi)始運(yùn)行掉蔬。
UIViewAnimationOptionRepeat:重復(fù)運(yùn)行動(dòng)畫。
UIViewAnimationOptionAutoreverse :動(dòng)畫運(yùn)行到結(jié)束點(diǎn)后仍然以動(dòng)畫方式回到初始點(diǎn)矾瘾。
UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套動(dòng)畫時(shí)間設(shè)置。
UIViewAnimationOptionOverrideInheritedCurve:忽略嵌套動(dòng)畫速度設(shè)置箭启。
UIViewAnimationOptionAllowAnimatedContent:動(dòng)畫過(guò)程中重繪視圖(注意僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫)壕翩。
UIViewAnimationOptionShowHideTransitionViews:視圖切換時(shí)直接隱藏舊視圖、顯示新視圖傅寡,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫)UIViewAnimationOptionOverrideInheritedOptions :不繼承父動(dòng)畫設(shè)置或動(dòng)畫類型放妈。`
2.動(dòng)畫速度控制(可從其中選擇一個(gè)設(shè)置)
`UIViewAnimationOptionCurveEaseInOut:動(dòng)畫先緩慢北救,然后逐漸加速。
UIViewAnimationOptionCurveEaseIn :動(dòng)畫逐漸變慢芜抒。
UIViewAnimationOptionCurveEaseOut:動(dòng)畫逐漸加速珍策。
UIViewAnimationOptionCurveLinear :動(dòng)畫勻速執(zhí)行,默認(rèn)值宅倒。`
3.轉(zhuǎn)場(chǎng)類型(僅適用于轉(zhuǎn)場(chǎng)動(dòng)畫設(shè)置攘宙,可以從中選擇一個(gè)進(jìn)行設(shè)置,基本動(dòng)畫拐迁、關(guān)鍵幀動(dòng)畫不需要設(shè)置)
`
UIViewAnimationOptionTransitionNone:沒(méi)有轉(zhuǎn)場(chǎng)動(dòng)畫效果蹭劈。
UIViewAnimationOptionTransitionFlipFromLeft :從左側(cè)翻轉(zhuǎn)效果。
UIViewAnimationOptionTransitionFlipFromRight:從右側(cè)翻轉(zhuǎn)效果线召。
UIViewAnimationOptionTransitionCurlUp:向后翻頁(yè)的動(dòng)畫過(guò)渡效果铺韧。
UIViewAnimationOptionTransitionCurlDown :向前翻頁(yè)的動(dòng)畫過(guò)渡效果。
UIViewAnimationOptionTransitionCrossDissolve:舊視圖溶解消失顯示下一個(gè)新視圖的效果缓淹。
UIViewAnimationOptionTransitionFlipFromTop :從上方翻轉(zhuǎn)效果哈打。
UIViewAnimationOptionTransitionFlipFromBottom:從底部翻轉(zhuǎn)效果。`
---
**補(bǔ)充二--keyPath**
layer有很多屬性讯壶,通過(guò)animationWithKeyPath修改前酿,列舉一下常用的屬性:
![](http://upload-images.jianshu.io/upload_images/292993-81c5817606549368.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
那么怎么知道這些屬性都有哪些呢。
1.[apple官方文檔](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html)
2.通過(guò)runtime
3.多看大神博客鹏溯,注意收集
####[附上以上動(dòng)畫的Demo罢维,需要的朋友可以下載看一下](https://github.com/xinge1/LXAnimationDemo)
---
推薦幾篇關(guān)于動(dòng)畫的博客
* [iOS開(kāi)發(fā)系列--讓你的應(yīng)用“動(dòng)”起來(lái)](http://www.cnblogs.com/kenshincui/p/3972100.html#overview)
* [放肆的使用UIBezierPath和CAShapeLayer畫各種圖形](http://www.reibang.com/p/c5cbb5e05075)
* [iOS動(dòng)畫(補(bǔ)充)--特殊Layer動(dòng)畫](http://www.reibang.com/p/4b6d60755dd3)
---