iOS--Animation总结
UIKit框架中
1.UIImageView里的序列帧动画
-
将序列帧动画图片存入imageView.animationImages数组中
示例:
NSMutableArray * array = [NSMutableArray array];
for (int i = 1; i < 6; i++) {
//将图片存入数组
NSString * string = [NSString stringWithFormat:@"hehua0%d",i];
UIImage * image = [UIImage imageNamed:string];
[array addObject:image];
}
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
//设置动画图片
self.imageView.animationImages = array;
//动画时间
self.imageView.animationDuration = 1;
//动画播放重复次数,值为0时,无限循环
self.imageView.animationRepeatCount = 0;
//开始动画
[self.imageView startAnimating];
//结束动画
[self.imageView stopAnimating];
-
播放GIF动画
可为UIImageView添加类别来实现方法
如+ (UIImageView *)imageViewWithGIFFile:(NSString *)file frame:(CGRect)frame;
导入头文件<ImageIO/ImageIO.h>和<CoreText/CoreText.h>
/**
* ARC下需要手动管理内存的有(Core)
*CT开头,例如:CTRunRef
*CF开头,例如:CTFrameRef
*CG开头,例如:CGImageSourceRef
*/
@implementation UIImageView (GIF)
+ (UIImageView *)imageViewWithGIFFile:(NSString *)file frame:(CGRect)frame
{
UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
// 加载gif文件数据
NSData *gifData = [NSData dataWithContentsOfFile:file];
// GIF动画图片数组
NSMutableArray *frames = nil;
// 图像源引用
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)gifData, NULL);
// 动画时长
CGFloat animationTime = 0.f;
if (src) {
// 获取gif图片的帧数
size_t count = CGImageSourceGetCount(src);
// 实例化图片数组
frames = [NSMutableArray arrayWithCapacity:count];
for (size_t i = 0; i < count; i++) {
// 获取指定帧图像
CGImageRef image = CGImageSourceCreateImageAtIndex(src, i, NULL);
// 获取GIF动画时长
NSDictionary *properties = (__bridge NSDictionary *)CGImageSourceCopyPropertiesAtIndex(src, i, NULL);
NSDictionary *frameProperties = [properties objectForKey:(NSString *)kCGImagePropertyGIFDictionary];
NSNumber *delayTime = [frameProperties objectForKey:(NSString *)kCGImagePropertyGIFUnclampedDelayTime];
animationTime += [delayTime floatValue];
if (image) {
[frames addObject:[UIImage imageWithCGImage:image]];
CGImageRelease(image);
}
}
CFRelease(src);
}
[imageView setImage:[frames objectAtIndex:0]];
[imageView setBackgroundColor:[UIColor clearColor]];
[imageView setAnimationImages:frames];
[imageView setAnimationDuration:animationTime];
[imageView startAnimating];
return imageView;
}
2.UIView动画
-
简单动画
//开始动画
[UIView beginAnimations:@"自定义动画名称" context:nil];
//延迟2秒执行
//[UIView setAnimationDelay:2];
//设置动画时间
[UIView setAnimationDuration:1];
//设置动画代理
[UIView setAnimationDelegate:self];
//将要开始动画
[UIView setAnimationWillStartSelector:@selector(要开始动画时执行)];
//已经结束动画
[UIView setAnimationDidStopSelector:@selector(结束动画执行)];
//设置动画的速度变化
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
//设置重复次数
//[UIView setAnimationRepeatCount:3];
//动画的反转
//[UIView setAnimationRepeatAutoreverses:YES];
//设置UIView的位置变化,大小变化,透明度
// self.imageView.alpha = 0;
// self.testView.backgroundColor = [UIColor redColor];
//
// distantce += 20;
//
// self.testView.frame = CGRectMake(distantce, 0, 100, 100);
//拉伸
// self.testView.transform = CGAffineTransformMakeScale(1.5, 1.5);
//平移
// self.testView.transform = CGAffineTransformMakeTranslation(100, 100);
// self.testView.transform = CGAffineTransformTranslate(self.testView.transform, 20, 0);
//旋转
//self.testView.transform = CGAffineTransformMakeRotation(M_PI_2);
//self.testView.transform = CGAffineTransformRotate(self.testView.transform, M_PI_4/2);
//提交动画
[UIView commitAnimations];
-
转场动画
(1)在一个UIView上添加两个imageView,然后设置动画
[UIView beginAnimations:@"transition" context:nil];
[UIView setAnimationDuration:2];
//设置转场动画
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.contentView cache:YES];
[self.contentView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
[UIView commitAnimations];
(2)UIView block转场动画
secondView -> firstView
这个方法会作用于fromView的父视图,用于切换两个view,通过执行这个方法,会将formView从其父视图上移除,将toView重新粘在其父视图上,展现一个动画效果。
[UIView transitionFromView:self.secondView toView:self.firstView duration:2 options:UIViewAnimationOptionTransitionCurlUp completion:^(BOOL finished) {
}];
转场动画的block实现
[UIView transitionWithView:self.contentView duration:2 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
//1.该方法可以实现两个页面的来回切换
[self.contentView exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
//2.该方法只能实现一次转场动画
// [self.firstView removeFromSuperview];
// [self.contentView addSubview:self.secondView];
} completion:^(BOOL finished) {
}];
-
UIView的block动画
(1)简单block动画的实现
例1 图片的透明度变化动画
//Duration动画时间 animations里是要到达的状态,completion里是动画完成之后的代码块
[UIView animateWithDuration:1 animations:^{
self.imageView.alpha = 0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 animations:^{
self.imageView.alpha = 1;
} completion:^(BOOL finished) {
}];
}];
例2 图片的旋转变化动画
[UIView animateWithDuration:1 animations:^{
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, M_PI_2);
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 animations:^{
//下面是实现图片旋转一定度数后返回原位置的两种方法
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, -M_PI_2);
//CGAffineTransformIdentity恢复最初状态
// self.imageView.transform = CGAffineTransformIdentity;
}];
}];
例3 增加了动画延迟
[UIView animateWithDuration:1 delay:2 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.imageView.backgroundColor = [UIColor grayColor];
} completion:^(BOOL finished) {
}];
(2) 带弹性效果的动画
//Damping 弹力 0 ~ 1
//SpringVelocity 弹簧初速度
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:10 options:UIViewAnimationOptionCurveLinear animations:^{
self.imageView.frame = CGRectMake(200, 100, 100, 100);
} completion:^(BOOL finished) {
}];
(3)关键帧动画
[UIView animateKeyframesWithDuration:3.0 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1/6.0 animations:^{
self.imageView.backgroundColor = [UIColor redColor];
}];
[UIView addKeyframeWithRelativeStartTime:1/6.0 relativeDuration:3/6.0 animations:^{
self.imageView.backgroundColor = [UIColor blueColor];
}];
[UIView addKeyframeWithRelativeStartTime:4/6.0 relativeDuration:2/6.0 animations:^{
self.imageView.backgroundColor = [UIColor orangeColor];
}];
} completion:^(BOOL finished) {
}];
QuartzCore框架中
3.CALayer的隐式动画
-
什么时候使用CALayer,什么时候使用UIView?
当视图需要响应时使用UIView,仅作为展示使用CALayer.
隐式动画只存在于CALayer的子层上
CALayer * layer = [CALayer layer];
layer.backgroundColor = [UIColor greenColor].CGColor;
layer.frame = CGRectMake(100, 100, 100, 100);
[self.view.layer addSublayer:layer];
//当执行layer变化语句时,默认有动画,即隐式动画
_layer.frame = CGRectMake(100, 100, arc4random_uniform(100), arc4random_uniform(100));
4.核心动画Core Animation
?核心动画和UIView动画的区别
核心动画一切都是假象,并不会真实的改变图层的属性值,如果以后做动画的时候,不需要与用户交互,通常用核心动画(转场)
UIView动画必须通过修改属性的真实值,才有动画效果
CAAnimation是一个抽象类,mac,iOS 通用,遵循了CAMediaTiming协议和CAAction协议!我们不要直接使用CAAnimation类,而是使用其子类:
具体可看 http://www.henishuo.com/caanimation-indtroduce-in-detail/
-
CATransition:提供渐变效果,如推拉push效果,消退fade效果,揭开reveal效果
-
CAAnimationGroup:允许多个动画同时播放
-
CABasicAnimation: 提供了对单一动画的实现
-
CAKeyframeAnimation: 关键桢动画,可以定义动画路线
-
CAPropertyAnimation:属性动画,通常不直接使用,而是使用CABasicAnimation子类
-
动画路径:完整路径对照表:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreAnimation_guide/Key-ValueCodingExtensions/Key-ValueCodingExtensions.html
CAAnimation(父类) -> CAPropertyAnimation 属性动画 -> (CABasicAnimation 基础动画 ,CAKeyframeAnimation 关键帧动画)
CAAnimation -> CAAnimationGroup 动画组
-
CABasicAnimation基础动画
//创建基础动画
CABasicAnimation * basic = [CABasicAnimation animation];
//动画路径
basic.keyPath = @"position";
//绝对距离
//设置初始状态
// basic.fromValue = [NSValue valueWithCGPoint:CGPointMake(0, 0)];
//终止状态
// basic.toValue = [NSValue valueWithCGPoint:CGPointMake(300, 300)];
//动画距离(相对距离)
//basic.byValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
//动画的初始和结束的模式 fillMode和removedOnCompletion要配合使用
basic.fillMode = kCAFillModeForwards;// @"forwards";
//动画完成在layer中删除
basic.removedOnCompletion = NO;
//如果初始状态就是当前动画未执行的位置
//动画时间
basic.duration = 1;
//动画的速度变化 eg:kCAMediaTimingFunctionEaseIn越来越快
basic.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
//?
//animation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.5 :0 :0.9 :0.7];
//添加动画
[_animationView.layer addAnimation:basic forKey:@"basic"];
-
CAKeyframeAnimation 关键帧动画
//创建关键帧动画
CAKeyframeAnimation * keyframe = [CAKeyframeAnimation animation];
keyframe.keyPath = @"position.x";
//设置关键帧的位置
keyframe.values = @[@0,@10,@-10,@10,@0];
//设置关键帧的时间
keyframe.keyTimes = @[ @0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1 ];
//无需设置起始位置
keyframe.additive = YES;
//calculationMode设置加速度,kCAAnimationPaced保持恒定的加速度,如果设置calculationMode,keyTimes失效
keyframe.calculationMode = kCAAnimationPaced;
//设置时间
keyframe.duration = 0.5;
[_animationView.layer addAnimation:keyframe forKey:@"keyframe"];
利用贝塞尔
UIView * v = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 30, 30)];
v.backgroundColor = [UIColor grayColor];
[self.view addSubview:v];
UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(50, 50, 300, 300)];
//创建关键帧动画
CAKeyframeAnimation * keyframe = [CAKeyframeAnimation animation];
keyframe.keyPath = @"position";
keyframe.path = path.CGPath;
//设置时间
keyframe.duration = 2;
//重复次数
keyframe.repeatCount = HUGE_VALF; //MAXFLOAT;
[_animationView.layer addAnimation:keyframe forKey:@"keyframe"];
-
CAAnimationGroup动画组
CABasicAnimation * basic1 = [CABasicAnimation animation];
basic1.keyPath = @"transform.scale";
basic1.toValue = @(arc4random_uniform(5));
basic1.duration = 0.5;
basic1.removedOnCompletion = NO;
basic1.fillMode = @"forwards";
// [self.animationView.layer addAnimation:basic1 forKey:@"aaa"];
CABasicAnimation * basic2 = [CABasicAnimation animation];
basic2.keyPath = @"transform.rotation";
basic2.toValue = @(arc4random_uniform(M_PI));
basic2.duration = 0.5;
basic2.beginTime = 0.5;
// [self.animationView.layer addAnimation:basic2 forKey:nil];
CAAnimationGroup * group = [CAAnimationGroup animation];
group.duration = 1;
group.removedOnCompletion = NO;
group.fillMode = @"forwards";
group.animations = @[basic1,basic2];
[self.animationView.layer addAnimation:group forKey:nil];
-
CATransition过渡动画
设置视图变化时的动画效果
-
1.#define定义的常量
-
kCATransitionFade 交叉淡化过渡
-
kCATransitionMoveIn 新视图移到旧视图上面
-
kCATransitionPush 新视图把旧视图推出去
-
kCATransitionReveal 将旧视图移开,显示下面的新视图
-
-
2.用字符串表示
-
pageCurl 向上翻一页
-
pageUnCurl 向下翻一页
-
rippleEffect 滴水效果
-
suckEffect 收缩效果,如一块布被抽走
-
cube 立方体效果
-
oglFlip 上下翻转效果
-
CATransition * transition = [CATransition animation];
transition.type = @"suckEffect";
transition.subtype = @"fromLeft";
transition.duration = 2;
[self.imageView.layer addAnimation:transition forKey:nil];
-
另外介绍一下CADisplayLink
//CADisplayLink,selector每秒钟默认调用60次。
//CADisplayLink和NSTimer区别:CADisplayLink用来做绘图,重绘。NSTimer用于计时,重复调用。
//创建CADisplayLink
self.displaylink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleAction:)];
//调用次数 = 60 / frameInterval
// self.displaylink.frameInterval = 3;
//将CADisplayLink放入RunLoop里
[self.displaylink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
Facebook POP动画
- poping开源库
POP比较好的一点是保留了动画结束后的状态,通过block回调。使用POPAnimatableProperty 可以快速添加基本动画,也可以自定义属性动画。
---弹性动画---
- (void)spring{
POPSpringAnimation* framePOP = [POPSpringAnimation animationWithPropertyNamed:kPOPViewBackgroundColor];
framePOP.springSpeed = 10.f;
framePOP.springBounciness = 4.f;
framePOP.toValue = [UIColor greenColor];
[framePOP setCompletionBlock:^(POPAnimation * anim , BOOL finsih) {
if (finsih) {
NSLog(@"view.frame = %@",NSStringFromCGRect(view.frame));
}
}];
[view pop_addAnimation:framePOP forKey:@"go"];
}
---减缓动画——--
- (void)Decay{
POPDecayAnimation* decay = [POPDecayAnimation animationWithPropertyNamed:kPOPViewFrame];
// decay.toValue = [NSValue valueWithCGRect:CGRectMake(200, 400, 100, 100)];
decay.velocity = [NSValue valueWithCGRect:CGRectMake(200, 300, 100, 100)];
[view pop_addAnimation:decay forKey:@"go"];
}
---基本动画---
-(void)basic{
POPBasicAnimation* basicAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerCornerRadius];
basicAnimation.toValue = [NSNumber numberWithFloat:CGRectGetHeight(view.frame)/2.];
basicAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// basicAnimation.duration = 3.f;
[basicAnimation setCompletionBlock:^(POPAnimation * ani, BOOL fin) {
if (fin) {
NSLog(@"view.frame = %@",NSStringFromCGRect(view.frame));
// POPBasicAnimation* newBasic = [POPBasicAnimation easeInEaseOutAnimation];
// newBasic.property = [POPAnimatableProperty propertyWithName:kPOPLayerCornerRadius];
// newBasic.toValue = [NSNumber numberWithFloat:0];
// [view.layer pop_addAnimation:newBasic forKey:@"go"];
}
}];
[view.layer pop_addAnimation:basicAnimation forKey:@"frameChange"];
---组合动画---
-(void)group
{
view.transform = CGAffineTransformMakeRotation(M_PI_2/3);
POPBasicAnimation* spring = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
spring.beginTime = CACurrentMediaTime();
spring.duration = .4f;
spring.fromValue = [NSNumber numberWithFloat:-100.f];
spring.toValue = [NSNumber numberWithFloat:CGRectGetMinY(view.frame) + 80];
[spring setCompletionBlock:^(POPAnimation * ani, BOOL fin) {
}];
POPBasicAnimation* basic = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation];
basic.beginTime = CACurrentMediaTime();
basic.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
basic.toValue = [NSNumber numberWithFloat:-M_PI_4];
basic.duration = .4f;
POPBasicAnimation* rotation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerRotation];
rotation.beginTime = CACurrentMediaTime() + .4f;
rotation.toValue = [NSNumber numberWithFloat:0.f];
rotation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
rotation.duration = .25f;
POPBasicAnimation* donw = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerPositionY];
donw.beginTime = CACurrentMediaTime() + 0.4f;
donw.toValue = [NSNumber numberWithFloat:CGRectGetMinY(view.frame)];
donw.duration = .25f;
donw.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[view.layer pop_addAnimation:spring forKey:@"spring"];
[view.layer pop_addAnimation:basic forKey:@"basic"];
[view.layer pop_addAnimation:donw forKey:@"down"];
[view.layer pop_addAnimation:rotation forKey:@"rotation"];
}