您的位置:首页 > 移动开发 > IOS开发

iOS 核心动画 代码详解

2016-02-01 11:42 363 查看
//
//  ViewController.m
//  test_shapeLayer_01
//
//  Created by admin on 1/28/16.
//  Copyright © 2016 jeffasd. All rights reserved.
//

#import "ViewController.h"

#define pi 3.14159265359
#define   DEGREES_TO_RADIANS(degrees)  ((pi * degrees)/
180)

@interface ViewController ()

@property(nonatomic,
strong) CAShapeLayer *shapeLayer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super
viewDidLoad];

    self.shapeLayer = [CAShapeLayer
layer];
//    _shapeLayer.frame = CGRectMake(0, 0, 200, 200);
    _shapeLayer.frame =
self.view.frame;
//    _shapeLayer.position = self.view.center;
    _shapeLayer.fillColor = [UIColor
clearColor].CGColor;
    
    _shapeLayer.lineWidth =
1.0f;
    _shapeLayer.strokeColor = [UIColor
cyanColor].CGColor;
    
//    UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];
    
//    UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];
    
    
//    UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(150, 150)
//                                                         radius:75
//                                                     startAngle:0
//                                                       endAngle:DEGREES_TO_RADIANS(135)
//                                                      clockwise:YES];
    
//    //绘制二次贝塞尔曲线
//    UIBezierPath *circlePath = [UIBezierPath bezierPath];
////    [circlePath moveToPoint:CGPointMake(20, 100)];
//    [circlePath moveToPoint:CGPointMake(0, 100)];
//    [circlePath addQuadCurveToPoint:CGPointMake(200, 100) controlPoint:CGPointMake(100, 0)];
    
    
#if 0
    //绘制三次贝塞尔曲线
    UIBezierPath *circlePath = [UIBezierPath bezierPath];
    [circlePath moveToPoint:CGPointMake(20,
50)];
    [circlePath addCurveToPoint:CGPointMake(200,
50) controlPoint1:CGPointMake(110,
0) controlPoint2:CGPointMake(110,
100)];
    _shapeLayer.path = circlePath.CGPath;
#endif
    
    
    //绘制三次贝塞尔曲线
    UIBezierPath *circlePath = [UIBezierPath
bezierPath];
    [circlePath moveToPoint:CGPointMake(20,
100)];
    [circlePath addCurveToPoint:CGPointMake(350,
600) controlPoint1:CGPointMake(110,
0) controlPoint2:CGPointMake(110,
100)];
    _shapeLayer.path = circlePath.CGPath;
    
    
    _shapeLayer.strokeStart =
0;
    _shapeLayer.strokeEnd =
1.0;
    
    [self.view.layer
addSublayer:_shapeLayer];
    
#if 0
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    animation.duration = 3;
    animation.timingFunction = [CAMediaTimingFunction functionWithName:@"easeInEaseOut"];
    animation.repeatCount = 1;
    animation.path = circlePath.CGPath;
    
    UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(100,
20, 10,
10)];
    
//    subView.center = self.view.center;
    
    subView.backgroundColor = [UIColor redColor];
    [self.view addSubview:subView];
    
//    subView.center = self.view.center;
    
    //为subView视图添加动画
    [subView.layer addAnimation:animation forKey:@"test"];
#endif
    
    
//    //绘制曲线
//    CGContextMoveToPoint(context, 20, 100);//移动到起始位置
//    /*绘制二次贝塞尔曲线
//     c:图形上下文
//     cpx:控制点x坐标
//     cpy:控制点y坐标
//     x:结束点x坐标
//     y:结束点y坐标
//     */
//    CGContextAddQuadCurveToPoint(context, 160, 0, 300, 100);
//    
//    CGContextMoveToPoint(context, 20, 500);
//    /*绘制三次贝塞尔曲线
//     c:图形上下文
//     cp1x:第一个控制点x坐标
//     cp1y:第一个控制点y坐标
//     cp2x:第二个控制点x坐标
//     cp2y:第二个控制点y坐标
//     x:结束点x坐标
//     y:结束点y坐标
//     */
//    CGContextAddCurveToPoint(context, 80, 300, 240, 500, 300, 300);
//    
//    //设置图形上下文属性
//    [[UIColor yellowColor]setFill];
//    [[UIColor redColor]setStroke];
//    
//    
//    //绘制路径
//    CGContextDrawPath(context, kCGPathFillStroke);
    
    
    CALayer *layer=[CALayer
layer];
    
    layer.frame=CGRectMake(50,
200, 50,
50);
    
    layer.backgroundColor=[UIColor
orangeColor].CGColor;
    
    layer.cornerRadius=8.0f;
    
    
