iOS 動畫基礎總結篇

陳雨塵發表於2018-07-18

美女鎮樓.JPG

好久沒有更新簡書了,最近在看一個動畫的第三方,想著是時候可以把動畫相關的東西總結下了!對了,上面的美女是龍母!哈哈,最近看權力遊戲,感覺很好!

-------------------------------------------------進入正題------------------------------------------------------------------

動畫的大體分類(個人總結可能有誤)

分類.png

UIView 動畫

屬性動畫

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelay:1];
    [UIView setAnimationDuration:2];
    [UIView setAnimationRepeatCount:100];
    [UIView setAnimationRepeatAutoreverses: YES];  // 翻轉
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; //設定動畫變化的曲線
    UIView *view =  self.redview;
    view.alpha = 0;
    view.center = CGPointMake(view.center.x + 300, view.center.y);
    [UIView setAnimationDelegate:self];   // 設定代理 監測動畫結束的
    [UIView setAnimationDidStopSelector:@selector(shopAction)];
    [UIView commitAnimations];


   其中   setAnimationCurve 引數為
   UIViewAnimationCurveEaseInOut:這種曲線的動畫開始緩慢,在其持續時間的中間加速,然後在完成之
 前再次減慢。這是大多數動畫的預設曲線。
   UIViewAnimationCurveEaseIn:動畫開始時緩慢,然後加速,直到動畫結束。這裡選用這種型別動畫曲
 線。
   UIViewAnimationCurveEaseOut:動畫開始時速度很快,在結束前開始減速。
   UIViewAnimationCurveLinear:在動畫持續時間內,動畫勻速執行。
複製程式碼

基於Block的屬性動畫

     [UIView animateWithDuration:0.5 animations:^{
    
    UIView *view = self.viewArray[4];
   view.transform = CGAffineTransformRotate(view.transform, M_2_PI); // 順時針旋轉
}];


[UIView animateKeyframesWithDuration:2 delay:0 options:UIViewKeyframeAnimationOptionRepeat animations:^{
    UIView *view = self.viewArray[5];
   view.transform = CGAffineTransformMakeScale(2, 1);//寬高伸縮比例;
} completion:^(BOOL finished) {
    if (finished) {
       UIView *view = self.viewArray[5];
       view.backgroundColor = [UIColor colorWithRed: arc4random()%256 / 255.0 green:arc4random()%256 / 255.0 blue:arc4random()%256/ 255.0  alpha:1.0];
    }
}];
[UIView animateKeyframesWithDuration:5 delay:0 options:UIViewKeyframeAnimationOptionRepeat animations:^{
     UIView *view = self.viewArray[6];
    view.transform = CGAffineTransformMakeTranslation(300, 6);//xy移動距離;
} completion:^(BOOL finished) {
    if (finished) {
        UIView *view = self.viewArray[6];
        view.backgroundColor = [UIColor colorWithRed: arc4random()%256 / 255.0 green:arc4random()%256 / 255.0 blue:arc4random()%256/ 255.0  alpha:1.0];
    }
    
}];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionRepeat animations:^{
      UIView *view = self.viewArray[7];
      view.transform = CGAffineTransformMake(1.5, 1, 2, 2, 1,1);//自定義形變,引數自擬;
    
} completion:^(BOOL finished) {
    if (finished) {
           UIView *view = self.viewArray[7];
           view.backgroundColor = [UIColor colorWithRed: arc4random()%256 / 255.0 green:arc4random()%256 / 255.0 blue:arc4random()%256/ 255.0  alpha:1.0];
    }
    
}];

// 彈簧效果  // 一  動畫執行的時間   二  動畫延遲執行的時間  第三個  彈簧震動的頻率 0 - 1 值越小頻率越高 四 彈簧的起始抖動的速度  五 代表動畫的效果  六 具體執行的動畫   七 執行完之後 的操作
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.1 initialSpringVelocity:10 options:UIViewAnimationOptionCurveLinear animations:^{
         UIView *view = self.viewArray[8];
    if (view.center.x > [UIScreen mainScreen].bounds.size.width) {
        view.center = CGPointMake(0, view.center.y);
    }else{
        view.center = CGPointMake(view.center.x + 10, view.center.y);
    }
    
    
    
} completion:^(BOOL finished) {
    
}];
複製程式碼

