Core Animation之多種動畫效果

jopen 10年前發布 | 14K 次閱讀 iOS開發 移動開發 Core Animation

前面介紹了Core Animation基礎知識,還有CALayer的簡單使用,最終還是有要動畫的滴,這里列出幾個動畫效果,參考下能加深對Core Animation的認識和理解

1、把圖片移到右下角變小透明

使用CAAnimationGroup疊加動畫效果,就是下面按鈕《把圖片移到右下角變小透明》描述的效果:

Core Animation之多種動畫效果    Core Animation之多種動畫效果   Core Animation之多種動畫效果

上面三個圖是動畫的三個狀態,實現代碼如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"snaguosha.png"]];
    self.imageView.frame = CGRectMake(10, 10, 128, 192);
    [self.view addSubview:self.imageView];
 }

 

- (IBAction)tranAction:(id)sender {
    CGPoint fromPoint = self.imageView.center;

//路徑曲線
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:fromPoint];
CGPoint toPoint = CGPointMake(300, 460);
[movePath addQuadCurveToPoint:toPoint
                 controlPoint:CGPointMake(300,0)];
//關鍵幀
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = YES;

//旋轉變化
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
scaleAnim.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
//x,y軸縮小到0.1,Z 軸不變
scaleAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
scaleAnim.removedOnCompletion = YES;

//透明度變化
CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:@"alpha"];
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0.1];
opacityAnim.removedOnCompletion = YES;

//關鍵幀,旋轉,透明度組合起來執行
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, scaleAnim,opacityAnim, nil];
animGroup.duration = 1;
[self.imageView.layer addAnimation:animGroup forKey:nil];

}</pre>

代碼解析:上面關鍵幀設置了動畫的路徑,scaleAnim設置了縮小,opacityAnim設置了透明度的變化。把三個動畫組合到:animGroup。

在把animGroup添加到imageView.layer層的動畫里。于是動畫效果就有了。

2、旋轉并向右移動

- (IBAction)RightRotateAction:(id)sender {
    CGPoint fromPoint = self.imageView.center;
    UIBezierPath *movePath = [UIBezierPath bezierPath];
    [movePath moveToPoint:fromPoint];
    CGPoint toPoint = CGPointMake(fromPoint.x +100 , fromPoint.y ) ;
    [movePath addLineToPoint:toPoint];

CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnim.path = movePath.CGPath;

CABasicAnimation *TransformAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
TransformAnim.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];

//沿Z軸旋轉
TransformAnim.toValue = [NSValue valueWithCATransform3D: CATransform3DMakeRotation(M_PI,0,0,1)];

//沿Y軸旋轉

// scaleAnim.toValue = [NSValue valueWithCATransform3D: CATransform3DMakeRotation(M_PI,0,1.0,0)];

//沿X軸旋轉

// TransformAnim.toValue = [NSValue valueWithCATransform3D: CATransform3DMakeRotation(M_PI,1.0,0,0)]; TransformAnim.cumulative = YES; TransformAnim.duration =3; //旋轉2遍,360度 TransformAnim.repeatCount =2; self.imageView.center = toPoint; TransformAnim.removedOnCompletion = YES; CAAnimationGroup *animGroup = [CAAnimationGroup animation]; animGroup.animations = [NSArray arrayWithObjects:moveAnim, TransformAnim, nil]; animGroup.duration = 6;

[self.imageView.layer addAnimation:animGroup forKey:nil];

}</pre>代碼解析:可能你沒注意到, CATransform3DMakeRotation,這返回的是旋轉的值。上面的動畫效果里返回的是 CATransform3DMakeScale縮放的值。
向右移動是因為關鍵幀使用了路徑為直線的路徑。

3、旋轉并消除邊緣鋸齒

- (IBAction)Rotate360Action:(id)sender {
    //圖片旋轉360度
    CABasicAnimation *animation = [ CABasicAnimation
                                   animationWithKeyPath: @"transform" ];
    animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];

    //圍繞Z軸旋轉,垂直與屏幕
    animation.toValue = [ NSValue valueWithCATransform3D:
                         CATransform3DMakeRotation(M_PI, 0, 0, 1.0) ];
    animation.duration = 3;
    //旋轉效果累計,先轉180度,接著再旋轉180度,從而實現360旋轉
    animation.cumulative = YES;
    animation.repeatCount = 2;

    //在圖片邊緣添加一個像素的透明區域,去圖片鋸齒
    CGRect imageRrect = CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height);
    UIGraphicsBeginImageContext(imageRrect.size);
    [self.imageView.image drawInRect:CGRectMake(1,1,self.imageView.frame.size.width-2,self.imageView.frame.size.height-2)];
    self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self.imageView.layer addAnimation:animation forKey:nil];
}
如果你仔細觀察,會看到第二個動畫里在旋轉時,圖片邊緣是有鋸齒的,如何消除呢? 在圖片邊緣添加一個像素的透明區域,去圖片鋸齒。

UIGraphicsBeginImageContext 開始圖片內容

UIGraphicsGetImageFromCurrentImageContext 獲取當前內容作為圖片,

UIGraphicsEndImageContext結束。是和UIGraphicsBeginImageContext配套使用的。

4、吃豆人動畫

這個有點復雜,首先說下實現的步驟:
  1. 畫一個吃豆人開口的路徑:pacmanOpenPath
  2. 畫一個吃豆人閉口的路徑:pacmanClosedPath
  3. 新建一個閉口的吃豆人頭的層:shapeLayer
  4. 把開口和閉口路徑設置成CABasicAnimation *chompAnimation動畫的起點和終點,這樣循環就能出現咬牙的動畫了。
  5. 最后設置一個路徑為關鍵幀,讓吃豆人在這條路徑上行動。
代碼如下:
- (void)animationInit
{
    self.view.backgroundColor = [UIColor blackColor];

    CGFloat radius = 30.0f;
    CGFloat diameter = radius * 2;
    CGPoint arcCenter = CGPointMake(radius, radius);
    // Create a UIBezierPath for Pacman's open state
    pacmanOpenPath = [UIBezierPath bezierPathWithArcCenter:arcCenter
                                                    radius:radius
                                                startAngle:DEGREES_TO_RADIANS(35)
                                                  endAngle:DEGREES_TO_RADIANS(315)
                                                 clockwise:YES];

    [pacmanOpenPath addLineToPoint:arcCenter];
    [pacmanOpenPath closePath];

    // Create a UIBezierPath for Pacman's close state
    pacmanClosedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter
                                                      radius:radius
                                                  startAngle:DEGREES_TO_RADIANS(1)
                                                    endAngle:DEGREES_TO_RADIANS(359)
                                                   clockwise:YES];
    [pacmanClosedPath addLineToPoint:arcCenter];
    [pacmanClosedPath closePath];

    // Create a CAShapeLayer for Pacman, fill with yellow
    shapeLayer = [CAShapeLayer layer];
    shapeLayer.fillColor = [UIColor yellowColor].CGColor;
    shapeLayer.path = pacmanClosedPath.CGPath;
    shapeLayer.strokeColor = [UIColor grayColor].CGColor;
    shapeLayer.lineWidth = 1.0f;
    shapeLayer.bounds = CGRectMake(0, 0, diameter, diameter);
    shapeLayer.position = CGPointMake(-40, -100);
    [self.view.layer addSublayer:shapeLayer];

    SEL startSelector = @selector(startAnimation);
    UIGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:startSelector];
    [self.view addGestureRecognizer:recognizer];
}
- (void)startAnimation {
    // 創建咬牙動畫
    CABasicAnimation *chompAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    chompAnimation.duration = 0.25;
    chompAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    chompAnimation.repeatCount = HUGE_VALF;
    chompAnimation.autoreverses = YES;
    // Animate between the two path values
    chompAnimation.fromValue = (id)pacmanClosedPath.CGPath;
    chompAnimation.toValue = (id)pacmanOpenPath.CGPath;
    [shapeLayer addAnimation:chompAnimation forKey:@"chompAnimation"];

    // Create digital '2'-shaped path

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path moveToPoint:CGPointMake(0, 100)];
    [path addLineToPoint:CGPointMake(300, 100)];
    [path addLineToPoint:CGPointMake(300, 200)];
    [path addLineToPoint:CGPointMake(0, 200)];
    [path addLineToPoint:CGPointMake(0, 300)];
    [path addLineToPoint:CGPointMake(300, 300)];

    CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    moveAnimation.path = path.CGPath;
    moveAnimation.duration = 8.0f;
    // Setting the rotation mode ensures Pacman's mouth is always forward.  This is a very convenient CA feature.
    moveAnimation.rotationMode = kCAAnimationRotateAuto;
    [shapeLayer addAnimation:moveAnimation forKey:@"moveAnimation"];
}

 

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self animationInit];
}

還需要添加一個宏:

#define DEGREES_TO_RADIANS(x) (3.14159265358979323846 * x / 180.0)    計算角度轉換

添加了個手勢,點一下屏幕,吃豆人就動起來了。效果:

Core Animation之多種動畫效果

本篇例子代碼:代碼

容芳志 (http://blog.csdn.net/totogo2010)

本文遵循“署名-非商業用途-保持一致”創作公用協議

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!