001-显示层动画
一、初级动画效果
1.基本思路
UIView的显示层初级动画就是通过修改UIView的各种属性来实现的
2.动画常用属性&动画回调方法

3.代码实例
1)位置动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(center) _aView.center = CGPointMake(300, 600); // 提交动画 [UIView commitAnimations];
2)形状动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(bounds) _aView.bounds = CGRectMake(0, 0, 200, 200); // 提交动画 [UIView commitAnimations];
3)位置+形状动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(frame) _aView.frame = CGRectMake(100, 400, 200, 200); // 提交动画 [UIView commitAnimations];
4)淡入淡出动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(alpha) _aView.alpha = 1; // 提交动画 [UIView commitAnimations];
5)颜色渐变动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(backgroundColor) _aView.backgroundColor = [UIColor blueColor]; // 提交动画 [UIView commitAnimations];
6)缩放动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(transform) _aView.transform = CGAffineTransformMakeScale(2.0, 3.0); // 提交动画 [UIView commitAnimations];
7)旋转动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(transform) _aView.transform = CGAffineTransformMakeRotation(M_PI_4); // 提交动画 [UIView commitAnimations];
8)位移动画
// 开始动画 [UIView beginAnimations:nil context:nil]; // 设置动画属性 [UIView setAnimationDuration:1.0]; // 修改属性(transform) _aView.transform = CGAffineTransformMakeTranslation(150, 300); // 提交动画 [UIView commitAnimations];
二、关键帧动画
1.方法解读


2.代码实例
// 关键帧动画 [UIView animateKeyframesWithDuration:4 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{ // 添加关键帧动画 // 第一帧:动画从0s开始,持续整个动画周期(4s)的1/2时间(2s) [UIView addKeyframeWithRelativeStartTime:0 relativeDuration:1.0 / 2.0 animations:^{ // 改变动画属性 _imageView.frame = CGRectMake(200, 100, 60, 60); }]; // 第二帧:动画从整个动画周期(4s)的1/2时间(2s)开始,持续整个动画周期(4s)的1/2时间(2s) [UIView addKeyframeWithRelativeStartTime:1.0 / 2.0 relativeDuration:1.0 / 2.0 animations:^{ // 改变动画属性 _imageView.frame = CGRectMake(300, 300, 90, 90); }]; } completion:nil];
三、逐帧动画
1.基于NSTimer的逐帧动画
1)原理
利用定时器NSTimer去定时更换每一帧的图片;一般用于逐帧动画时间间隔比较长的时候
2)实例代码

2.基于CADisplayLink的逐帧动画
1)原理
利用定时器NSTimer去定时更换每一帧的图片;一般用于逐帧动画时间间隔比较短(超过每秒60帧)的时候,或者要求播放帧率之间间隔比较均匀
2)CADisplayLink & NSTimer的区别
iOS设备的屏幕刷帧频率默认是60Hz(即1s刷帧60次),而CADisplayLink默认的刷帧频率刚好与之保持一致,因此CADisplayLink的精度特别高
3)代码实例
#pragma mark - 界面 - (void)initUI { // imageView _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 300, 90, 90)]; _imageView.image = [UIImage imageNamed:@"image_0"]; _imageView.contentMode = UIViewContentModeScaleAspectFit; [self.view addSubview:_imageView]; // 定义CADisplayLink _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(refreshImageView)]; _displayLink.frameInterval = 1; [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; _index = 0; } #pragma mark - CADisplayLink事件 - (void)refreshImageView { _imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"image_%d", _index]]; _index++; if (_index == 12) { [_displayLink invalidate]; _displayLink = nil; } }
3.基于draw方法的逐帧动画
1)draw方法
a.当创建一个新的UIView时,其自动生成了一个draw()方法,且此方法可以被重写
b. draw方法一般什么时候调用:
①使用addSubview会触发layoutSubviews
②更新view的frame属性会触发layoutSubviews
③直接调用setLayoutSubviews方法会触发layoutSubviews
2)代码实例
// ViewController.m文件 #pragma mark - 界面 - (void)initUI { // 自定义bView(待绘制的view) _bView = [[LDView alloc] initWithFrame:self.view.bounds]; _bView.backgroundColor = [UIColor whiteColor]; _radius = 0; [self.view addSubview:_bView]; // 动画btn UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem]; btn.frame = CGRectMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height - 40, 100, 30); [btn setTitle:@"动画" forState:UIControlStateNormal]; [btn setTitle:@"停止动画" forState:UIControlStateSelected]; [btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; } #pragma mark - 点击事件 - (void)btnClick:(UIButton *)sender { sender.selected = !sender.isSelected; if (sender.isSelected) { // 定义定时器 _timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(refreshImageView) userInfo:nil repeats:YES]; } else { [_timer invalidate]; _timer = nil; _radius = 0; } } #pragma mark - CADisplayLink事件 - (void)refreshImageView { _bView.radius = _radius++; } // LDView.h文件 #import <UIKit/UIKit.h> @interface LDView : UIView #pragma mark - 属性 @property (nonatomic, assign) CGFloat radius; @end // LDView.m文件 #import "LDView.h" @implementation LDView #pragma mark - 属性的setter方法 - (void)setRadius:(CGFloat)radius { _radius = radius; // 重新绘制(调用drawRect:方法) [self setNeedsDisplay]; } #pragma mark - 重写 - (void)drawRect:(CGRect)rect { // 获取上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 绘制圆 CGContextAddArc(ctx, self.bounds.size.width / 2.0, self.bounds.size.height / 2.0, self.radius, 0, M_PI * 2, NO); // 渲染 CGContextFillPath(ctx); }
四、GIF动画
1.GIF分解单帧图片
1)GIF图片分解过程
①本地读取GIF图片,将其转换成NSData类型
②将NSData作为ImageIO模块的输入
③获取ImageIO的输出数据:UIImage
④将获取的UIImage数据存储为JPG或者PNG格式保存到本地
2)代码实例
#pragma mark - GIF分解单帧图片 - (void)resolveGIF { // 1.本地读取GIF图片,将其转换成NSData类型 NSString *gifName = [[NSBundle mainBundle] pathForResource:@"53c380a7a2ed8" ofType:@"gif"]; NSData *gifData = [NSData dataWithContentsOfFile:gifName]; // 2.将NSData作为ImageIO模块的输入 CGImageSourceRef gifDataSourceRef = CGImageSourceCreateWithData((CFDataRef)gifData, nil); NSInteger gifDataCount = CGImageSourceGetCount(gifDataSourceRef); for (NSInteger i = 0; i < gifDataCount - 1; i++) { CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifDataSourceRef, i, nil); // 3.获取ImageIO的输出数据:UIImage UIImage *image = [UIImage imageWithCGImage:imageRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]; // 4.将获取的UIImage数据存储为JPG或者PNG格式保存到本地 NSData *imageData = UIImagePNGRepresentation(image); NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:[NSString stringWithFormat:@"%ld.png", i]]; NSError *error = nil; [imageData writeToFile:filePath options:NSDataWritingAtomic error:&error]; if (!error) { NSLog(@"第%ld张图片保存成功!", i); } else { NSLog(@"第%ld张图片保存失败!", i); } } }
2.单帧图片合成GIF
1)合成GIF的过程
①加载待处理的n张图片原始数据源
②在Document目录下构建GIF文件
③循环为GIF图像对象添加每一帧元素
④设置GIF文件属性,利用ImageIO编码GIF文件
2)代码实例
#pragma mark - 单帧图片合成GIF - (void)compoundGIF { // 1.加载待处理的n张图片原始数据源 NSMutableArray *images = [NSMutableArray array]; for (NSInteger i = 0; i < 30; i++) { NSString *imageName = [NSString stringWithFormat:@"%ld.png", i]; UIImage *image = [UIImage imageNamed:imageName]; [images addObject:image]; } // 2.在Document目录下构建GIF文件 NSString *gifPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"hudie.gif"]; CFURLRef gifURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)gifPath, kCFURLPOSIXPathStyle, NO); CGImageDestinationRef imageDestinationRef = CGImageDestinationCreateWithURL(gifURL, (CFStringRef)@"com.compuserve.gif", images.count, nil); // 3.循环为GIF图像对象添加每一帧元素 // 设置每帧图片之间的间隔 NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:0.2f] forKey:(NSString *)kCGImagePropertyGIFDelayTime] forKey:(NSString *)kCGImagePropertyGIFDictionary]; // 循环为GIF图像对象添加每一帧元素 for (UIImage *image in images) { CGImageDestinationAddImage(imageDestinationRef, image.CGImage, (CFDictionaryRef)properties); } // 4.设置GIF文件属性,利用ImageIO编码GIF文件 NSMutableDictionary *dic = [NSMutableDictionary dictionary]; // 设置图片彩色空间格式 [dic setValue:(NSString *)kCGImagePropertyColorModelRGB forKey:(NSString *)kCGImagePropertyColorModel]; // 设置图片的颜色深度 [dic setValue:@16 forKey:(NSString *)kCGImagePropertyDepth]; // 设置图片的GIF执行次数 [dic setValue:@1 forKey:(NSString *)kCGImagePropertyGIFLoopCount]; NSDictionary *propertyGIFDictionary = [NSDictionary dictionaryWithObject:dic forKey:(NSString *)kCGImagePropertyGIFDictionary]; CGImageDestinationSetProperties(imageDestinationRef, (CFDictionaryRef)propertyGIFDictionary); // 完成GIF的Destination目标文件构建 CGImageDestinationFinalize(imageDestinationRef); }
3.GIF图像展示
1)原理
iOS原生的其实是不支持直接显示GIF图片,但是我们知道:GIF其实就是一帧帧的单帧图片构成,所以我们可以先对GIF分解,接下来再去进行多图片显示
GIF展示步骤:
①GIF分解
②进行多图片显示
2)代码实例
#pragma mark - GIF图像展示 - (void)showGIF { // 1.GIF分解单帧图片 NSMutableArray *images = [NSMutableArray array]; // 本地读取GIF图片,将其转换成NSData类型 NSString *gifName = [[NSBundle mainBundle] pathForResource:@"53c380a7a2ed8" ofType:@"gif"]; NSData *gifData = [NSData dataWithContentsOfFile:gifName]; // 将NSData作为ImageIO模块的输入 CGImageSourceRef gifDataSourceRef = CGImageSourceCreateWithData((CFDataRef)gifData, nil); NSInteger gifDataCount = CGImageSourceGetCount(gifDataSourceRef); for (NSInteger i = 0; i < gifDataCount - 1; i++) { CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifDataSourceRef, i, nil); // 获取ImageIO的输出数据:UIImage UIImage *image = [UIImage imageWithCGImage:imageRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]; [images addObject:image]; } // 2.借助UIImageView展示单帧图片 UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; imageView.contentMode = UIViewContentModeCenter; [self.view addSubview:imageView]; // 设置图片数组 imageView.animationImages = images; // 设置总时长 imageView.animationDuration = 5; // 设置展示次数 imageView.animationRepeatCount = 1; [imageView startAnimating]; }

浙公网安备 33010602011771号