Add animated image playback rate config. Allows user to control the animation speed

This commit is contained in:
DreamPiggy 2019-11-05 23:11:53 +08:00
parent f7821b8285
commit a6e515208b
4 changed files with 45 additions and 0 deletions

View File

@ -29,6 +29,14 @@
/// Total loop count for animated image rendering. Default is animated image's loop count.
@property (nonatomic, assign) NSUInteger totalLoopCount;
/// The animation playback rate. Default is 1.0
/// `1.0` means the normal speed.
/// `0.0` means stopping the animation.
/// `0.0-1.0` means the slow speed.
/// `> 1.0` means the fast speed.
/// `< 0.0` is not supported currently and stop animation. (may support reverse playback in the future)
@property (nonatomic, assign) double playRate;
/// Provide a max buffer size by bytes. This is used to adjust frame buffer count and can be useful when the decoding cost is expensive (such as Animated WebP software decoding). Default is 0.
/// `0` means automatically adjust by calculating current memory usage.
/// `1` means without any buffer cache, each of frames will be decoded and then be freed after rendering. (Lowest Memory and Highest CPU)

View File

@ -44,6 +44,7 @@
// Get the current frame and loop count.
self.totalLoopCount = provider.animatedImageLoopCount;
self.animatedProvider = provider;
self.playRate = 1.0;
#if SD_UIKIT
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
#endif
@ -232,12 +233,20 @@
// Then check if timestamp is reached
self.currentTime += duration;
NSTimeInterval currentDuration = [self.animatedProvider animatedImageDurationAtIndex:currentFrameIndex];
NSTimeInterval playRate = self.playRate;
if (playRate <= 0) {
// Does not support <= 0 play rate
[self stopPlaying];
return;
}
currentDuration = currentDuration / playRate;
if (self.currentTime < currentDuration) {
// Current frame timestamp not reached, return
return;
}
self.currentTime -= currentDuration;
NSTimeInterval nextDuration = [self.animatedProvider animatedImageDurationAtIndex:nextFrameIndex];
nextDuration = nextDuration / playRate;
if (self.currentTime > nextDuration) {
// Do not skip frame
self.currentTime = nextDuration;

View File

@ -43,6 +43,15 @@
This class override UIImageView's `animationRepeatCount` property on iOS, use this property as well.
*/
@property (nonatomic, assign) NSInteger animationRepeatCount;
/**
The animation playback rate. Default is 1.0.
`1.0` means the normal speed.
`0.0` means stopping the animation.
`0.0-1.0` means the slow speed.
`> 1.0` means the fast speed.
`< 0.0` is not supported currently and stop animation. (may support reverse playback in the future)
*/
@property (nonatomic, assign) double playRate;
/**
Provide a max buffer size by bytes. This is used to adjust frame buffer count and can be useful when the decoding cost is expensive (such as Animated WebP software decoding). Default is 0.
`0` means automatically adjust by calculating current memory usage.

View File

@ -18,6 +18,7 @@
@interface SDAnimatedImageView () <CALayerDelegate> {
BOOL _initFinished; // Extra flag to mark the `commonInit` is called
double _playRate;
}
@property (nonatomic, strong, readwrite) UIImage *currentFrame;
@ -92,6 +93,7 @@
// So the properties which rely on this order, should using lazy-evaluation or do extra check in `setImage:`.
self.shouldCustomLoopCount = NO;
self.shouldIncrementalLoad = YES;
self.playRate = 1.0;
#if SD_MAC
self.wantsLayer = YES;
#endif
@ -147,6 +149,9 @@
self.player.totalLoopCount = self.animationRepeatCount;
}
// Play Rate
self.player.playRate = self.playRate;
// Setup handler
@weakify(self);
self.player.animationFrameHandler = ^(NSUInteger index, UIImage * frame) {
@ -191,6 +196,20 @@
return self.player.runLoopMode;
}
- (void)setPlayRate:(double)playRate
{
_playRate = playRate;
self.player.playRate = playRate;
}
- (double)playRate
{
if (!_initFinished) {
return 1.0; // Defaults to 1.0
}
return _playRate;
}
- (BOOL)shouldIncrementalLoad
{
if (!_initFinished) {