//    CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.translation.y"];
//    
//    animation.duration=4.0f;
//    
//    animation.autoreverses=NO;
//    
//    animation.repeatCount=1;
//    
//    animation.toValue=[NSNumber numberWithInt:-10];
//    
//    animation.fromValue=[NSNumber numberWithInt:200];
//    
//    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    
    CABasicAnimation *animationZoomIn=[CABasicAnimation
animationWithKeyPath:@"transform.scale"];
    
    animationZoomIn.duration=2.0f;
    
    animationZoomIn.autoreverses=NO;
    
    animationZoomIn.repeatCount=1;
    
    animationZoomIn.toValue=[NSNumber
numberWithFloat:1.56];
    
    animationZoomIn.timingFunction=[CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseIn];
    
    CABasicAnimation *animationZoomOut=[CABasicAnimation
animationWithKeyPath:@"transform.scale"];
    
    animationZoomOut.beginTime=2.0f;
    
    animationZoomOut.duration=2.0f;
    
    animationZoomOut.autoreverses=NO;
    
    animationZoomOut.repeatCount=1;
    
    animationZoomOut.toValue=[NSNumber
numberWithFloat:.01];
    
    animationZoomOut.timingFunction=[CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseOut];
    
    CAAnimationGroup *group=[CAAnimationGroup
animation];
    
    group.duration=4.0f;
    
//    group.animations=[NSArray arrayWithObjects: animation, animationZoomIn, animationZoomOut,nil];
    group.animations=[NSArray
arrayWithObjects: animationZoomIn, animationZoomOut,nil];
    
    group.removedOnCompletion=NO;
    
    group.fillMode=kCAFillModeForwards;
    
    [layer addAnimation:group
forKey:nil];
    
    [self.view.layer
addSublayer:layer];
    
    
    //layer.hidden=YES;
    
}

- (void)didReceiveMemoryWarning {
    [super
didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

//
//  ViewController.m
//  CABasicAnimationDemo

//

#import "ViewController.h"

#define KYOffset    20

@interface ViewController ()

@property(nonatomic,
strong)UIView *ViewTest;

@property(nonatomic,
strong) CAShapeLayer *shapeLayer;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super
viewDidLoad];

    self.shapeLayer = [CAShapeLayer
layer];
    _shapeLayer.frame =
self.view.frame;
    _shapeLayer.fillColor = [UIColor
clearColor].CGColor;
    _shapeLayer.lineWidth =
1.0f;
    _shapeLayer.strokeColor = [UIColor
redColor].CGColor;
    
    self.ViewTest = [[UIView
alloc] initWithFrame:CGRectMake(20,
100, 200,
200)];
    
    [self.view
addSubview:_ViewTest];
    self.ViewTest.backgroundColor = [UIColor
redColor];
    
    
    //组合动画调用
//    [self startAnimation2];
    
    //永久闪烁动画
//    [self opacityForever_Animation:0.3];
    
    ////有闪烁次数的动画
//    [self opacityTimes_Animation:10 durTimes:0.3];
    
    //画一条线
路径
//    [self drawACurvedLine];
    
    //路径动画
//    [self animateCicleAlongPath];
    
//    [self initScaleLayer];
    
    //顺序执行动画
    [self
animationByOrder];
    
}

