学习一下动画,感谢以下大神的文章:
UIView:基础动画.关键帧动画.转场动画
Core Animation :基础动画,关键帧动画,动画组,转场动画,逐帧动画
CALayer :CALayer简介,CALayer常用属性,CALayer绘图
===> http://www.cnblogs.com/kenshincui/p/3972100.html
在看完这些文章之后,本猿照葫芦画猴子,写了个小demo,算是简单学习下动画.该demo中使用CABasicAnimation CAKeyframeAnimation keyframeAnimation
贝塞尔曲线绘制路径 UIView动画 逐帧动画 UIView动画 转场动画 动画组 CALayer动画,传感器仿膜拜动画大锅乱炖.
1.首先为各个动画写个入口
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 //背景 4 UIImage * bgImg = [UIImage imageNamed:@"树林"]; 5 self.bgImg = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, SCRCCEWH.width, SCRCCEWH.height)]; 6 self.bgImg.image = bgImg; 7 [self.view addSubview:self.bgImg]; 8 9 self.currentIndex = 1; //默认第一张图片 10 self.ballAry = @[@"大师球",@"高级球",@"超级球",@"精灵球"]; //先准备4个球体 11 12 //晴天娃娃摇摆动画 13 [self sunChildAniamtion]; //基础动画 CABasicAnimation 14 //制作树叶layer 15 [self makeLeafLayer]; 16 //制作小汽车 17 [self makeCarLayer]; 18 //落叶下落动画 19 [self fallLeafAnimation]; //关键帧动画 CAKeyframeAnimation 通过贝塞尔曲线绘制下路路径 CGPathCreateMutable 20 //落叶旋转动画 21 [self leafOverturnAnimation]; //基础动画 CABasicAnimation 22 //落叶生长动画 23 [self leafGrowAnimation]; //UIView动画 24 //蝴蝶飞舞动画 25 [self butterflyAnimation]; //逐帧动画:振翅 飞翔:关键帧动画 路径:keyframeAnimation 26 27 }
2.点击屏幕的时候,展开转场动画(水波效果),仿膜拜动画,组合动画(汽车动画)
1 //MARK:点击屏幕 2 -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ 3 //制作球体 4 WLBallView * ballView = [[WLBallView alloc] initWithFrame:CGRectMake(0, 80, 50, 50) AndImageName:self.ballAry[arc4random_uniform(4)]]; 5 [self.view addSubview:ballView]; 6 [ballView starMotion]; 7 //系统转场动画 8 CATransition *transition = [CATransition animation]; 9 transition.type = @"rippleEffect"; //部分动画类型是未公开的,但仍然可以使用 10 transition.duration = 2; 11 [self.bgImg.layer addAnimation:transition forKey:nil]; 12 //组合动画 13 [self groupAnimation]; //组合动画(汽车) 14 }
3.接下来是组合动画(汽车)的代码,组合CABasicAnimation + CAKeyframeAnimation
1 //MARK:制作小汽车 2 -(void)makeCarLayer{ 3 self.carLayer = [[CALayer alloc]init]; 4 self.carLayer.bounds = CGRectMake(0, 0, 100, 100); 5 self.carLayer.position = CGPointMake(SCRCCEWH.width - 100, SCRCCEWH.height - 50); 6 self.carLayer.contents = (id)[UIImage imageNamed:@"小汽车"].CGImage; 7 [self.view.layer addSublayer:self.carLayer]; 8 } 9 //MARK:组合动画 10 -(void)groupAnimation{ 11 // 1.创建动画组 12 CAAnimationGroup * animationGroup = [CAAnimationGroup animation]; 13 // 2.设置组中的动画和其他属性 14 CABasicAnimation * basicAnimation = [self carBasicAnimation]; 15 CAKeyframeAnimation * keyframeAnimation = [self carKeyFrameAnimation]; 16 animationGroup.animations = @[keyframeAnimation,basicAnimation]; 17 18 animationGroup.duration=10.0;//设置动画时间,如果动画组中动画已经设置过动画属性则不再生效 19 animationGroup.beginTime=CACurrentMediaTime()+2;//延迟五秒执行 20 21 //3.给图层添加动画 22 [self.carLayer addAnimation:animationGroup forKey:nil]; 23 } 24 //小汽车加速动画 25 -(CABasicAnimation *)carBasicAnimation{ 26 CABasicAnimation *basicAnimation=[CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 27 28 CGFloat toValue= M_PI_2 / 2.5; 29 basicAnimation.toValue=[NSNumber numberWithFloat: M_PI_2/2.5]; 30 [basicAnimation setValue:[NSNumber numberWithFloat:toValue] forKey:@"carTransform"]; 31 return basicAnimation; 32 } 33 //MARK:小汽车移动动画 34 -(CAKeyframeAnimation *)carKeyFrameAnimation{ 35 CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"]; 36 37 CGPoint endPoint= CGPointMake(-100, SCRCCEWH.height - 50); 38 CGPathRef path=CGPathCreateMutable(); 39 CGPathMoveToPoint(path, NULL, self.carLayer.position.x, self.carLayer.position.y); 40 CGPathAddCurveToPoint(path, NULL, endPoint.x/2, endPoint.y, endPoint.x/3, endPoint.y, endPoint.x, endPoint.y); 41 42 keyframeAnimation.path=path; 43 CGPathRelease(path); 44 45 [keyframeAnimation setValue:[NSValue valueWithCGPoint:endPoint] forKey:@"carRunAnimation"]; 46 47 return keyframeAnimation; 48 }
4.落叶动画.落叶通过CALayer绘制,UIVIew动画控制叶子生长动画,叶子下落动画通过关键帧动画.路径通过绘制二次贝塞尔曲线,叶子旋转动画通过基础动画CABasicAnimation
1 /*---------------------------------------------------------------------------------------*/ 2 //MARK:制作落叶Layer 3 -(void)makeLeafLayer{ 4 self.leafLayer = [[CALayer alloc]init]; 5 self.leafLayer.bounds = CGRectMake(0, 0, 30, 30); 6 self.leafLayer.position = CGPointMake(145, 145); 7 self.leafLayer.anchorPoint = CGPointMake(0.5, 0.6); //锚点,便于旋转动画 8 self.leafLayer.contents = (id)[UIImage imageNamed:@"落叶"].CGImage; 9 [self.view.layer addSublayer:self.leafLayer]; 10 } 11 //MARK:落叶生长动画 12 -(void)leafGrowAnimation{ 13 UIImageView * imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 1, 1)]; 14 imgView.image = [UIImage imageNamed:@"落叶"]; 15 imgView.layer.position = CGPointMake(145, 145); 16 [self.view addSubview:imgView]; 17 18 [UIView animateWithDuration:8.5 animations:^{ 19 imgView.frame = CGRectMake(0, 0, 30, 30); 20 imgView.layer.position = CGPointMake(145, 145); 21 } completion:^(BOOL finished) { 22 [imgView removeFromSuperview]; 23 [self leafGrowAnimation]; 24 }]; 25 26 } 27 //MARK: 落叶下落动画 28 -(void)fallLeafAnimation{ 29 //1.创建关键帧动画并设置动画属性 30 CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"]; 31 32 //2.设置路径 33 //绘制贝塞尔曲线 34 CGPathRef path=CGPathCreateMutable(); 35 CGPathMoveToPoint(path, NULL, self.leafLayer.position.x, self.leafLayer.position.y);//移动到起始点 36 CGPathAddCurveToPoint(path, NULL, 160, 190, -20, 150, 55,SCRCCEWH.height);//绘制二次贝塞尔曲线 37 38 keyframeAnimation.path=path;//设置path属性 39 CGPathRelease(path);//释放路径对象 40 keyframeAnimation.repeatCount = HUGE_VALF; //重复次数 41 keyframeAnimation.calculationMode = kCAAnimationCubicPaced; //动画的计算模式 42 keyframeAnimation.keyTimes = @[@0.0,@0.5,@0.7,@1.0]; //控制各个帧的时间 43 //设置其他属性 44 keyframeAnimation.duration=8.0; 45 keyframeAnimation.beginTime=CACurrentMediaTime()+1;//设置延迟执行 46 47 48 //3.添加动画到图层,添加动画后就会执行动画 49 [self.leafLayer addAnimation:keyframeAnimation forKey:@"fallLeaf"]; 50 } 51 //MARK:落叶旋转动画 52 -(void)leafOverturnAnimation{ 53 // 1.创建动画并制定动画属性 54 CABasicAnimation * basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 55 // 2.设置动画属性结束值 56 basicAnimation.toValue = [NSNumber numberWithFloat:M_PI_2*3]; 57 basicAnimation.repeatCount = HUGE_VALF; 58 // 3.设置动画属性的属性 59 basicAnimation.duration = 6.0; 60 basicAnimation.autoreverses = YES; //旋转后再旋转回原来的位置 61 62 // 4.添加动画到图层,注意key仅仅相当于给动画命名,以后获取动画可以采用该名字获取 63 [self.leafLayer addAnimation:basicAnimation forKey:@"leafOverturn"]; 64 }
4.娃娃摇摆动画,通过基础动画CABasicAnimation
1 //MARK: 晴天娃娃摇摆动画 2 -(void)sunChildAniamtion{ 3 UIImageView * imgView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 40, 80)]; 4 imgView.center = CGPointMake(SCRCCEWH.width/2, 0); 5 imgView.image = [UIImage imageNamed:@"娃娃"]; 6 imgView.layer.anchorPoint = CGPointMake(28.5/40, 16/80); 7 [self.view addSubview:imgView]; 8 9 id fromValue = [NSNumber numberWithFloat:-M_PI/ 10.0]; 10 id toValue = [NSNumber numberWithFloat:M_PI/ 10.0]; 11 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; 12 animation.duration = 1.5; // 持续时间 13 14 CAMediaTimingFunction *mediaTiming = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 15 animation.timingFunction = mediaTiming; 16 animation.repeatCount = HUGE_VALF; // 重复次数 17 animation.fromValue = fromValue;// 起始角度 18 animation.toValue = toValue; // 终止角度 19 animation.autoreverses = YES; 20 [imgView.layer addAnimation:animation forKey:nil]; 21 }
5.蝴蝶动画,震翅通过逐帧动画,路径通过关键帧动画的属性,设置关键帧实现
1 //得到蝴蝶当前图片 2 - (UIImage *)getImage:(BOOL)isNext{ 3 if(isNext){ 4 self.currentIndex = (self.currentIndex + 1)%IMAGE_COUNT; 5 }else{ 6 self.currentIndex = (self.currentIndex - 1 + IMAGE_COUNT)%IMAGE_COUNT; 7 } 8 NSString * imageName = [NSString stringWithFormat:@"%i.jpg",self.currentIndex]; 9 return [UIImage imageNamed:imageName]; 10 } 11 //蝴蝶飞舞动画 12 -(void)butterflyAnimation{ 13 self.butterflyLayer = [[CALayer alloc]init]; 14 self.butterflyLayer.bounds = CGRectMake(0, 0, 60, 60); 15 self.butterflyLayer.position = CGPointMake(SCRCCEWH.width, SCRCCEWH.height/2); 16 [self.view.layer addSublayer:self.butterflyLayer]; 17 18 self.images = [NSMutableArray array]; 19 for (int i = 1; i <= 2; i++){ 20 NSString * imageName = [NSString stringWithFormat:@"fly%i.png",i]; 21 UIImage * image = [UIImage imageNamed:imageName]; 22 [self.images addObject:image]; 23 } 24 25 // 定义时钟对象 26 CADisplayLink * displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(step)]; 27 // 添加时钟对象到主队列循环 28 [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 29 30 // 蝴蝶飞舞路径 31 [self butterflypath]; 32 } 33 //MARK:蝴蝶飞舞路径 34 -(void)butterflypath{ 35 //1.创建关键帧动画并设置动画属性 36 CAKeyframeAnimation *keyframeAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"]; 37 38 //2.设置关键帧 39 NSValue * key1 = [NSValue valueWithCGPoint:self.butterflyLayer.position]; //对于关键帧动画初始值不能省略 40 NSValue * key2 = [NSValue valueWithCGPoint:CGPointMake(80, 220)]; 41 NSValue * key3 = [NSValue valueWithCGPoint:CGPointMake(55, 200)]; 42 NSValue * key4 = [NSValue valueWithCGPoint:CGPointMake(60, 78)]; 43 NSValue * key5 = [NSValue valueWithCGPoint:CGPointMake(88, 0)]; 44 NSArray * values = @[key1,key2,key3,key4,key5]; 45 keyframeAnimation.values = values; 46 47 48 keyframeAnimation.repeatCount = HUGE_VALF; //重复次数 49 keyframeAnimation.calculationMode = kCAAnimationCubicPaced; //动画的计算模式 50 keyframeAnimation.keyTimes = @[@0.0,@0.5,@0.7,@1.0]; //控制各个帧的时间 51 //设置其他属性 52 keyframeAnimation.duration=15; 53 keyframeAnimation.beginTime=CACurrentMediaTime()+1;//设置延迟执行 54 //3.添加动画到图层,添加动画后就会执行动画 55 [self.butterflyLayer addAnimation:keyframeAnimation forKey:@"butterfly"]; 56 57 } 58 //MARK: 每次屏幕刷新就会执行一次此方法 59 -(void)step{ 60 //定义一个变量记录执行次数 61 static int s = 1; 62 if(++s % 25 == 0){ 63 UIImage * image = self.images[self.currentIndex]; 64 self.butterflyLayer.contents = (id)image.CGImage; 65 self.currentIndex = (self.currentIndex + 1)%IMAGE_COUNT; 66 } 67 68 }