我的理解是UIView的屬性動畫 就是在一定時間內改變其屬性值從而達到動畫的效果。

屬性動畫效果如下,有助於理解不同引數的效果

UIview 屬性動畫.gif

過渡動畫(本來有做gif 圖但是不知道為啥放上來不會動了 捂臉!) 圖好了?

轉場.gif

  [UIView transitionWithView:self.view3 duration:1 options:UIViewAnimationOptionTransitionFlipFromTop animations:^{
        self.view1.hidden = NO;
        self.view2.hidden = YES;
    } completion:^(BOOL finished) {
        
    }];


  引數  
 //轉場動畫相關的

  UIViewAnimationOptionTransitionNone            //無轉場動畫
  UIViewAnimationOptionTransitionFlipFromLeft    //轉場從左翻轉
  UIViewAnimationOptionTransitionFlipFromRight   //轉場從右翻轉
  UIViewAnimationOptionTransitionCurlUp          //上卷轉場
  UIViewAnimationOptionTransitionCurlDown        //下卷轉場
  UIViewAnimationOptionTransitionCrossDissolve   //轉場交叉消失
  UIViewAnimationOptionTransitionFlipFromTop     //轉場從上翻轉
  UIViewAnimationOptionTransitionFlipFromBottom  //轉場從下翻轉
複製程式碼

layer 層動畫

layer 層屬性 設定一些邊框 圓角等

view.layer.borderWidth = 6;
view.layer.borderColor = [UIColor redColor].CGColor;
view.layer.cornerRadius = 10;
CGPoint archP = view.layer.anchorPoint;
CGPoint postion = view.layer.position;
複製程式碼

layer 動畫 CABasicAnimation

   // 一些常用的key
   /*   transform.scale	比例轉化	@(0.8)
 transform.scale.x	寬的比例	@(0.8)
 transform.scale.y	高的比例	@(0.8)
 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之間的
 */
   /*  屬性	說明
duration	動畫的時長
repeatCount	重複的次數。不停重複設定為 HUGE_VALF
repeatDuration	設定動畫的時間。在該時間內動畫一直執行,不計次數。
beginTime	指定動畫開始的時間。從開始延遲幾秒的話,設定為【CACurrentMediaTime() + 秒數】 的方式
timingFunction	設定動畫的速度變化
autoreverses	動畫結束時是否執行逆動畫
fromValue	所改變屬性的起始值
toValue	所改變屬性的結束時的值
byValue	所改變屬性相同起始值的改變數
 */

 //CABasicAnimation 最終不會修改其屬性  只是為了做動畫使用
 // 設定需要修改的layer層屬性
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position.x"];
//設定對應的控制元件Layer層position.x 的起始值
basicAnimation.fromValue = @(-112);
// 設定最終值
basicAnimation.toValue = @(425);
// 設定時間
basicAnimation.duration = 4;
// 設定動畫重複的次數
basicAnimation.repeatCount = 1000000;
// 將動畫新增到對應檢視的layer層上
[view1.layer addAnimation:basicAnimation forKey:nil];


CABasicAnimation *transformAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];

transformAnima.fromValue = @(M_PI_2);
transformAnima.toValue = @(M_PI);
transformAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transformAnima.autoreverses = YES;
transformAnima.repeatCount = HUGE_VALF;
transformAnima.beginTime = CACurrentMediaTime() + 1;


// 這兩個是在動畫結束之後使view 到最終狀態而不是原始狀態  因為layer 層動畫 其實view 本身frame 沒有改變的
transformAnima.removedOnCompletion = NO;
transformAnima.fillMode = kCAFillModeForwards;
//    fillMode
 /* 該屬性定義了你的動畫在開始和結束時的動作。預設值是 kCAFillModeRemoved。
  取值的解釋
   kCAFillModeRemoved 設定為該值,動畫將在設定的 beginTime 開始執行(如沒有設定beginTime屬性,則動畫立即執行),動畫執行完成後將會layer的改變恢復原狀。
   kCAFillModeForwards 設定為該值,動畫即使之後layer的狀態將保持在動畫的最後一幀,而removedOnCompletion的預設屬性值是 YES,所以為了使動畫結束之後layer保持結束狀態,應將removedOnCompletion設定為NO。
   kCAFillModeBackwards 設定為該值,將會立即執行動畫的第一幀,不論是否設定了 beginTime屬性。觀察發現,設定該值,剛開始檢視不見,還不知道應用在哪裡。
 kCAFillModeBoth 該值是 kCAFillModeForwards 和 kCAFillModeBackwards的組合狀態
*/

   // 新增動畫
   [view.layer addAnimation:transformAnima forKey:@"A"];