-(void)startAnimation
{
    CABasicAnimation *animation = [CABasicAnimation
animationWithKeyPath:@"position"];
    animation.fromValue = [NSValue
valueWithCGPoint:CGPointMake(50,
50)];
    animation.toValue = [NSValue
valueWithCGPoint:CGPointMake(300,
300)];
    animation.duration =
3.0f;
    animation.repeatCount =
1;
    //animation.removedOnCompletion = NO; //完成后是否回到原来状态,如果为NO
就是停留在动画结束时的状态
    //animation.fillMode = kCAFillModeRemoved;//动画完成后返回到原来状态
    //animation.fillMode = kCAFillModeBackwards;
    animation.fillMode =
kCAFillModeForwards;//当动画完成时,保留在动画结束的状态
    
    [self.ViewTest.layer
addAnimation:animation forKey:nil];
}

-(void)startAnimation1
{
    CABasicAnimation *animation = [CABasicAnimation
animationWithKeyPath:@"transform.translation.y"];
    animation.fromValue = [NSNumber
numberWithFloat:0.0f];
    animation.toValue   = [NSNumber
numberWithFloat:10.0f];
    //animation.duration = 0.5f;
    //animation.fillMode = kCAFillModeForwards;
    //animation.removedOnCompletion = NO;
    //animation.repeatCount = 2;
    //[self.ViewTest.layer addAnimation:animation forKey:nil];
    
    CABasicAnimation *animation1 = [CABasicAnimation
animationWithKeyPath:@"transform.translation.x"];
    animation.fromValue = [NSNumber
numberWithFloat:0.0f];
    animation.toValue   = [NSNumber
numberWithFloat:10.0f];
    //animation.duration = 0.5f;
    //animation.fillMode = kCAFillModeForwards;
    //animation.removedOnCompletion = NO;
    //animation.repeatCount = 2;
    //[self.ViewTest.layer addAnimation:animation1 forKey:nil];
    
    CAAnimationGroup *groupAnimation = [CAAnimationGroup
animation];
    groupAnimation.duration =
2.0f;
    groupAnimation.autoreverses  =
YES;
    groupAnimation.repeatCount =
5;
    [groupAnimation setAnimations:[NSArray
arrayWithObjects:animation,animation1,
nil]];
    
    [self.ViewTest.layer
addAnimation:groupAnimation
forKey:nil];
}

//组合动画
-(void)startAnimation2
{
    //界限
    CABasicAnimation *boundsAnimation = [CABasicAnimation
animationWithKeyPath:@"bounds"];
//    CABasicAnimation *boundsAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
    boundsAnimation.fromValue = [NSValue
valueWithCGRect: self.ViewTest.bounds];
    boundsAnimation.toValue = [NSValue
valueWithCGRect:CGRectZero];
    //透明度变化
    CABasicAnimation *opacityAnimation = [CABasicAnimation
animationWithKeyPath:@"opacity"];
    opacityAnimation.fromValue = [NSNumber
numberWithFloat:1.0];
    opacityAnimation.toValue = [NSNumber
numberWithFloat:0.5];
    
    //位置移动
    CABasicAnimation *animation  = [CABasicAnimation
animationWithKeyPath:@"position"];
    animation.fromValue =  [NSValue
valueWithCGPoint: self.ViewTest.layer.position];
    CGPoint toPoint =
self.ViewTest.layer.position;
    toPoint.x +=
180;
    animation.toValue = [NSValue
valueWithCGPoint:toPoint];
    
    //旋转动画
    CABasicAnimation* rotationAnimation =
    [CABasicAnimation
animationWithKeyPath:@"transform.rotation.z"];//"z"还可以是“x”“y”,表示沿z轴旋转
    
    rotationAnimation.toValue = [NSNumber
numberWithFloat:(2 *
M_PI) * 3];
    // 3 is the number of 360 degree rotations
    
    // Make the rotation animation duration slightly less than the other animations to give it the feel
    // that it pauses at its largest scale value
    rotationAnimation.duration =
3.0f;
    rotationAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
//缓入缓出
    //rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    
    //缩放动画
    CABasicAnimation *scaleAnimation = [CABasicAnimation
animationWithKeyPath:@"transform.scale"];
    scaleAnimation.fromValue = [NSNumber
numberWithFloat:0.0];
    scaleAnimation.toValue = [NSNumber
numberWithFloat:1.0];
    scaleAnimation.duration =
3.0f;
    scaleAnimation.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    //组合动画
    CAAnimationGroup *animationGroup = [CAAnimationGroup
animation];
    animationGroup.duration =
3.0f;
    animationGroup.autoreverses =
YES;   //是否重播,原动画的倒播
    animationGroup.repeatCount =
NSNotFound;//HUGE_VALF;
//HUGE_VALF,源自math.h
//    [animationGroup setAnimations:[NSArray arrayWithObjects:rotationAnimation, scaleAnimation,boundsAnimation, nil]];
    
//    [animationGroup setAnimations:[NSArray arrayWithObjects:scaleAnimation, nil]];
    
    [animationGroup setAnimations:[NSArray
arrayWithObjects:boundsAnimation,
nil]];
    
    //将上述两个动画编组
    
    [self.ViewTest.layer
addAnimation:animationGroup
forKey:@"animationGroup"];
}

