再談CAAnimation動畫


CAAnimaton動畫分為CABasicAnimation & CAKeyframeAnimation

 

CABasicAnimation動畫

顧名思義就是最基本的動畫, 老規矩先上代碼:

//1.先創建一個要執行動畫的View
    UIView *actView = ({
    
        UIView *view         = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
        view.backgroundColor = [UIColor redColor];
        
        view;
    });
    
    [self.view addSubview:actView];

//2 創建CABasicAnimation位移動畫
    CABasicAnimation *basicAnimation = ({
    
        CABasicAnimation *animation   = [CABasicAnimation animationWithKeyPath:@"position"];
        animation.removedOnCompletion = NO;
        animation.fillMode            = kCAFillModeForwards;
        animation.duration            = 2;
        animation.repeatCount         = 10;
        animation.beginTime           = CACurrentMediaTime() + 5;
        animation.toValue             = [NSValue valueWithCGPoint:CGPointMake(400, 400)];
        
        animation;
    });

//3. 將動畫添加到view的layer層
    [actView.layer addAnimation:basicAnimation forKey:@"first"];

GIF1

gif是抄的老司機的

首先創建動畫的時候我們直接指定keypath為“position”位移動畫, 還有哪些動畫可以設定呢?

可以查看CALayer的源碼

/* The bounds of the layer. Defaults to CGRectZero. Animatable. */

@property CGRect bounds;

只要有標注Animatable的屬性都可以做動畫, 我們羅列下做個記錄方便以后查看

@property CGRect bounds;

@property CGPoint position;

@property CGFloat zPosition;

@property CGPoint anchorPoint;

@property CGFloat anchorPointZ;

@property CATransform3D transform;

@property(getter=isHidden) BOOL hidden;

@property(getter=isDoubleSided) BOOL doubleSided;

@property CATransform3D sublayerTransform;

@property BOOL masksToBounds;

@property(nullable, strong) id contents;

@property CGRect contentsRect;

@property CGFloat contentsScale;

@property CGRect contentsCenter;

@property float minificationFilterBias;

@property(nullable) CGColorRef backgroundColor;

@property CGFloat cornerRadius;

@property CGFloat borderWidth;

@property(nullable) CGColorRef borderColor;

@property float opacity;

@property(nullable, copy) NSArray *filters;

@property(nullable, copy) NSArray *backgroundFilters;

@property BOOL shouldRasterize;

@property CGFloat rasterizationScale;

@property(nullable) CGColorRef shadowColor;

@property float shadowOpacity;

@property CGSize shadowOffset;

@property CGFloat shadowRadius;

@property(nullable) CGPathRef shadowPath;

雖然是取名字是BasicAnimation, 但能實現到動畫還是挺多的, 后面有空再逐個試驗下

removedOnCompletion = NO,是否在播放完成后移除。這是一個非常重要的屬性,有的時候我們希望動畫播放完成,但是保留最終的播放效果是,這個屬性一定要改為NO,否則無效。

fillMode,是播放結束后的狀態。他有四個枚舉值

  • kCAFillModeForwards//保持結束時狀態
  • kCAFillModeBackwards//保持開始時狀態
  • kCAFillModeBoth//保持兩者,我沒懂兩者是什么概念,實際使用中與kCAFillModeBackwards相同
  • kCAFillModeRemoved//移除

這個屬性使用的時候要設置removedOnCompletion = NO

duration, 是動畫持續時間

repeatCount, 動畫重復次數, 默認不重復

beginTime, 動畫延時

toValue, 動畫最后的位置 注意時NSValue封裝

還有一個fromValue, 動畫開始的位置, 不設置的話就是View當前的位置

 

下面時用CABasicAnimation寫的動畫修改圓角的動畫, 把一個正方形慢慢變成圓形

CABasicAnimation *basicAnimation2 = ({
        
        CABasicAnimation *animation   = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
        animation.removedOnCompletion = NO;
        animation.fillMode            = kCAFillModeForwards;
        animation.duration            = 2;
        animation.toValue             = @50;
        
        animation;
    });

 大家可以復制到Xcode中去試試效果

 

CAKeyframeAnimation關鍵幀動畫

相比BasicAnimation, KeyframeAnimation更為靈活, 可以設置多段動畫

一樣上代碼先

CAKeyframeAnimation *keyframeAnimation = ({
    
        CAKeyframeAnimation *animation   = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        animation.removedOnCompletion    = NO;
        animation.fillMode               = kCAFillModeForwards;
        animation.duration               = 2;
        animation.repeatCount            = 10;
        animation.beginTime              = CACurrentMediaTime() + 5;
        animation.calculationMode        = kCAAnimationCubicPaced;
        animation.keyTimes               = @[@0, @0.25, @0.5];
        animation.values                 = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],
                                             [NSValue valueWithCGPoint:CGPointMake(200, 200)],
                                             [NSValue valueWithCGPoint:CGPointMake(0,400)]];
        
        animation;
    });

gif2

大部分根CABasicAnimation差不多, 我說說不一樣的地方