複製程式碼

CAKeyframeAnimation 關鍵幀動畫

// 關鍵幀動畫
// 指定動畫需要修改的屬性
CAKeyframeAnimation *keyFrameA = [CAKeyframeAnimation animationWithKeyPath:@"position"];
// 獲得起始的點
CGPoint point1 = view12.layer.position;
// 第二個點
CGPoint point2 = CGPointMake(375 / 2.0, -50);
// 第三個點
CGPoint point3 = CGPointMake(375 + 50, point1.y);
// 第四個點
CGPoint point4 = point1;
NSValue *pointV1 = [NSValue valueWithCGPoint:point1];
NSValue *pointV2 = [NSValue valueWithCGPoint:point2];
NSValue *pointV3 = [NSValue valueWithCGPoint:point3];
NSValue *pointV4 = [NSValue valueWithCGPoint:point4];
keyFrameA.values = @[pointV1,pointV2,pointV3,pointV4];
// 設定每幀動畫的起始和結束點
keyFrameA.duration = 5;
// 設定重複的次數
keyFrameA.repeatCount = 1000;
//將動畫新增到指定的控制元件的layer上;
[view12.layer addAnimation:keyFrameA forKey:nil];


//繞矩形迴圈跑

CALayer * rectLayer = [[CALayer alloc] init];
rectLayer.frame = CGRectMake(15, 200, 30, 30);
rectLayer.cornerRadius = 15;
rectLayer.backgroundColor = [[UIColor blackColor] CGColor];
[self.view.layer addSublayer:rectLayer];
CAKeyframeAnimation *rectRunAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
//設定關鍵幀位置,必須含起始與終止位置
rectRunAnimation.values = @[[NSValue valueWithCGPoint:rectLayer.frame.origin],
                            [NSValue valueWithCGPoint:CGPointMake([UIScreen mainScreen].bounds.size.width - 15,
                                                                  rectLayer.frame.origin.y)],
                            [NSValue valueWithCGPoint:CGPointMake([UIScreen mainScreen].bounds.size.width - 15,
                                                                  rectLayer.frame.origin.y + 100)],
                            [NSValue valueWithCGPoint:CGPointMake(15, rectLayer.frame.origin.y + 100)],
                            [NSValue valueWithCGPoint:rectLayer.frame.origin]];

 //    CGMutablePathRef path = CGPathCreateMutable()
//    CGPathMoveToPoint(path, NULL, rectLayer.position.x - 15, rectLayer.position.y - 15);
 //    CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y);
 //    CGPathAddLineToPoint(path, NULL, 320 - 15, rectLayer.frame.origin.y + 100);
 //    CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y + 100);
//    CGPathAddLineToPoint(path, NULL, 15, rectLayer.frame.origin.y);
//    rectRunAnimation.path = path;
//    CGPathRelease(path);



//設定每個關鍵幀的時長,如果沒有顯式地設定,則預設每個幀的時間=總duration/(values.count - 1)
rectRunAnimation.keyTimes = @[[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.6],
                              [NSNumber numberWithFloat:0.7], [NSNumber numberWithFloat:0.8],
                              [NSNumber numberWithFloat:1]];

  //    1 kCAMediaTimingFunctionLinear//線性
  //    2 kCAMediaTimingFunctionEaseIn//淡入
  //    3 kCAMediaTimingFunctionEaseOut//淡出
 //    4 kCAMediaTimingFunctionEaseInEaseOut//淡入淡出
  //    5 kCAMediaTimingFunctionDefault//預設