//永久闪烁的动画
-(void)opacityForever_Animation:(float)time
{
    CABasicAnimation *animation=[CABasicAnimation
animationWithKeyPath:@"opacity"];
    animation.fromValue=[NSNumber
numberWithFloat:1.0];
    animation.toValue=[NSNumber
numberWithFloat:0.0];
    animation.autoreverses=YES;
    animation.duration=time;
    animation.repeatCount=FLT_MAX;
    animation.removedOnCompletion=NO;
    animation.fillMode=kCAFillModeForwards;
    
    [self.ViewTest.layer
addAnimation:animation forKey:@"opacityForever"];
}
/**************************************************************************/

//有闪烁次数的动画

-(void)opacityTimes_Animation:(float)repeatTimes durTimes:(float)time;
{
    CABasicAnimation *animation=[CABasicAnimation
animationWithKeyPath:@"opacity"];
    animation.fromValue=[NSNumber
numberWithFloat:1.0];
    animation.toValue=[NSNumber
numberWithFloat:0.4];
    animation.repeatCount=repeatTimes;
    animation.duration=time;
    animation.removedOnCompletion=NO;
    animation.fillMode=kCAFillModeForwards;
    animation.timingFunction=[CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseIn];
    animation.autoreverses=YES;
    
    [self.ViewTest.layer
addAnimation:animation forKey:@"opacityTimes"];
    
}
/**************************************************************************/
//路径动画

-(void)keyframeAniamtion:(CGMutablePathRef)path durTimes:(float)time Rep:(float)repeatTimes
{
    
}

//在视图中画一条线
-(void)drawACurvedLine
{
    UIGraphicsBeginImageContext(CGSizeMake(320,
460));
    CGContextRef context =
UIGraphicsGetCurrentContext();
    
    CGContextSetLineWidth(context,
3);
    CGContextSetStrokeColorWithColor(context, [UIColor
blueColor].CGColor);
    //设置起点
    CGContextMoveToPoint(context,
10, 10);
    
    CGContextAddQuadCurveToPoint(context,
10, 450,
310, 450);
    //CGContextAddQuadCurveToPoint(context, 310, 10, 10, 10);
    
    //划线
    CGContextDrawPath(context,
kCGPathStroke);
    
    //得到一个image
从目前的矢量上下文
    UIImage *curve =
UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    UIImageView *curveView = [[UIImageView
alloc]initWithImage:curve];
    curveView.frame =
CGRectMake(1,
1, 320,
460);
    [curveView setBackgroundColor:[UIColor
clearColor]];
    [self.view
addSubview:curveView];
}

-(void)animateCicleAlongPath
{
    //准备关键帧动画
    CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation
animationWithKeyPath:@"position"];
//    pathAnimation.calculationMode = kCAAnimationPaced;
    pathAnimation.calculationMode =
kCAAnimationLinear;
    pathAnimation.fillMode =
kCAFillModeForwards;
    pathAnimation.removedOnCompletion =
NO;
    pathAnimation.duration =
5.0f;
    pathAnimation.repeatCount =
200;
    pathAnimation.autoreverses =
YES; //原路返回,而不是从头再来
    //设置动画路径
    //CGPoint endPoint = CGPointMake(310, 450);
    CGMutablePathRef curvedPath =