calculationMode, 設置為kCAAnimationCubicPaced后動畫在轉角更加平滑, 否則會有明顯的停頓

大家可以注銷這行代碼試試看

keyTime飾設置每一段動畫的速度, 不設置的話默認為勻速, 這個地方注意有幾段動畫就要設置段數+1個速度, 第一個一般是0, 如果有少寫 后面的漏掉的部分動畫就不會執行

values, 就是設置動畫線路 內容是NSValue封裝的CGpoint

還有一個變量Path可以設置, 這個屬性可以用UIBezierPath來設定特殊形狀的路徑, 如果有設置path屬性, values屬性就不會生效了

上代碼

    CAKeyframeAnimation *keyframeAnimation = ({
    
        CAKeyframeAnimation *animation   = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        animation.removedOnCompletion    = NO;
        animation.fillMode               = kCAFillModeForwards;
        animation.duration               = 2;
        animation.repeatCount            = 10;
        animation.beginTime              = CACurrentMediaTime() + 5;
        animation.calculationMode        = kCAAnimationCubicPaced;
        animation.keyTimes               = @[@0, @0.25, @0.5, @0.75, @1];
        animation.values                 = @[[NSValue valueWithCGPoint:CGPointMake(0, 0)],
                                             [NSValue valueWithCGPoint:CGPointMake(200, 200)],
                                             [NSValue valueWithCGPoint:CGPointMake(0,400)]];
        animation.path                   = [UIBezierPath bezierPathWithOvalInRect:\
                                            CGRectMake(100, 100, 100, 100)].CGPath;
        
        animation;
    });

fi

關於UIBezierPath后面會再單獨

 

然后我們說下動畫組, CAAnimation是可以幾個動畫合並在一起的

上代碼:

//2.2 創建CABasicAnimation動畫
    CABasicAnimation *basicAnimation2 = ({
        
        CABasicAnimation *animation   = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
        animation.removedOnCompletion = NO;
        animation.fillMode            = kCAFillModeForwards;
        animation.duration            = 2;
        animation.toValue             = @50;
        
        animation;
    });
    
    //2.3 創建CAKeyframeAnimation動畫
    CAKeyframeAnimation *keyframeAnimation = ({
    
        CAKeyframeAnimation *animation   = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        animation.removedOnCompletion    = NO;
        animation.fillMode               = kCAFillModeForwards;
        animation.duration               = 2;
        animation.calculationMode        = kCAAnimationCubicPaced;
        animation.keyTimes               = @[@0, @0.25, @0.5, @0.75, @1];
        animation.path                   = [UIBezierPath bezierPathWithOvalInRect:\
                                            CGRectMake(100, 100, 100, 100)].CGPath;
        
        animation;
    });
    
    //3. 創建動畫組
    CAAnimationGroup *group = ({
    
        CAAnimationGroup *group   = [CAAnimationGroup animation];
        group.duration            = 2;
        group.fillMode            = kCAFillModeForwards;
        group.removedOnCompletion = NO;
        group.animations          = @[basicAnimation2, keyframeAnimation];
        
        group;
    });
    
    //4. 將動畫添加到view的layer層
    [actView.layer addAnimation:group forKey:@"first"];

14

這里我們把上面創建的一個動畫修改圓角跟沿着正方形路線走的動畫加入到一個CAAnimationGroup中

這里在要加入組中的動畫最后不要設置延遲時間, 可能會出問題

老司機說animations數組中你的所有CAAnimaiton對象請安beginTime進行升序排列

但海沒明白怎么回事 這部分后面找時間看下

 

利用緩動函數配合關鍵幀動畫實現比較復雜的物理性動畫

先說說什么是緩動函數, 就是有高人寫了一個庫可以計算出模擬物理性動畫(比如彈簧效果)所要的路徑

Github地址: https://github.com/YouXianMing/EasingAnimation

具體有哪些動畫效果可看庫中的緩動函數查詢表, 簡單舉個小球落地的效果

上代碼:

//設置原始畫面
    UIView *showView               = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    showView.layer.masksToBounds   = YES;
    showView.layer.cornerRadius    = 50.f;
    showView.layer.backgroundColor = [UIColor redColor].CGColor;
    
    [self.view addSubview:showView];
    
    //創建關鍵幀動畫
    CAKeyframeAnimation *keyFrameAnimation = [CAKeyframeAnimation animation];
    
    //設置動畫屬性
    keyFrameAnimation.keyPath              = @"position";
    keyFrameAnimation.duration             = 4.0f;
    
    //關鍵處, 在這里使用的緩動函數計算點路徑
    keyFrameAnimation.values = [YXEasing calculateFrameFromPoint:showView.center
                                                         toPoint:CGPointMake(50, 300)
                                                            func:BounceEaseOut
                                                      frameCount:4.0f * 30];
    
    //設置動畫結束位置
    showView.center = CGPointMake(50, 300);
    
    //添加動畫到layer層
    [showView.layer addAnimation:keyFrameAnimation forKey:nil];

 

最后還有

CATransition

專場動畫, 我們再后面一篇中來講

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM