iOS那些簡單的動畫(不定期更新)

關于 Core Animation

Core Animation是一組非常強大的動畫處理API,使用它能做出很多優雅的動畫效果。能用的動畫類有4個子類:CABasicAnimation、CAKeyframeAnimation、CATransition、CAAnimationGroup

開發步驟:

  1. 初始化一個動畫對象(CAAnimation)并設置一些動畫相關屬性.
  1. 添加動畫對象到層(CALayer)中,開始執行動畫.

CALayer中很多屬性都可以通過CAAnimation實現動畫效果, 包括opacity, position, transform, bounds, contents等,具體可以在API文檔中查找

通過調用CALayer的addAnimation:forKey:增加動畫到層(CALayer)中,這樣就能觸發動畫了.通過調用removeAnimationForKey:可以停止層中的動畫.

注:Core Animation的動畫執行過程都是在后臺操作的,不會阻塞主線程.

創建動畫時你可能用到的屬性

屬性 | 解讀
----|------|----
Autoreverses | 設定這個屬性為 YES 時,在它到達目的地之后,動畫的返回到開始的值,代替了直接跳轉到開始的值,過渡平滑
Duration |設定開始值到結束值花費的時間。期間會被速度的屬性所影響
RemovedOnCompletion | 這個屬性默認為 YES,在指定的時間段完成后,動畫就自動的從層上移除了。
FillMode | 這個屬性一般和 RemovedOnCompletion 配合使用,保持動畫狀態。其中kCAFillModeForwards 當動畫結束后,layer會一直保持著動畫最后的狀態.此時將RemovedOnCompletion設為NO
Speed | 默認的值為 1.0.如果你改變這個值為 2.0,動畫會用 2 倍的速度播放。這樣的影響就是使持續時間減半。如果你指定的持續時間為 6 秒,速度為 2.0,動畫就會播放 3 秒鐘即一半的持續時間。
RepeatCount | 默認的是 0,動畫只會播放一次。如果指定一個無限大的重復次數,使用 MAXFLOAT 。這個不應該和 repeatDration 屬性一塊使用
RepeatDuration | 這個屬性指定了動畫應該被重復多久。動畫會一直重復,直到設定的時間用完。同上它不應該和 repeatCount 一起使用
FromValue | 設置動畫的初始值
ToValue | 設置動畫的到達值
TimingFunction | 控制動畫運行的節奏. kCAMediaTimingFunctionLinear(線性):勻速,給你一個相對靜態的感覺 kCAMediaTimingFunctionEaseIn(漸進):動畫緩慢進入,然后加速離開 kCAMediaTimingFunctionEaseOut(漸出):動畫全速進入,然后減速的到達目的地 kCAMediaTimingFunctionEaseInEaseOut(漸進漸出):動畫緩慢的進入,中間加速,然后減速的到達目的地。這個是默認的動畫行為。
BeginTime | 可以用來設置動畫延遲執行時間,若想延遲1s,就設置為CACurrentMediaTime()+1,CACurrentMediaTime()為圖層的當前時間

巧妙的運用這些可以屬性實現很棒的動畫效果,比如下面:用CABasicAnimation實現的動畫

CABasicAnimation動畫

簡單的呼吸和搖擺動畫


animation.gif

簡單的代碼

 1.呼吸動畫
    CABasicAnimation *animation =[CABasicAnimation animationWithKeyPath:@"opacity"];
    animation.fromValue = [NSNumber numberWithFloat:1.0f];
    animation.toValue = [NSNumber numberWithFloat:0.0f];
    animation.autoreverses = YES;    //回退動畫(動畫可逆,即循環)
    animation.duration = 1.0f;
    animation.repeatCount = MAXFLOAT;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;//removedOnCompletion,fillMode配合使用保持動畫完成效果
    animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    [self.alphaTagButton.layer addAnimation:animation forKey:@"aAlpha"];  

2.搖擺動畫
    //設置旋轉原點
    self.sharkTagButton.layer.anchorPoint = CGPointMake(0.5, 0);
    CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    //角度轉弧度(這里用1,-1簡單處理一下)
    rotationAnimation.toValue = [NSNumber numberWithFloat:1];
    rotationAnimation.fromValue = [NSNumber numberWithFloat:-1];
    rotationAnimation.duration = 1.0f;
    rotationAnimation.repeatCount = MAXFLOAT;
    rotationAnimation.removedOnCompletion = NO;
    rotationAnimation.autoreverses = YES;
    rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    rotationAnimation.fillMode = kCAFillModeForwards;
    [self.sharkTagButton.layer addAnimation:rotationAnimation forKey:@"revItUpAnimation"];
    

