CABasicAnimation動(dòng)畫和keypath說明

一、簡介

  • CABasicAnimation是CAPropertyAnimation的子類, CAPropertyAnimation有一個(gè)字符串類型的keyPath屬性
結(jié)構(gòu)圖-1
  • keyPath內(nèi)容是CALayer的可動(dòng)畫Animatable屬性,可動(dòng)畫屬性可見CAlayer篇

  • 我們可以指定CALayer的某個(gè)屬性名為keyPath,并且對(duì)CALayer的這個(gè)屬性的值進(jìn)行修改,達(dá)到相應(yīng)的動(dòng)畫效果。

  • 例如:指定keyPath = @"position",就會(huì)修改CALayer的position屬性的值,- > 可以實(shí)現(xiàn)平移的動(dòng)畫效果

  • 屬性說明: fromValue:keyPath相應(yīng)屬性的初始值,toValue:keyPath相應(yīng)屬性的結(jié)束值

  • 因此,初始化好CAPropertyAnimation的子類對(duì)象后,必須先設(shè)置keyPath(修改的是CALayer的哪個(gè)屬性)-> 指明執(zhí)行的是怎樣的動(dòng)畫(平移/縮放/旋轉(zhuǎn)等)

  • 隨著動(dòng)畫的進(jìn)行,在長度為 duration的持續(xù)時(shí)間內(nèi),keyPath相應(yīng)屬性的值從fromValue漸漸地變?yōu)?code>toValue

  • keyPath內(nèi)容是CALayer的可動(dòng)畫Animatable屬性

  • 如果fillMode=kCAFillModeForwards同時(shí)removedOnComletion=NO,那么在動(dòng)畫執(zhí)行完畢后,圖層會(huì)保持顯示動(dòng)畫執(zhí)行后的狀態(tài)。但在實(shí)質(zhì)上,圖層的屬性值還是動(dòng)畫執(zhí)行前的初始值,并沒有真正被改變。

屬性說明:

  • duration
    動(dòng)畫時(shí)長

  • fromValue
    動(dòng)畫起始的位置,根據(jù)keyPath的值不一樣,這里的值也不一樣;比如keyPath是position的時(shí)候,fromValue的值就是[NSValue valueWithCGPoint:<#(CGPoint)#>];

  • toValue
    動(dòng)畫結(jié)束位置,和fromValue的值一致

  • repeatCount
    動(dòng)畫執(zhí)行次數(shù)

  • Autoreverses
    當(dāng)你設(shè)定這個(gè)屬性為 YES 時(shí),在它到達(dá)目的地之后,動(dòng)畫的返回到開始的值,代替了直接跳轉(zhuǎn)到 開始的值。

  • removedOnCompletion
    這個(gè)是在動(dòng)畫結(jié)束后,是否會(huì)回到開始的值,默認(rèn)是YES。如果設(shè)置為NO,則動(dòng)畫結(jié)束后,會(huì)保持動(dòng)畫結(jié)束后的形態(tài),但layer的相關(guān)屬性值并沒有改變

  • Duration
    Duration 這個(gè)參數(shù)你已經(jīng)相當(dāng)熟悉了。它設(shè)定開始值到結(jié)束值花費(fèi)的時(shí)間。期間會(huì)被速度的屬性所影響。 RemovedOnCompletion 這個(gè)屬性默認(rèn)為 YES,那意味著,在指定的時(shí)間段完成后,動(dòng)畫就自動(dòng)的從層上移除了。這個(gè)一般不用。

假如你想要再次用這個(gè)動(dòng)畫時(shí),你需要設(shè)定這個(gè)屬性為 NO。這樣的話,下次你在通過-set 方法設(shè)定動(dòng)畫的屬 性時(shí),它將再次使用你的動(dòng)畫,而非默認(rèn)的動(dòng)畫。

  • Speed
    默認(rèn)的值為 1.0.這意味著動(dòng)畫播放按照默認(rèn)的速度。如果你改變這個(gè)值為 2.0,動(dòng)畫會(huì)用 2 倍的速度播放。 這樣的影響就是使持續(xù)時(shí)間減半。如果你指定的持續(xù)時(shí)間為 6 秒,速度為 2.0,動(dòng)畫就會(huì)播放 3 秒鐘---一半的 持續(xù)時(shí)間。

  • BeginTime
    這個(gè)屬性在組動(dòng)畫中很有用。它根據(jù)父動(dòng)畫組的持續(xù)時(shí)間,指定了開始播放動(dòng)畫的時(shí)間。默認(rèn)的是 0.0.組 動(dòng)畫在下個(gè)段落中討論“Animation Grouping”。

  • TimeOffset
    如果一個(gè)時(shí)間偏移量是被設(shè)定,動(dòng)畫不會(huì)真正的可見,直到根據(jù)父動(dòng)畫組中的執(zhí)行時(shí)間得到的時(shí)間都流逝 了。

  • RepeatCount
    默認(rèn)的是 0,意味著動(dòng)畫只會(huì)播放一次。如果指定一個(gè)無限大的重復(fù)次數(shù),使用 1e100f。這個(gè)不應(yīng)該和 repeatDration 屬性一塊使用。

  • RepeatDuration
    這個(gè)屬性指定了動(dòng)畫應(yīng)該被重復(fù)多久。動(dòng)畫會(huì)一直重復(fù),直到設(shè)定的時(shí)間流逝完。它不應(yīng)該和 repeatCount 一起使用。

keyPath屬性說明:

transform.scale = 比例轉(zhuǎn)換
transform.rotation = 旋轉(zhuǎn)
transform.rotation.x = x軸旋轉(zhuǎn)
transform.rotation.y = y軸旋轉(zhuǎn)

opacity = 透明度
margin = 邊距
position = 位移
backgroundColor = 背景顏色
cornerRadius = 圓角
borderWidth = 邊框?qū)挾?br> bounds = 位置,體積
contents = 內(nèi)容
contentsRect = 面積
frame = 位置,體積
hidden = 是否隱藏

shadowColor = 陰影顏色
shadowOffset = 陰影偏移
shadowOpacity = 陰影透明

shadowRadius = 陰影半徑

CABasicAnimation應(yīng)用:

直線進(jìn)度條:

/*直線進(jìn)度條*/
- (CAShapeLayer *)lineAnimationLayer
{
    if(!_lineAnimationLayer){
        _lineAnimationLayer = [CAShapeLayer layer];
        _lineAnimationLayer.strokeColor = [UIColor greenColor].CGColor;
        _lineAnimationLayer.lineWidth = 5;
//        設(shè)置路徑
        UIBezierPath * path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(50, 200)];
        [path addLineToPoint:CGPointMake(300, 200)];
        _lineAnimationLayer.path = path.CGPath;
        /*動(dòng)畫,keyPath是系統(tǒng)定的關(guān)鍵詞,可以自己去幫助文檔里面查看*/
        CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
//        animation的動(dòng)畫時(shí)長
        animation.duration = 4.0;
//        動(dòng)畫的其實(shí)位置
        animation.fromValue = @(0);
//        動(dòng)畫的結(jié)束位置
        animation.toValue = @(1);
//        動(dòng)畫執(zhí)行次數(shù)
        animation.repeatCount = MAXFLOAT;
//        添加動(dòng)畫并設(shè)置key;這個(gè)key值是自己定義的
        [_lineAnimationLayer addAnimation:animation forKey:@"lineAnimationLayer"];
    
    }
    return _lineAnimationLayer;
}

執(zhí)行結(jié)果:

進(jìn)度條.gif

邊框環(huán)繞效果

實(shí)現(xiàn)代碼:

/**
 * 跑馬燈二(shaperLayer)
 */
