版本記錄
| 版本號(hào) | 時(shí)間 |
|---|---|
| V1.0 | 2017.09.16 |
前言
app中好的炫的動(dòng)畫(huà)可以讓用戶耳目一新,為產(chǎn)品增色不少,關(guān)于動(dòng)畫(huà)的實(shí)現(xiàn)我們可以用基本動(dòng)畫(huà)、關(guān)鍵幀動(dòng)畫(huà)、序列幀動(dòng)畫(huà)以及基于CoreGraphic的動(dòng)畫(huà)等等,接下來(lái)這幾篇我就介紹下我可以想到的幾種動(dòng)畫(huà)繪制方法。具體Demo示例已開(kāi)源到Github —— 刀客傳奇,感興趣的可以看我寫(xiě)的另外幾篇。
1. 實(shí)現(xiàn)動(dòng)畫(huà)方式深度解析(一) —— 播放GIF動(dòng)畫(huà)(一)
FLAnimatedImage框架作者
上一篇我們介紹了播放GIF動(dòng)畫(huà)的幾種方式,其中特意提到使用FLAnimatedImage框架播放動(dòng)畫(huà),為了層次清晰,所以另外開(kāi)幾篇進(jìn)行單獨(dú)講解,這一篇我們就開(kāi)始講一下利用FLAnimatedImage播放GIF動(dòng)畫(huà)。
首先我們看一下作者。

最新的star統(tǒng)計(jì)數(shù)目是6k+,他們是四個(gè)人在維護(hù)這個(gè)框架。
基本介紹
FLAnimatedImage是一種高性能的iOS GiF動(dòng)畫(huà)引擎,主要體現(xiàn)在下面幾個(gè)方面。
- 以與桌面瀏覽器相當(dāng)?shù)牟シ潘俣韧瑫r(shí)播放多個(gè)GIF
- 可變的幀延遲
- 在有內(nèi)存方面壓力還是很好的運(yùn)行
- 在第一個(gè)回放循環(huán)中消除延遲或阻塞
- 以現(xiàn)代瀏覽器的方式解釋快速GIF的幀延遲
看一個(gè)示例

1. 安裝與使用
FLAnimatedImage是一個(gè)很好封裝的插件組件。 簡(jiǎn)單地將UIImageView實(shí)例替換為FLAnimatedImageView的實(shí)例,以獲得動(dòng)畫(huà)GIF支持。 沒(méi)有中央緩存或狀態(tài)來(lái)管理。
- 使用Cocoapods安裝管理
$ pod try FLAnimatedImage
把他加入到您的app,復(fù)制兩個(gè)類FLAnimatedImage.h/.m 和 FLAnimatedImageView.h/.m到您的xcode工程,或者通過(guò)Cocoapods命令行集成。
pod 'FLAnimatedImage', '~> 1.0'
- 使用Carthage
github "Flipboard/FLAnimatedImage"
在你的xcode中,#import "FLAnimatedImage.h",從一個(gè)Gif動(dòng)畫(huà)創(chuàng)建一個(gè)image,并展示它。
FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif"]]];
FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init];
imageView.animatedImage = image;
imageView.frame = CGRectMake(0.0, 0.0, 100.0, 100.0);
[self.view addSubview:imageView];
它兼容iOS6,并涉及到下面這些框架。
QuartzCoreImageIOMobileCoreServicesCoreGraphics
它能夠進(jìn)行細(xì)粒度日志記錄,可以在FLAnimatedImage上設(shè)置一個(gè)塊,當(dāng)通過(guò)調(diào)用方法+ setLogBlock:logLevel:時(shí),可以記錄發(fā)生的各種日志級(jí)別。 例如:
// Set up FLAnimatedImage logging.
[FLAnimatedImage setLogBlock:^(NSString *logString, FLLogLevel logLevel) {
// Using NSLog
NSLog(@"%@", logString);
// ...or CocoaLumberjackLogger only logging warnings and errors
if (logLevel == FLLogLevelError) {
DDLogError(@"%@", logString);
} else if (logLevel == FLLogLevelWarn) {
DDLogWarn(@"%@", logString);
}
} logLevel:FLLogLevelWarn];
框架結(jié)構(gòu)及API接口
下面我們就看一下該框架的框架結(jié)構(gòu)

大家可以看到,這個(gè)框架很輕量級(jí)??蚣艿墓ぷ髟砑傲鞒倘缦滤?。


接著我們看一下API接口
1. FLAnimatedImage.h
這里面包含了好幾個(gè)接口
@interface FLAnimatedImage : NSObject
@property (nonatomic, strong, readonly) UIImage *posterImage; // Guaranteed to be loaded; usually equivalent to `-imageLazilyCachedAtIndex:0`
@property (nonatomic, assign, readonly) CGSize size; // The `.posterImage`'s `.size`
@property (nonatomic, assign, readonly) NSUInteger loopCount; // 0 means repeating the animation indefinitely
@property (nonatomic, strong, readonly) NSDictionary *delayTimesForIndexes; // Of type `NSTimeInterval` boxed in `NSNumber`s
@property (nonatomic, assign, readonly) NSUInteger frameCount; // Number of valid frames; equal to `[.delayTimes count]`
@property (nonatomic, assign, readonly) NSUInteger frameCacheSizeCurrent; // Current size of intelligently chosen buffer window; can range in the interval [1..frameCount]
@property (nonatomic, assign) NSUInteger frameCacheSizeMax; // Allow to cap the cache size; 0 means no specific limit (default)
// Intended to be called from main thread synchronously; will return immediately.
// If the result isn't cached, will return `nil`; the caller should then pause playback, not increment frame counter and keep polling.
// After an initial loading time, depending on `frameCacheSize`, frames should be available immediately from the cache.
- (UIImage *)imageLazilyCachedAtIndex:(NSUInteger)index;
// Pass either a `UIImage` or an `FLAnimatedImage` and get back its size
+ (CGSize)sizeForImage:(id)image;
// On success, the initializers return an `FLAnimatedImage` with all fields initialized, on failure they return `nil` and an error will be logged.
- (instancetype)initWithAnimatedGIFData:(NSData *)data;
// Pass 0 for optimalFrameCacheSize to get the default, predrawing is enabled by default.
- (instancetype)initWithAnimatedGIFData:(NSData *)data optimalFrameCacheSize:(NSUInteger)optimalFrameCacheSize predrawingEnabled:(BOOL)isPredrawingEnabled NS_DESIGNATED_INITIALIZER;
+ (instancetype)animatedImageWithGIFData:(NSData *)data;
@property (nonatomic, strong, readonly) NSData *data; // The data the receiver was initialized with; read-only
@end
@interface FLAnimatedImage (Logging)
+ (void)setLogBlock:(void (^)(NSString *logString, FLLogLevel logLevel))logBlock logLevel:(FLLogLevel)logLevel;
+ (void)logStringFromBlock:(NSString *(^)(void))stringBlock withLevel:(FLLogLevel)level;
@end
@interface FLWeakProxy : NSProxy
+ (instancetype)weakProxyForObject:(id)targetObject;
@end
可以看見(jiàn),這里面有三個(gè)接口。
2. FLAnimatedImageView.h
看一下接口
#import <UIKit/UIKit.h>
@class FLAnimatedImage;
@protocol FLAnimatedImageViewDebugDelegate;
//
// An `FLAnimatedImageView` can take an `FLAnimatedImage` and plays it automatically when in view hierarchy and stops when removed.
// The animation can also be controlled with the `UIImageView` methods `-start/stop/isAnimating`.
// It is a fully compatible `UIImageView` subclass and can be used as a drop-in component to work with existing code paths expecting to display a `UIImage`.
// Under the hood it uses a `CADisplayLink` for playback, which can be inspected with `currentFrame` & `currentFrameIndex`.
//
@interface FLAnimatedImageView : UIImageView
// Setting `[UIImageView.image]` to a non-`nil` value clears out existing `animatedImage`.
// And vice versa, setting `animatedImage` will initially populate the `[UIImageView.image]` to its `posterImage` and then start animating and hold `currentFrame`.
@property (nonatomic, strong) FLAnimatedImage *animatedImage;
@property (nonatomic, copy) void(^loopCompletionBlock)(NSUInteger loopCountRemaining);
@property (nonatomic, strong, readonly) UIImage *currentFrame;
@property (nonatomic, assign, readonly) NSUInteger currentFrameIndex;
// The animation runloop mode. Enables playback during scrolling by allowing timer events (i.e. animation) with NSRunLoopCommonModes.
// To keep scrolling smooth on single-core devices such as iPhone 3GS/4 and iPod Touch 4th gen, the default run loop mode is NSDefaultRunLoopMode. Otherwise, the default is NSDefaultRunLoopMode.
@property (nonatomic, copy) NSString *runLoopMode;
@end
框架使用
下面就看一下該框架的基本使用,給一個(gè)我自己寫(xiě)的簡(jiǎn)單示例,直接看代碼。
#import "ViewController.h"
#import "FLAnimatedImageView.h"
#import "FLAnimatedImage.h"
@interface ViewController ()
@end
@implementation ViewController
#pragma mark - OVerride Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
//找到路徑文件
NSString *pathStr = [[NSBundle mainBundle] pathForResource:@"gifAnimation.gif" ofType:nil];
//將gif轉(zhuǎn)化為NSData數(shù)據(jù)
NSData *gifData = [NSData dataWithContentsOfFile:pathStr];
//數(shù)據(jù)顯示
FLAnimatedImage *image = [FLAnimatedImage animatedImageWithGIFData:gifData];
FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init];
imageView.animatedImage = image;
imageView.frame = CGRectMake(100.0, 200.0, 200.0, 200.0);
[self.view addSubview:imageView];
}
@end
下面看一下播放Gif圖的效果

這里只是一個(gè)簡(jiǎn)單的使用,只是給大家簡(jiǎn)單的展示。
后記
未完,待續(xù)~~~