陀螺儀&加速儀的動畫

ps:好吧 這個屬于亂入,和上面的搖擺動畫差不多的效果,只是這個是手動的 哈哈

3、陀螺儀&加速儀的動畫
    self.motionManager = [[CMMotionManager alloc] init];
    self.motionManager.deviceMotionUpdateInterval = 1.0f/100.0f; //1秒100次
    self.sharkTagButton.layer.anchorPoint = CGPointMake(0.5, 0);
    [self.motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
        if(fabs(motion.attitude.roll)<1.0f)
        {
            [UIView animateWithDuration:0.6 animations:^{
                self.sharkTagButton.layer.transform = CATransform3DMakeRotation(-(motion.attitude.roll), 0, 0, 1);
            }];
        }else if (fabs(motion.attitude.roll)<1.5f)
        {
            [UIView animateWithDuration:0.6 animations:^{
                int s;
                if (motion.attitude.roll>0)
                {
                    s=-1;
                }else
                {
                    s = 1;
                }
                self.sharkTagButton.layer.transform = CATransform3DMakeRotation(s*M_PI_2, 0, 0, 1);
            }];
        }
        if ((motion.attitude.pitch)<0)
        {
            [UIView animateWithDuration:0.6 animations:^{
                self.sharkTagButton.layer.transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
            }];
        }
        
    }];

Demo地址:
https://github.com/yongliangP/CABasicAnimationDemo



CATransition之簡單的轉場動畫

CAAnimation的子類,用于做轉場動畫,能夠為層提供移出屏幕和移入屏幕的動畫效果。

屬性 解讀
type 動畫過渡類型
subtype 動畫過渡方向
  • 常用動畫類型:
type的值 解讀 對應常量
fade 淡入淡出 kCATransitionFade
push 推擠 kCATransitionPush
reveal 揭開 kCATransitionReveal
moveIn 覆蓋 kCATransitionMoveIn
cube 立方體 私有API
suckEffect 吮吸 私有API
oglFlip 翻轉 私有API
rippleEffect 波紋 私有API
pageCurl 反翻頁 私有API
cameraIrisHollowOpen 開鏡頭 私有API
cameraIrisHollowClose 關鏡頭 私有API

注:私有API只能通過字符串使用哈


  • 過渡方向參數:
subtype的值 解讀
kCATransitionFromRight 從右轉場
kCATransitionFromLeft 從左轉場
kCATransitionFromBottom 從下轉場
kCATransitionFromTop 從上轉場

簡單的CATransition動畫


CATransitionDemo2.gif
-(void)animationWithType:(NSString*)type
{

    //- 創建一個轉場動畫:
    CATransition *transition = [CATransition animation];
    transition.repeatCount = 5;

    //    - 確定動畫類型:
    transition.type = type;
    
    //    - 確定子類型(方向等)
    transition.subtype = kCATransitionFromLeft;
    
    //    - 確定動畫時間
    transition.duration = 1;
    
    //    - 添加動畫
    [self.imageView.layer addAnimation:transition forKey:nil];
    
}

使用時只用傳你的想要的動畫類型就好,私有API只能通過字符串使用哈。

[self animationWithType:self.dataArray[indexPath.row]];

DEMO地址:https://github.com/yongliangP/CATransitionDemo


---20160908更新


CAKeyframeAnimation

先看圖,就是那個在跑的小圓球,為了方便,把動畫集成在了一個Demo里了

ScreenShotDemo2.gif
  • 1 .簡單介紹

CAKeyframeAnimation是CApropertyAnimation的子類,跟CABasicAnimation的區別是:CABasicAnimation只能從一個數值(fromValue)變到另一個數值(toValue),而CAKeyframeAnimation會使用一個NSArray保存這些數值,是一種更靈活的動畫方式。

  • 2 .屬性介紹
屬性 解讀
values NSArray對象,里面的元素稱為”關鍵幀”(keyframe)。動畫對象會在指定的時間(duration)內,依次顯示values數組中的每一個關鍵幀
path 可以設置一個CGPathRef\CGMutablePathRef,讓層跟著路徑移動。path只對CALayer的anchorPoint和position起作用。如果你設置了path,那么values將被忽略
keyTimes 可以為對應的關鍵幀指定對應的時間點,其取值范圍為[0,1],keyTimes中的每一個時間值都對應values中的每一幀.當keyTimes沒有設置的時候,各個關鍵幀的時間是平分的
  • 3 .實現
  • 3.1 values方式實現