CGPathCreateMutable();
    CGPathMoveToPoint(curvedPath,
NULL, 10,
10);
    CGPathAddQuadCurveToPoint(curvedPath,
NULL, 10,
450, 310,
450);
    CGPathAddQuadCurveToPoint(curvedPath,
NULL, 310,
10, 10,
10);
    //已经有了路径,我们要告诉动画 
路径
    pathAnimation.path = curvedPath;
    CGPathRelease(curvedPath); 
//这里要手工释放
    
    _shapeLayer.path = curvedPath;
    [self.view.layer
addSublayer:_shapeLayer];
    
    [self.ViewTest.layer
addAnimation:pathAnimation
forKey:nil];
    
}

- (void)initScaleLayer{
    CALayer *scaleLayer = [CALayer
new];
    scaleLayer.backgroundColor = [UIColor
blueColor].CGColor;
    scaleLayer.frame =
CGRectMake(60,
20 + KYOffset,
50, 50);
    scaleLayer.cornerRadius =
10;
    [self.view.layer
addSublayer:scaleLayer];
    
    CABasicAnimation *scaleAnimation = [CABasicAnimation
animationWithKeyPath:@"transform.scale"];
    scaleAnimation.fromValue = [NSNumber
numberWithFloat:1.0];
    scaleAnimation.toValue = [NSNumber
numberWithFloat:1.5];
    scaleAnimation.autoreverses =
YES;
    scaleAnimation.fillMode =
kCAFillModeForwards;
    scaleAnimation.repeatCount =
MAXFLOAT;
    scaleAnimation.duration =
0.8;
    
    [scaleLayer addAnimation:scaleAnimation
forKey:@"scaleAnimation"];
}

- (void)animationByOrder//animationBySequence
{
    
    CABasicAnimation *posAnimation = [CABasicAnimation
animationWithKeyPath:@"position"];
    posAnimation.fromValue = [NSValue
valueWithCGPoint:CGPointMake(50,
50)];
    posAnimation.toValue = [NSValue
valueWithCGPoint:CGPointMake(300,
300)];
    // Here's the important part
    [posAnimation setDuration:5.0];
    [posAnimation setBeginTime:0.0];
    posAnimation.fillMode =
kCAFillModeForwards;//当动画完成时,保留在动画结束的状态
//    posAnimation.duration = 3.0f;
//    posAnimation.repeatCount = 1;
    //animation.removedOnCompletion = NO; //完成后是否回到原来状态,如果为NO
就是停留在动画结束时的状态
    //animation.fillMode = kCAFillModeRemoved;//动画完成后返回到原来状态
    //animation.fillMode = kCAFillModeBackwards;

    
    
//    CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
//    [posAnimation setFromValue:[NSNumber numberWithFloat:0.0]];
//    [posAnimation setToValue:[NSNumber numberWithFloat:1.0]];
//    // Here's the important part
//    [posAnimation setDuration:10.0];
//    [posAnimation setBeginTime:0.0];
    
    CABasicAnimation *borderWidthAnimation = [CABasicAnimation
animationWithKeyPath:@"borderWidth"];
    [borderWidthAnimation setFromValue:[NSNumber
numberWithFloat:0.0]];
    [borderWidthAnimation setToValue:[NSNumber
numberWithFloat:20.0]];
    // Here's the important part
    [borderWidthAnimation setDuration:10.0];
    [borderWidthAnimation setBeginTime:5.0];
                                                   
//kCAMediaTimingFunctionLinear kCAMediaTimingFunctionEaseInEaseOut
    borderWidthAnimation.timingFunction=[CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionLinear];
    
    CAAnimationGroup *group = [CAAnimationGroup
animation];
    [group setDuration:10.0];
    [group setAnimations:[NSArray
arrayWithObjects:posAnimation, borderWidthAnimation,
nil]];
    
    [self.ViewTest.layer
addAnimation:group forKey:nil];
    self.ViewTest.layer.borderColor
= [UIColor yellowColor].CGColor;
}

/**************************************************************************/
- (void)didReceiveMemoryWarning
{
    [super
didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: