版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.09.16 |
前言
app中好的炫的動畫可以讓用戶耳目一新牲蜀,為產(chǎn)品增色不少蚂子,關(guān)于動畫的實現(xiàn)我們可以用基本動畫、關(guān)鍵幀動畫截亦、序列幀動畫以及基于CoreGraphic的動畫等等肮疗,接下來這幾篇我就介紹下我可以想到的幾種動畫繪制方法戚扳。具體Demo示例已開源到Github —— 刀客傳奇
ios中實現(xiàn)動畫的幾種方式
-
GIF
- 這個就很簡單了,讓UI給你個Gif圖族吻,你就直播播放就可以了帽借。具體播放可是使用UIWebView、UIImageView以及框架FLAnimatedImage
-
序列幀動畫
- 將動畫的每一幀都放在本地超歌,然后用
UIImageView
播放序列幀動畫砍艾。
- 將動畫的每一幀都放在本地超歌,然后用
-
系統(tǒng)的框架
CoreAnimation
- 里面可以做關(guān)鍵幀動畫,基本動畫等等巍举。下面會給出CoreAnimation的框架結(jié)構(gòu)圖脆荷,關(guān)于CoreAnimation框架我會分一大塊去講解。
-
系統(tǒng)自帶的
UIView
動畫- 直接在block里面實現(xiàn)位置大小改變等操作,并可設(shè)置動畫結(jié)束后的邏輯蜓谋,可做一些簡單的動畫梦皮。
-
第三方框架比如說
Lottie - ios
- Airbub開發(fā)的一個動畫框架,具體可以參考一種動畫框架Lottie的解析(三)—— 框架結(jié)構(gòu)桃焕。
-
第三方框架比如說Facebook Keyframes剑肯,
- 關(guān)鍵幀是Facebook構(gòu)建的一個非常好的新庫。 然而观堂,關(guān)鍵幀不支持一些
Lottie
的功能让网,如遮罩,修剪路徑等等师痕。
- 關(guān)鍵幀是Facebook構(gòu)建的一個非常好的新庫。 然而观堂,關(guān)鍵幀不支持一些
-
CoreGraphic
- 利用
CoreGraphic
和時間控制溃睹,可以自己自定義設(shè)計動畫,這種方式不是很好把握胰坟,但是還是可以實現(xiàn)的因篇。
- 利用
上面已經(jīng)列出來了,我認(rèn)為很全的做動畫的幾種方式或者思考方法笔横,不足的或者疏漏的希望大家提醒我竞滓,我好補全。
播放GIF動畫
播放GIF動畫的方式有很多狠裹,下面我就主要介紹幾種方式虽界。首先準(zhǔn)備了點GiF素材,如下涛菠。
1. 利用WebView播放GIF動畫
利用系統(tǒng)自帶的WebView就可以加載數(shù)據(jù)播放動畫莉御。主要思路步驟如下:
- 找到gif文件在bundle的地址路徑
- 利用NSData的類方法,將gif數(shù)據(jù)類型改變
- 利用UIWebView對象方法
loadData:
加載數(shù)據(jù)就可以播放了俗冻。
具體代碼如下所示:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0.0, 0.0, 375, 667)];
webView.scalesPageToFit = YES;
webView.opaque = NO;
[self.view addSubview:webView];
//找到路徑文件
NSString *pathStr = [[NSBundle mainBundle] pathForResource:@"gifAnimation.gif" ofType:nil];
//將gif轉(zhuǎn)化為NSData數(shù)據(jù)
NSData *gifData = [NSData dataWithContentsOfFile:pathStr];
//將gifData給WebView進行播放
[webView loadData:gifData MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];
}
@end
下面看一下播放效果
可見可以正常播放礁叔,具體界面適配問題就不說了,能播放就可以迄薄。
2. 利用UIImageView和ImageIO框架播放
具體思路就是將gif轉(zhuǎn)化為多張靜態(tài)png圖片琅关,然后利用UIImageView播放。需要借助框架#import <ImageIO/ImageIO.h>
里面的接口實現(xiàn)讥蔽。
下面我們就看一下代碼
#import "ViewController.h"
#import <ImageIO/ImageIO.h>
@interface ViewController ()
@end
@implementation ViewController
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
//gif URL路徑
NSURL *gifURL = [[NSBundle mainBundle] URLForResource:@"gifAnimation" withExtension:@"gif"];
//gif轉(zhuǎn)圖片
CGImageSourceRef gifSource = CGImageSourceCreateWithURL((CFURLRef)gifURL, NULL);
//圖片個數(shù)
size_t frameCount = CGImageSourceGetCount(gifSource);
//將CGImage轉(zhuǎn)化為UIImage涣易,并存儲在數(shù)組里面
NSMutableArray *frameArrM = [NSMutableArray array];
for (size_t i = 0; i < frameCount; i ++) {
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
UIImage *image = [UIImage imageWithCGImage:imageRef];
[frameArrM addObject:image];
CGImageRelease(imageRef);
}
//動畫顯示
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.frame];
[self.view addSubview:imageView];
imageView.animationImages = [frameArrM copy];
imageView.animationDuration = 1/10;
[imageView startAnimating];
}
@end
下面看一下效果驗證。
UIImageView
播放是通過定時器來控制圖片模擬動畫的冶伞,它們控制的楨速是固定的新症。如果設(shè)置的模擬楨速跟gif本身的楨速相近的話倒沒什么,如果楨速相差過大就會產(chǎn)生卡頓或者快進的視覺效果响禽。
3. SDWebImage
這個網(wǎng)絡(luò)圖片加載框架徒爹,大家都很清楚了荚醒,和gif相關(guān)的類只有UIImage+GIF
,它是UIImage的一個分類隆嗅。
看一下這個分類的接口
#import "SDWebImageCompat.h"
@interface UIImage (GIF)
/**
* Compatibility method - creates an animated UIImage from an NSData, it will only contain the 1st frame image
*/
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data;
/**
* Checks if an UIImage instance is a GIF. Will use the `images` array
*/
- (BOOL)isGIF;
@end
這個接口只提供了兩個方法:
-
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data;
界阁,這個方法只會返回第一幀。 -
- (BOOL)isGIF;
判斷UIImage實例是否是Gif胖喳。
下面看一下具體實現(xiàn)
#import "UIImage+GIF.h"
#import <ImageIO/ImageIO.h>
#import "objc/runtime.h"
#import "NSImage+WebCache.h"
@implementation UIImage (GIF)
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data {
if (!data) {
return nil;
}
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
size_t count = CGImageSourceGetCount(source);
UIImage *staticImage;
if (count <= 1) {
staticImage = [[UIImage alloc] initWithData:data];
} else {
// we will only retrieve the 1st frame. the full GIF support is available via the FLAnimatedImageView category.
// this here is only code to allow drawing animated images as static ones
#if SD_WATCH
CGFloat scale = 1;
scale = [WKInterfaceDevice currentDevice].screenScale;
#elif SD_UIKIT
CGFloat scale = 1;
scale = [UIScreen mainScreen].scale;
#endif
CGImageRef CGImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
#if SD_UIKIT || SD_WATCH
UIImage *frameImage = [UIImage imageWithCGImage:CGImage scale:scale orientation:UIImageOrientationUp];
staticImage = [UIImage animatedImageWithImages:@[frameImage] duration:0.0f];
#elif SD_MAC
staticImage = [[UIImage alloc] initWithCGImage:CGImage size:NSZeroSize];
#endif
CGImageRelease(CGImage);
}
CFRelease(source);
return staticImage;
}
- (BOOL)isGIF {
return (self.images != nil);
}
@end
調(diào)用上面的接口只能返回第一幀泡躯。所以不可以的,我查了下資料禀晓,SDWebImage以前是可以的精续,但是后來更改了接口就不可以了坝锰。
下面我們就驗證這個問題粹懒,看一下代碼
#import "ViewController.h"
#import "SDWebImage/UIImage+GIF.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//找到路徑文件
NSString *pathStr = [[NSBundle mainBundle] pathForResource:@"gifAnimation.gif" ofType:nil];
//將gif轉(zhuǎn)化為NSData數(shù)據(jù)
NSData *gifData = [NSData dataWithContentsOfFile:pathStr];
UIImage *image = [UIImage sd_animatedGIFWithData:gifData];
//顯示
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.frame];
[self.view addSubview:imageView];
imageView.image = image;
}
@end
運行起來就會發(fā)現(xiàn),只是一張靜態(tài)的圖片顷级,并不能播放GIF凫乖。為什么會這樣呢?
看一下UIImage+GIF.m
中count > 1
時給的提示:
//we will only retrieve the 1st frame. the full GIF support is available via the FLAnimatedImageView category.
// this here is only code to allow drawing animated images as static ones
意思就是讓我們使用FLAnimatedImageView
這個框架和接口播放GIF弓颈。
所以帽芽,利用SDWebImage框架播放GIF是行不通的了。
4. FLAnimatedImage
FLAnimatedImage
是由Flipboard
開源的iOS平臺上播放GIF動畫的一個優(yōu)秀解決方案翔冀,在內(nèi)存占用和播放體驗都有不錯的表現(xiàn)导街。
這里就簡單的提一下,詳細(xì)的說明放在下篇纤子,避免內(nèi)容混雜搬瑰,保持邏輯的清晰性,希望大家持續(xù)關(guān)注我控硼。
后記
未完泽论,待續(xù)~~