-(void)setUpCAKeyframeAnimationUseValues
{

    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    
    animation.keyPath = @"position";
    
    NSValue *value1 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
    
    NSValue *value2 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, 50)];
    
    NSValue *value3 = [NSValue valueWithCGPoint:CGPointMake(kWindowWidth - 50, kWindowHeight-50)];
    
    NSValue *value4 = [NSValue valueWithCGPoint:CGPointMake(50, kWindowHeight-50)];
    
    NSValue *value5 = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
    
    animation.values = @[value1,value2,value3,value4,value5];
    animation.repeatCount = MAXFLOAT;
    
    animation.removedOnCompletion = NO;
    
    animation.fillMode = kCAFillModeForwards;
    
    animation.duration = 6.0f;
    
    animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    [self.keyButton.layer addAnimation:animation forKey:@"values"];
    
}

    • 3.2 path方式實現
-(void)setUpCAKeyframeAnimationUsePath
{
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    
    animation.keyPath = @"position";
    
    CGMutablePathRef path = CGPathCreateMutable();
    
    //矩形線路
    CGPathAddRect(path, NULL, CGRectMake(50,50, kWindowWidth - 100,kWindowHeight - 100));
    
    animation.path=path;
    
    CGPathRelease(path);
    
    animation.repeatCount = MAXFLOAT;
    
    animation.removedOnCompletion = NO;
    
    animation.fillMode = kCAFillModeForwards;
    
    animation.duration = 10.0f;
    
    animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    [self.keyButton.layer addAnimation:animation forKey:@"path"];


}

    • 3.3 keyTimes演示
-(void)setUpCAKeyframeAnimationUsekeyTimes
{
    
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
//    animation.keyPath = @"transform.translation.x";
    animation.keyPath = @"position.x";
    animation.values = @[@0, @20, @-20, @20, @0];
    animation.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];
    animation.duration = 0.5;
    animation.additive = YES;
    [self.sharkTagButton.layer addAnimation:animation forKey:@"keyTimes"];

}


---20160921更新


CAAnimationGroup

看圖,就是那個下方的小長方形,簡單實現

ScreenShotGroupDemo.gif

動畫組,顧名思義就是動畫的組合,具體動畫可以參考上文,不同的腦洞會出現不同的化學反應。

簡單示例:

    CABasicAnimation * animationScale = [CABasicAnimation animation];
    animationScale.keyPath = @"transform.scale";
    animationScale.toValue = @(0.1);
    
    CABasicAnimation *animationRota = [CABasicAnimation animation];
    animationRota.keyPath = @"transform.rotation";
    animationRota.toValue = @(M_PI_2);
    
    CAAnimationGroup * group = [[CAAnimationGroup alloc] init];
    group.duration = 3.0;
    group.fillMode = kCAFillModeForwards;
    group.removedOnCompletion = NO;
    group.repeatCount = MAXFLOAT;
    
    group.animations = @[animationScale,animationRota];
    [self.groupButton.layer addAnimation:group forKey:nil];
 

Demo傳送門

附:關于keyPath你可能用到的屬性

屬性 解讀
transform.rotation.x 圍繞x軸翻轉。y,z同理 參數:角度
transform.rotation 默認圍繞z軸
transform.scale.x x方向縮放。y,z同理
transform.scale 所有方向縮放
transform.translation.x x軸方向移動,參數:x軸上的坐標。y,z同理
transform.translation 移動到的點
zPosition 平面的位置
opacity 透明度
backgroundColor 背景顏色 參數:顏色 (id)[[UIColor redColor] CGColor]
cornerRadius layer圓角
borderWidth 邊框寬度
bounds 大小 參數:CGRect
contents 內容 參數:CGImage
contentsRect 可視內容 參數:CGRect 值是0~1之間的小數
position 位置,效果和transform.rotation差不多
shadowColor 陰影顏色
shadowOffset 陰影偏移
shadowOpacity 陰影透明度
shadowRadius 陰影角度

照例放Demo
Demo地址:
https://github.com/yongliangP/CABasicAnimationDemo
如果你覺得對你有幫助請點喜歡哦,也可以關注我,每周至少一篇技術。
或者關注 我的專題 每周至少5篇更新,多謝支持哈。
(ps:核心動畫編程pdf中文版想要的可以私信我)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容