-(void)marquee2{
    //創(chuàng)建一個(gè)shaperLayer
    CAShapeLayer *shaperLayer = [CAShapeLayer layer];
    shaperLayer.bounds = CGRectMake(0, 0, 10, 5);
    shaperLayer.position = CGPointMake((kWidth-300)/2, (kHeight-200)/2);
    shaperLayer.strokeColor = [UIColor whiteColor].CGColor;
    shaperLayer.fillColor = [UIColor clearColor].CGColor;
    shaperLayer.lineDashPattern = @[@(10),@(10)];
//    虛線結(jié)尾處的類型
    shaperLayer.lineCap = kCALineCapRound;
//    拐角處layer的類型
    shaperLayer.lineJoin = kCALineJoinRound;
    shaperLayer.lineWidth = 5;
    
    //創(chuàng)建動(dòng)畫路徑
    UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 300, 200)];
    shaperLayer.path = path.CGPath;
//    CGPathRelease(path.CGPath);
    
    CAKeyframeAnimation *animation2 = [CAKeyframeAnimation animationWithKeyPath:@"strokeEnd"];
    animation2.duration = 8;
    animation2.repeatCount = MAXFLOAT;
    animation2.values = @[@(0),@(1),@(0)];
    animation2.removedOnCompletion = NO;
    animation2.fillMode = kCAFillModeForwards;
    
    /**
     * 上述的animation2的動(dòng)畫和效果和下面的animation動(dòng)畫效果是一樣的
     */
    CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.duration = 4;
    animation.repeatCount = MAXFLOAT;
    animation.fromValue = @(0);
    animation.toValue = @(1);
//    這個(gè)設(shè)置是在一個(gè)動(dòng)畫完成時(shí),是否需要反向動(dòng)畫,默認(rèn)是NO
    animation.autoreverses = YES;
    
    [shaperLayer addAnimation:animation forKey:nil];
    
    [self.layer addSublayer:shaperLayer];
}

實(shí)現(xiàn)效果:

邊框環(huán)繞.gif

邊框環(huán)繞二

原理:用到兩個(gè)shaperLayer來實(shí)現(xiàn),利用CAAnimationDelegate代理方法做處理

.h文件

/*第一個(gè)shaperLayer*/
@property (nonatomic,strong) CAShapeLayer *shaperLayer1;
/*第二個(gè)shaperLayer*/
@property (nonatomic,strong) CAShapeLayer *shaperLayer2;
/*第一個(gè)shaperLayer的動(dòng)畫*/
@property (nonatomic,strong) CABasicAnimation *animation1;
/*第二個(gè)shaperLayer的動(dòng)畫*/
@property (nonatomic,strong) CABasicAnimation *animation2;

.m文件

/*無到有的shaper*/
- (CAShapeLayer *)shaperLayer1
{
    if(!_shaperLayer1){
        _shaperLayer1 = [CAShapeLayer layer];
        //    shaperLayer1.position = CGPointMake((kWidth-300)/2, (kHeight-200)/2);
        _shaperLayer1.strokeColor = [UIColor whiteColor].CGColor;
        _shaperLayer1.fillColor = [UIColor clearColor].CGColor;
        _shaperLayer1.lineDashPattern = @[@(8)];
        //    結(jié)尾處的類型
        _shaperLayer1.lineCap = kCALineCapRound;
        //    拐角處的類型
        _shaperLayer1.lineJoin = kCALineJoinRound;
        _shaperLayer1.lineWidth = 5;
    }
    return _shaperLayer1;
}
/*有到無shaper*/
- (CAShapeLayer *)shaperLayer2
{
    if(!_shaperLayer2){
        _shaperLayer2 = [CAShapeLayer layer];
        //    shaperLayer2.position = CGPointMake((kWidth-300)/2, (kHeight-200)/2);
        _shaperLayer2.strokeColor = [UIColor whiteColor].CGColor;
        _shaperLayer2.fillColor = [UIColor clearColor].CGColor;
        _shaperLayer2.lineDashPattern = @[@(8)];
        //    結(jié)尾處的類型
        _shaperLayer2.lineCap = kCALineCapRound;
        //    拐角處的類型
        _shaperLayer2.lineJoin = kCALineJoinRound;
        _shaperLayer2.lineWidth = 5;
    }
    return _shaperLayer2;
}

