CABasicAnimation 动画
import "ViewController.h"
import <QuartzCore/QuartzCore.h>
define View_Side 80
define Screen_Width 320
define Screen_Height 460
import "AnimationDelegate.h"
@interface ViewController ()<CAAnimationDelegate>
{
UIView *_demoView;
}
@end
@implementation ViewController
/**
- initialize the demoview.
*/
-
(void)initDemoView
{
_demoView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, View_Side, View_Side)];
_demoView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:_demoView];
} -
(void)viewDidLoad
{
[super viewDidLoad];
[self initDemoView];[self performSelector:@selector(starAnimationScale1) withObject:nil afterDelay:2.0f];
}
/*!
设定动画
属性 说明
duration 动画的时长
repeatCount 重复的次数。不停重复设置为 HUGE_VALF
repeatDuration 设置动画的时间。在该时间内动画一直执行,不计次数。
beginTime 指定动画开始的时间。从开始延迟几秒的话,设置为【CACurrentMediaTime() + 秒数】 的方式
timingFunction 设置动画的速度变化
autoreverses 动画结束时是否执行逆动画
fromValue 所改变属性的起始值
toValue 所改变属性的结束时的值
byValue 所改变属性相同起始值的改变量
removedOnCompletion 防止动画结束后回到初始状态 所以为了使动画结束之后layer保持结束状态,应将removedOnCompletion设置为NO
fillMode 防止动画结束后回到初始状态 该属性定义了你的动画在开始和结束时的动作。默认值是 kCAFillModeRemoved。
speed speed 改变动画的速度 可以直接设置动画上的speed属性,这样只有这个动画速度。
speed两点需注意的:
(1)如果设置动画时间为4s,speed设置为2,则动画只需2s即可执行完。
(2)如果同时设置了动画的speed和layer 的speed,则实际的speed为两者相乘。
*/
-(void)scaleopcity{
CABasicAnimation *animaiton = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animaiton.fromValue = @(M_PI_4);
animaiton.toValue = @(M_PI);
animaiton.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animaiton.autoreverses = NO;
animaiton.repeatCount = HUGE_VALF;
animaiton.beginTime = CACurrentMediaTime() + 1;
animaiton.delegate = self;//协议
animaiton.delegate = [[AnimationDelegate alloc]init];
// 防止动画结束后回到初始状态
animaiton.removedOnCompletion = NO;
animaiton.fillMode = kCAFillModeForwards;
/*!
kCAFillModeForwards kCAFillModeForwards 设置为该值,动画即使之后layer的状态将保持在动画的最后一帧,而removedOnCompletion的默认属性
值是 YES,所以为了使动画结束之后layer保持结束状态,应将removedOnCompletion设置为NO。
kCAFillModeBackwards kCAFillModeBackwards 设置为该值,将会立即执行动画的第一帧,不论是否设置了 beginTime属性。观察发现,设置该值,刚开
始视图不见,还不知道应用在哪里。
kCAFillModeBoth kCAFillModeBoth 该值是 kCAFillModeForwards 和 kCAFillModeBackwards的组合状态
kCAFillModeRemoved kCAFillModeRemoved 设置为该值,动画将在设置的 beginTime 开始执行(如没有设置beginTime属性,则动画立即执行),动
画执行完成后将会layer的改变恢复原状。
*/
/*
kCAMediaTimingFunctionLinear 传这个值,在整个动画时间内动画都是以一个相同的速度来改变。也就是匀速运动。
kCAMediaTimingFunctionEaseIn 使用该值,动画开始时会较慢,之后动画会加速。
kCAMediaTimingFunctionEaseOut 使用该值,动画在开始时会较快,之后动画速度减慢。
kCAMediaTimingFunctionEaseInEaseOut 使用该值,动画在开始和结束时速度较慢,中间时间段内速度较快。
kCAMediaTimingFunctionDefault
*/
//添加动画
[_demoView.layer addAnimation:animaiton forKey:@"Animation"];
}
//其实比较重要的是有多个动画的时候如何在代理方法中区分不同的动画
//方式一:
//如果我们添加动画的视图是全局变量,可使用该方法。
//添加动画时,我们使用了
//动画开始时
- (void)animationDidStart:(CAAnimation *)anim
{
if ([anim isEqual:[_demoView.layer animationForKey:@"Animation"]]) {
NSLog(@"动画组执行了");
}
}
//动画结束时
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
//方法中的flag参数表明了动画是自然结束还是被打断,比如调用了removeAnimationForKey:方法或removeAnimationForKey方法,flag为NO,如果是正常结束,flag为YES。
NSLog(@"结束了");
}
//方式二
//添加动画的视图是局部变量时,可使用该方法
//添加动画给动画设置key-value对
-(void)animationCustomDidStart{
// [positionAnima setValue:@"PositionAnima" forKey:@"AnimationKey"];
// [transformAnima setValue:@"TransformAnima" forKey:@"AnimationKey"];
}
//动画结束时
//- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
//{
// if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"PositionAnima"]) {
// NSLog(@"位置移动动画执行结束");
// }
// else if ([[anim valueForKey:@"AnimationKey"]isEqualToString:@"TransformAnima"]){
// NSLog(@"旋转动画执行结束");
// }
//}
//y上下跳
-(void)starAnimationScale{
CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"];
positionAnima.duration = 0.8;
positionAnima.fromValue = @(_demoView.center.y);
positionAnima.toValue = @(_demoView.center.y-30);
positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
positionAnima.repeatCount = HUGE_VALF;
positionAnima.repeatDuration = 2;
positionAnima.removedOnCompletion = NO;
positionAnima.fillMode = kCAFillModeForwards;
[_demoView.layer addAnimation:positionAnima forKey:@"AnimationMoveY"];
}
//centery 中心点旋转
-(void)starAnimationScale1{
CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"];
positionAnima.fromValue = @(_demoView.center.y);
positionAnima.toValue = @(_demoView.center.y-30);
positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
CABasicAnimation *transformAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
transformAnima.fromValue = @(0);
transformAnima.toValue = @(M_PI);
transformAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
CAAnimationGroup *animaGroup = [CAAnimationGroup animation];
animaGroup.duration = 2.0f;
animaGroup.fillMode = kCAFillModeForwards;
animaGroup.removedOnCompletion = NO;
animaGroup.animations = @[positionAnima,transformAnima];
[_demoView.layer addAnimation:animaGroup forKey:@"Animation"];
}
pragma mark - 我的旋转 顺时针
-(void)startAnimation{
CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];
rotationAnimation.duration = 5.0;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1000;
[_demoView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}
-(void)opacity{
// CABasicAnimation *animation = [self opacityForever_Animation:3.0];
CABasicAnimation *animation = [self scale:[NSNumber numberWithInt:1] orgin:[NSNumber numberWithInt:1] durTimes:3.3 Rep:3];
[_demoView.layer addAnimation:animation forKey:nil];
}
pragma mark =====缩放-=============
-(CABasicAnimation *)scale:(NSNumber *)Multiple orgin:(NSNumber *)orginMultiple durTimes:(float)time Rep:(float)repertTimes
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = Multiple;
animation.toValue = orginMultiple;
animation.autoreverses = YES;
animation.repeatCount = repertTimes;
animation.duration = time;//不设置时候的话,有一个默认的缩放时间.
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
return animation;
}
pragma mark ====旋转动画======
-(CABasicAnimation *)rotation:(float)dur degree:(float)degree direction:(int)direction repeatCount:(int)repeatCount
{
//第一个参数是旋转角度,后面三个参数形成一个围绕其旋转的向量,起点位置由UIView的center属性标识。
CATransform3D rotationTransform = CATransform3DMakeRotation(degree, 0, 0, direction);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:rotationTransform];
animation.duration = dur;
animation.autoreverses = NO;
animation.cumulative = NO;
animation.fillMode = kCAFillModeForwards;
animation.repeatCount = repeatCount;
return animation;
}
pragma mark === 永久闪烁的动画 ======
-(CABasicAnimation *)opacityForever_Animation:(float)time
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];//必须写opacity才行。
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:0.0f];//这是透明度。
animation.autoreverses = YES;
animation.duration = time;
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];///没有的话是均匀的动画。
return animation;
}
/**
- CABasicAnimation test
*/
-
(void)demoViewBasicAnimation
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];animation.fromValue = [NSValue valueWithCGPoint:CGPointMake(_demoView.center.x, _demoView.center.y)]; //可以省略...
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(270, 410)];
animation.duration = 3.0f;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; //动画速度设置
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = NO;[_demoView.layer addAnimation:animation forKey:nil];
}
/**
- CAKeyframeAnimation test
*/
-
(void)demoViewKeyframeAnimation
{
_demoView.layer.anchorPoint = CGPointMake(0.5, 0.0);
CAKeyframeAnimation *animaiton = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];NSArray *rotationVelues = @[@(M_PI_4), @(-M_PI_4), @(M_PI_4)];
animaiton.values = rotationVelues;
animaiton.duration = 3.0f;
animaiton.repeatCount = HUGE_VALF; // #define HUGE_VALF 1e50f[_demoView.layer addAnimation:animaiton forKey:nil];
}
/**
- The animation used Bezierpath
*/
-
(void)demoViewBezierPathAnimation
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:_demoView.center]; //一定要设置 不然底层的CGPath找不到起始点,将会崩溃
[path addCurveToPoint:CGPointMake(270, 410) controlPoint1:CGPointMake(0, 460) controlPoint2:CGPointMake(320, 0)]; //以左下角和右上角为控制点CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
animation.path = path.CGPath;
animation.duration = 3.0f;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;[_demoView.layer addAnimation:animation forKey:nil];
}
@end