rectRunAnimation.timingFunctions = @[[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn],
                                     [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
rectRunAnimation.repeatCount = 1000;
rectRunAnimation.autoreverses = NO;

 //    1 const kCAAnimationLinear//線性,預設
 //    2 const kCAAnimationDiscrete//離散,無中間過程,但keyTimes設定的時間依舊生效,物體跳躍地出現在各個關鍵幀上
 //    3 const kCAAnimationPaced//平均,keyTimes跟timeFunctions失效
 //    4 const kCAAnimationCubic//平均,同上
 //    5 const kCAAnimationCubicPaced//平均,同上

rectRunAnimation.calculationMode = kCAAnimationLinear;
rectRunAnimation.duration = 4;
rectRunAnimation.removedOnCompletion = NO;
rectRunAnimation.fillMode = kCAFillModeForwards;
[rectLayer addAnimation:rectRunAnimation forKey:@"rectRunAnimation"];
self.rectLayer = rectLayer;
}
  // 抖動示例

  // 建立幀動畫物件
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
  // 設定動畫屬性
anim.keyPath = @"transform.rotation";
anim.values = @[@(kAngleToRadian(-5)), @(kAngleToRadian(5))];
 // 設定動畫執行次數
anim.repeatCount = HUGE_VALF;
 // 設定動畫的執行時長
anim.duration = 0.1;
  // 設定動畫的自動反轉效果
anim.autoreverses = YES;
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
/ 將動畫效果新增到lionImage的layer上
[self.imagev.layer addAnimation:anim forKey:nil];
複製程式碼

本來都有動圖的,現在都動不了,大家可以想象下 一個圖在左右抖動 , 上面的那個圖是 一個小球按著矩形 線路走一會快一會慢 ! ?

圖來了

CAKeyframeAnimation.gif

其實關鍵幀動畫相對來說可能會作出比較複雜的效果,使用方法很簡單,只是複雜的動畫會使用到演算法,可能稍微需要思考。

CATransition 轉場

 kCATransitionFade                   //交叉淡化過渡                     
kCATransitionMoveIn               //移動覆蓋原圖                     
kCATransitionPush                    //新檢視將舊檢視推出去                     
kCATransitionReveal                //底部顯出來     
 kCATransitionFromRight;                     
 kCATransitionFromLeft(預設值)                     
 kCATransitionFromTop;                     
 kCATransitionFromBottom          
注:kCATransitionFade 不支援Subtype   

CATransition *anima = [CATransition animation];
anima.type = kCATransitionFade;//設定動畫的型別
anima.subtype = kCATransitionFromRight; //設定動畫的方向
//anima.startProgress = 0.3;//設定動畫起點
//anima.endProgress = 0.8;//設定動畫終點
anima.duration = 1.0f;
 [_demoView.layer addAnimation:anima forKey:@"fadeAnimation"];
複製程式碼

當然很多動畫都不是單一的出現的,下面我們就看下動畫組合。 其實動畫組合無非就是多種動畫作用在一個view上面達到的效果

例如

組合動畫.gif

動畫組合

  // 動畫組合
CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"];
positionAnima.duration = 0.8;
positionAnima.fromValue = @(view.center.y);
positionAnima.toValue =  @(view.center.y + 100);
positionAnima.timingFunction = [CAMediaTimingFunction 
 functionWithName:kCAMediaTimingFunctionLinear];
positionAnima.repeatCount = HUGE_VALF;
//    positionAnima.repeatDuration = 2;
positionAnima.removedOnCompletion = NO;
positionAnima.fillMode = kCAFillModeForwards;
positionAnima.delegate = self;
positionAnima.autoreverses = YES; // 執行逆動畫
[view.layer addAnimation:positionAnima forKey:@"AnimationMoveY"];


/* 放大縮小 */

// 設定為縮放
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

// 動畫選項設定
animation.duration = 2.5; // 動畫持續時間
animation.repeatCount = HUGE_VALF; // 重複次數
animation.autoreverses = YES; // 動畫結束時執行逆動畫
// 縮放倍數
animation.fromValue = [NSNumber numberWithFloat:1.0]; // 開始時的倍率
animation.toValue = [NSNumber numberWithFloat:2.0]; // 結束時的倍率
// 新增動畫
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[view.layer addAnimation:animation forKey:@"scale-layer"];

效果就是在移動的過程中放大縮小
複製程式碼

好了,至此都總結完畢,這些都是基礎的東西,好好利用這些再複雜的動畫也能做出來! 當然,還有粒子效果這裡因為沒有動圖就不先不總結了,好的,謝謝大家的捧場!

相關文章