/*注釋*/
- (CABasicAnimation *)animation1
{
    if(!_animation1){
        _animation1 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        _animation1.duration = 4;
        _animation1.fromValue = @(0);
        _animation1.toValue = @(1);
        _animation1.repeatCount = 1;
        _animation1.removedOnCompletion = NO;
        _animation1.fillMode = kCAFillModeForwards;
        _animation1.delegate = self;
        [_animation1 setValue:@"animation1" forKey:@"animation1"];
    }
    return _animation1;
}

/*注釋*/
- (CABasicAnimation *)animation2
{
    if(!_animation2){
        _animation2 = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
        _animation2.fromValue = @(1);
        _animation2.toValue = @(0);
        _animation2.duration = 4;
        _animation2.repeatCount = 1;
//        _animation2.autoreverses = YES;
        _animation2.removedOnCompletion = NO;
        _animation2.fillMode = kCAFillModeBackwards;
        _animation2.delegate = self;
        [_animation2 setValue:@"animation2" forKey:@"animation2"];
    }
    return _animation2;
}

- (void)marquee3{
//    創(chuàng)建路徑
    UIBezierPath * path1 = [UIBezierPath bezierPath];
    [path1 moveToPoint:CGPointMake(20, 200)];
    [path1 addLineToPoint:CGPointMake(300, 200)];
    [path1 addLineToPoint:CGPointMake(300, 400)];
    [path1 addLineToPoint:CGPointMake(20, 400)];
    [path1 closePath];
    self.shaperLayer1.path = path1.CGPath;
    
    UIBezierPath * path2 = [UIBezierPath bezierPath];
    [path2 moveToPoint:CGPointMake(20, 200)];
    [path2 addLineToPoint:CGPointMake(20, 400)];
    [path2 addLineToPoint:CGPointMake(300, 400)];
    [path2 addLineToPoint:CGPointMake(300, 200)];
    [path2 closePath];
    self.shaperLayer2.path = path2.CGPath;
//    創(chuàng)建動(dòng)畫
    [self.shaperLayer1 addAnimation:self.animation1 forKey:@"animation1"];
    
    [self.layer addSublayer:self.shaperLayer1];
    [self.layer addSublayer:self.shaperLayer2];
    self.shaperLayer2.opacity = 0;
}

//動(dòng)畫開始
- (void)animationDidStart:(CAAnimation *)anim{
    
}

//動(dòng)畫結(jié)束
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
    //判斷是不是第一個(gè)動(dòng)畫
    if ([[anim valueForKey:@"animation1"] isEqualToString:@"animation1"]) {
        self.shaperLayer1.opacity = 0;
//shaperLayer1刪除掉所有動(dòng)畫
        [self.shaperLayer1 removeAnimationForKey:@"animation1"];
        [self.shaperLayer2 addAnimation:self.animation2 forKey:@"animation2"];
        self.shaperLayer2.opacity = 1;
    }else{
        self.shaperLayer2.opacity = 0;
//shaperLayer2刪除所有的動(dòng)畫
        [self.shaperLayer2 removeAllAnimations];
        [self.shaperLayer1 addAnimation:self.animation1 forKey:@"animation1"];
        self.shaperLayer1.opacity = 1;
    }
}

上述代碼有一段下面的代碼:

[self.shaperLayer2 removeAllAnimations];

一般在動(dòng)畫結(jié)束后,layer會(huì)自動(dòng)刪除掉自己的animation。但是在你設(shè)置了animation的removedOnCompletion屬性為NO的時(shí)候,就需要自己刪除掉layer的animation。removeAllAnimationsremoveAnimationForKey不僅有表面的意思刪除掉動(dòng)畫,還有起到暫停動(dòng)畫的效果,在動(dòng)畫過程中實(shí)現(xiàn)這個(gè),會(huì)使動(dòng)畫暫停;

調(diào)用:

[self marquee3];

實(shí)現(xiàn)效果:

邊框環(huán)繞2.gif

這個(gè)動(dòng)畫中間會(huì)跳動(dòng)一下,目前要想實(shí)現(xiàn)這個(gè)效果,沒有想到其他方法,有想法的朋友可以告知下,這里感謝不已。

最后

這里說一個(gè)研究過程中遇到的一個(gè)問題:
問題:animation動(dòng)畫結(jié)束后,會(huì)閃回到最開始狀態(tài),然后消失
解決這個(gè)問題,首先要在創(chuàng)建animation的時(shí)候,設(shè)置兩個(gè)屬性值。分別為:

//這個(gè)屬性表示的是動(dòng)畫結(jié)束后是否回到開始的狀態(tài),默認(rèn)是YES
 animation.removedOnCompletion = NO;
//這個(gè)描述的是動(dòng)畫填充方式
animation.fillMode = kCAFillModeForwards;

fillMode 有下面幾個(gè)狀態(tài)值:

  • kCAFillModeRemoved 這個(gè)是默認(rèn)值,也就是說當(dāng)動(dòng)畫開始前和動(dòng)畫結(jié)束后,動(dòng)畫對(duì)layer都沒有影響,動(dòng)畫結(jié)束后,layer會(huì)恢復(fù)到之前的狀態(tài)

  • kCAFillModeForwards 當(dāng)動(dòng)畫結(jié)束后,layer會(huì)一直保持著動(dòng)畫最后的狀態(tài)

  • kCAFillModeBackwards 在動(dòng)畫開始前,只需要將動(dòng)畫加入了一個(gè)layer,layer便立即進(jìn)入動(dòng)畫的初始狀態(tài)并等待動(dòng)畫開始。

  • kCAFillModeBoth 這個(gè)其實(shí)就是上面兩個(gè)的合成,動(dòng)畫加入之后在開始之前,layer便處于動(dòng)畫初始狀態(tài),動(dòng)畫結(jié)束后layer保持動(dòng)畫最后的狀態(tài)


其他的動(dòng)畫效果可以自己嘗試下。

CABasicAnimation的具體應(yīng)用在后續(xù)的CALayer、CAShaperLayer里面都有用到

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 CALayer IOS SDK詳解之CALayer(一) http://doc.okbase.net/Hell...
    Kevin_Junbaozi閱讀 5,336評(píng)論 3 23
  • 如果想讓事情變得順利,只有靠自己--夏爾·紀(jì)堯姆 上一章介紹了隱式動(dòng)畫的概念。隱式動(dòng)畫是在iOS平臺(tái)創(chuàng)建動(dòng)態(tài)用戶界...
    夜空下最亮的亮點(diǎn)閱讀 2,101評(píng)論 0 1
  • 在iOS實(shí)際開發(fā)中常用的動(dòng)畫無非是以下四種:UIView動(dòng)畫,核心動(dòng)畫,幀動(dòng)畫,自定義轉(zhuǎn)場(chǎng)動(dòng)畫。 1.UIView...
    請(qǐng)叫我周小帥閱讀 3,323評(píng)論 1 23
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺ios動(dòng)畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,690評(píng)論 6 30
  • 在iOS中隨處都可以看到絢麗的動(dòng)畫效果,實(shí)現(xiàn)這些動(dòng)畫的過程并不復(fù)雜,今天將帶大家一窺iOS動(dòng)畫全貌。在這里你可以看...
    F麥子閱讀 5,270評(píng)論 5 13

友情鏈接更多精彩內(nèi)容