Fix for Play logic and render group bug

This commit is contained in:
brandon_withrow 2017-08-14 16:59:04 -07:00
parent e2365eead5
commit 9434c0ef1d
10 changed files with 161 additions and 127 deletions

View File

@ -1,5 +1,5 @@
PODS:
- lottie-ios (2.0.2)
- lottie-ios (2.0.3)
DEPENDENCIES:
- lottie-ios (from `../`)
@ -9,7 +9,7 @@ EXTERNAL SOURCES:
:path: "../"
SPEC CHECKSUMS:
lottie-ios: c9ffa6f63af639e79eb45087c417974cb4435956
lottie-ios: 445f77c7f661f95587e49095a1ac7de43f0da896
PODFILE CHECKSUM: fdbd59f361db8744871f0e9a0b3f94e0b7b8ca6b

View File

@ -1,6 +1,6 @@
{
"name": "lottie-ios",
"version": "2.0.2",
"version": "2.0.3",
"summary": "Used to natively render vector animations exported from After Effects.",
"description": "Lottie is a mobile library for Android and iOS that parses Adobe After Effects animations exported as json with bodymovin and renders the vector animations natively on mobile and through React Native!\n\nFor the first time, designers can create and ship beautiful animations without an enginineer painstakingly recreating it be hand. Since the animation is backed by JSON they are extremely small in size but can be large in complexity! Animations can be played, resized, looped, sped up, slowed down, and even interactively scrubbed.",
"homepage": "https://github.com/airbnb/lottie-ios",
@ -13,7 +13,7 @@
},
"source": {
"git": "https://github.com/airbnb/lottie-ios.git",
"tag": "2.0.2"
"tag": "2.0.3"
},
"platforms": {
"ios": "8.0",

View File

@ -1,5 +1,5 @@
PODS:
- lottie-ios (2.0.2)
- lottie-ios (2.0.3)
DEPENDENCIES:
- lottie-ios (from `../`)
@ -9,7 +9,7 @@ EXTERNAL SOURCES:
:path: "../"
SPEC CHECKSUMS:
lottie-ios: c9ffa6f63af639e79eb45087c417974cb4435956
lottie-ios: 445f77c7f661f95587e49095a1ac7de43f0da896
PODFILE CHECKSUM: fdbd59f361db8744871f0e9a0b3f94e0b7b8ca6b

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.2</string>
<string>2.0.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.2</string>
<string>2.0.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>

View File

@ -83,7 +83,6 @@
FA1F5A951E42B25500FF36BF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FA1F5A941E42B25500FF36BF /* ViewController.m */; };
FA1F5A971E42B25500FF36BF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FA1F5A961E42B25500FF36BF /* Assets.xcassets */; };
FA1F5A9A1E42B25500FF36BF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FA1F5A981E42B25500FF36BF /* Main.storyboard */; };
FAFA304C27E35A5B877B245D /* Pods_Lottie_Example_MacOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AC7587B24F90B40ADD0CEA8C /* Pods_Lottie_Example_MacOS.framework */; };
FC6DFE4EE48E30E0517FE2B2 /* Pods_Lottie_Viewer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CED53248BEFE3C87F0FE12C7 /* Pods_Lottie_Viewer.framework */; };
/* End PBXBuildFile section */
@ -233,7 +232,6 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FAFA304C27E35A5B877B245D /* Pods_Lottie_Example_MacOS.framework in Frameworks */,
FC6DFE4EE48E30E0517FE2B2 /* Pods_Lottie_Viewer.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -17,10 +17,14 @@
@implementation LOTAnimationView {
CABasicAnimation *_playAnimation;
LOTCompositionContainer *_compContainer;
NSNumber *_playRangeStartFrame;
NSNumber *_playRangeEndFrame;
CGFloat _playRangeStartProgress;
CGFloat _playRangeEndProgress;
NSBundle *_bundle;
}
# pragma mark - Initializers
# pragma mark - Convenience Initializers
+ (nonnull instancetype)animationNamed:(nonnull NSString *)animationName {
return [self animationNamed:animationName inBundle:[NSBundle mainBundle]];
@ -85,6 +89,8 @@
return [[LOTAnimationView alloc] initWithModel:nil inBundle:nil];
}
# pragma mark - Initializers
- (instancetype)initWithContentsOfURL:(NSURL *)url {
self = [super initWithFrame:CGRectZero];
if (self) {
@ -152,11 +158,10 @@
_animationProgress = 0;
_loopAnimation = NO;
_autoReverseAnimation = NO;
}
- (void)setSceneModel:(LOTComposition *)sceneModel {
_sceneModel = sceneModel;
[self _setupWithSceneModel:sceneModel];
_playRangeEndFrame = nil;
_playRangeStartFrame = nil;
_playRangeEndProgress = 0;
_playRangeStartProgress = 0;
}
- (void)_setupWithSceneModel:(LOTComposition *)model {
@ -182,19 +187,71 @@
- (void)_restoreState {
if (_isAnimationPlaying) {
_isAnimationPlaying = NO;
[self playWithCompletion:self.completionBlock];
if (_playRangeStartFrame && _playRangeEndProgress) {
[self playFromFrame:_playRangeStartFrame toFrame:_playRangeEndFrame withCompletion:self.completionBlock];
} else if (_playRangeEndProgress != _playRangeStartProgress) {
[self playFromProgress:_playRangeStartProgress toProgress:_playRangeEndProgress withCompletion:self.completionBlock];
} else {
[self playWithCompletion:self.completionBlock];
}
} else {
self.animationProgress = _animationProgress;
}
}
# pragma mark - External Methods
- (void)_removeCurrentAnimationIfNecessary {
_playAnimation.speed = 0;
_isAnimationPlaying = NO;
_playAnimation.delegate = nil;
[_compContainer removeAllAnimations];
_playAnimation = nil;
}
- (CGFloat)_progressForFrame:(NSNumber *)frame {
if (!_sceneModel) {
return 0;
}
return ((frame.floatValue - _sceneModel.startFrame.floatValue) / (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue));
}
- (NSNumber *)_frameForProgress:(CGFloat)progress {
if (!_sceneModel) {
return @0;
}
return @(((_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue) * progress) + _sceneModel.startFrame.floatValue);
}
# pragma mark - Completion Block
- (void)_callCompletionIfNecessary:(BOOL)complete {
if (self.completionBlock) {
self.completionBlock(complete);
self.completionBlock = nil;
}
}
# pragma mark - External Methods - Model
- (void)setSceneModel:(LOTComposition *)sceneModel {
[self _setupWithSceneModel:sceneModel];
}
# pragma mark - External Methods - Play Control
- (void)play {
if (!_sceneModel) {
_isAnimationPlaying = YES;
return;
}
[self playFromFrame:_sceneModel.startFrame toFrame:_sceneModel.endFrame withCompletion:nil];
}
- (void)playWithCompletion:(LOTAnimationCompletionBlock)completion {
if (!_sceneModel) {
_isAnimationPlaying = YES;
self.completionBlock = completion;
return;
}
[self playFromFrame:_sceneModel.startFrame toFrame:_sceneModel.endFrame withCompletion:completion];
}
@ -204,10 +261,17 @@
- (void)playFromProgress:(CGFloat)fromStartProgress
toProgress:(CGFloat)toEndProgress
withCompletion:(nullable LOTAnimationCompletionBlock)completion{
CGFloat startFrame = ((_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue) * fromStartProgress) + _sceneModel.startFrame.floatValue;
CGFloat endFrame = ((_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue) * toEndProgress) + _sceneModel.startFrame.floatValue;
[self playFromFrame:@(startFrame) toFrame:@(endFrame) withCompletion:completion];
withCompletion:(nullable LOTAnimationCompletionBlock)completion {
if (!_sceneModel) {
_isAnimationPlaying = YES;
self.completionBlock = completion;
_playRangeStartProgress = fromStartProgress;
_playRangeEndProgress = toEndProgress;
return;
}
[self playFromFrame:[self _frameForProgress:fromStartProgress]
toFrame:[self _frameForProgress:toEndProgress]
withCompletion:completion];
}
- (void)playToFrame:(nonnull NSNumber *)toFrame
@ -221,13 +285,23 @@
if (_isAnimationPlaying) {
return;
}
_playRangeStartFrame = fromStartFrame;
_playRangeEndFrame = toEndFrame;
if (completion) {
self.completionBlock = completion;
}
if (!_sceneModel) {
_isAnimationPlaying = YES;
return;
}
if (_animationProgress == 1) {
_animationProgress = 0;
NSNumber *currentFrame = [self _frameForProgress:_animationProgress];
currentFrame = @(MAX(MIN(currentFrame.floatValue, toEndFrame.floatValue), fromStartFrame.floatValue));
if (currentFrame.floatValue == toEndFrame.floatValue) {
currentFrame = fromStartFrame;
}
_animationProgress = [self _progressForFrame:currentFrame];
NSTimeInterval offset = MAX(0, (_animationProgress * (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue)) - fromStartFrame.floatValue) / _sceneModel.framerate.floatValue;
NSTimeInterval duration = ((toEndFrame.floatValue - fromStartFrame.floatValue) / _sceneModel.framerate.floatValue);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"currentFrame"];
@ -240,66 +314,81 @@
animation.autoreverses = _autoReverseAnimation;
animation.delegate = self;
animation.removedOnCompletion = NO;
if (completion) {
self.completionBlock = completion;
}
_playAnimation = animation;
_playAnimation.beginTime = CACurrentMediaTime() - offset;
[_compContainer addAnimation:animation forKey:@"play"];
_isAnimationPlaying = YES;
}
- (void)stop {
self.animationProgress = 0;
}
#pragma mark - Other Time Controls
- (void)pause {
if (!_sceneModel) {
- (void)stop {
if (!_sceneModel ||
!_isAnimationPlaying) {
_isAnimationPlaying = NO;
return;
}
[self setProgressWithFrame:_sceneModel.startFrame callCompletionIfNecessary:YES];
}
- (void)pause {
if (!_sceneModel ||
!_isAnimationPlaying) {
_isAnimationPlaying = NO;
return;
}
_playAnimation.delegate = nil;
_playAnimation.speed = 0;
NSNumber *frame = [_compContainer.presentationLayer.currentFrame copy];
_animationProgress = frame.floatValue / _sceneModel.endFrame.floatValue;
[self setProgressWithFrame:frame callCompletionIfNecessary:YES];
}
- (void)setAnimationProgress:(CGFloat)animationProgress {
if (!_sceneModel) {
_animationProgress = animationProgress;
return;
}
[self setProgressWithFrame:[self _frameForProgress:animationProgress] callCompletionIfNecessary:YES];
}
- (void)setProgressWithFrame:(nonnull NSNumber *)currentFrame {
[self setProgressWithFrame:currentFrame callCompletionIfNecessary:YES];
}
- (void)setProgressWithFrame:(nonnull NSNumber *)currentFrame callCompletionIfNecessary:(BOOL)callCompletion {
[self _removeCurrentAnimationIfNecessary];
[self _callCompletionIfNecessary:NO];
_animationProgress = [self _progressForFrame:currentFrame];
[CATransaction begin];
[CATransaction setDisableActions:YES];
_compContainer.currentFrame = frame;
_compContainer.currentFrame = currentFrame;
[_compContainer setNeedsDisplay];
[CATransaction commit];
if (callCompletion) {
[self _callCompletionIfNecessary:NO];
}
}
- (void)setLoopAnimation:(BOOL)loopAnimation {
_loopAnimation = loopAnimation;
if (_isAnimationPlaying && _sceneModel) {
NSNumber *frame = [(LOTCompositionContainer *)_compContainer.presentationLayer currentFrame];
NSNumber *start = _playAnimation.fromValue;
NSNumber *end = _playAnimation.toValue;
[self _removeCurrentAnimationIfNecessary];
_compContainer.currentFrame = frame;
_animationProgress = frame.floatValue / (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue);
[self playFromFrame:start toFrame:end withCompletion:self.completionBlock];
NSNumber *frame = [_compContainer.presentationLayer.currentFrame copy];
[self setProgressWithFrame:frame callCompletionIfNecessary:NO];
[self playFromFrame:_playRangeStartFrame toFrame:_playRangeEndFrame withCompletion:self.completionBlock];
}
}
- (void)setProgressWithFrame:(nonnull NSNumber *)currentFrame {
if (!_sceneModel) {
return;
-(void)setAnimationSpeed:(CGFloat)animationSpeed {
_animationSpeed = animationSpeed;
if (_isAnimationPlaying && _sceneModel) {
NSNumber *frame = [_compContainer.presentationLayer.currentFrame copy];
[self setProgressWithFrame:frame callCompletionIfNecessary:NO];
[self playFromFrame:_playRangeStartFrame toFrame:_playRangeEndFrame withCompletion:self.completionBlock];
}
[self _removeCurrentAnimationIfNecessary];
[self _callCompletionIfNecessary:NO];
_animationProgress = currentFrame.floatValue / (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue);
[CATransaction begin];
[CATransaction setDisableActions:YES];
_compContainer.currentFrame = currentFrame;
[_compContainer setNeedsDisplay];
[CATransaction commit];
}
# pragma mark - External Methods - Cache
- (void)setCacheEnable:(BOOL)cacheEnable{
_cacheEnable = cacheEnable;
if (!self.cacheKey) {
@ -319,6 +408,8 @@
}
}
# pragma mark - External Methods - Other
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
- (void)addSubview:(nonnull LOTView *)view
@ -368,63 +459,16 @@
}
}
- (void)_removeCurrentAnimationIfNecessary {
_playAnimation.speed = 0;
_isAnimationPlaying = NO;
_playAnimation.delegate = nil;
[_compContainer removeAllAnimations];
_playAnimation = nil;
}
# pragma mark - Completion Block
- (void)_callCompletionIfNecessary:(BOOL)complete {
if (self.completionBlock) {
self.completionBlock(complete);
self.completionBlock = nil;
}
- (void)logHierarchyKeypaths {
[_compContainer logHierarchyKeypathsWithParent:nil];
}
# pragma mark - Getters and Setters
- (void)setAnimationProgress:(CGFloat)animationProgress {
if (!_sceneModel) {
_animationProgress = animationProgress;
return;
}
[self _removeCurrentAnimationIfNecessary];
[self _callCompletionIfNecessary:NO];
CGFloat duration = _sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue;
CGFloat frame = (duration * animationProgress) + _sceneModel.startFrame.floatValue;
_animationProgress = animationProgress;
[CATransaction begin];
[CATransaction setDisableActions:YES];
_compContainer.currentFrame = @(frame);
[_compContainer setNeedsDisplay];
[CATransaction commit];
}
-(void)setAnimationSpeed:(CGFloat)animationSpeed {
if (!_sceneModel) {
_animationSpeed = animationSpeed;
return;
}
_animationSpeed = animationSpeed;
if (_isAnimationPlaying) {
NSNumber *frame = [(LOTCompositionContainer *)_compContainer.presentationLayer currentFrame];
NSNumber *start = _playAnimation.fromValue;
NSNumber *end = _playAnimation.toValue;
[self _removeCurrentAnimationIfNecessary];
_compContainer.currentFrame = frame;
_animationProgress = frame.floatValue / (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue);
[self playFromFrame:start toFrame:end withCompletion:self.completionBlock];
}
}
- (CGFloat)animationDuration {
if (!_sceneModel) {
return 0;
}
if (_playAnimation) {
return _playAnimation.duration;
}
@ -545,26 +589,16 @@
[CATransaction commit];
}
# pragma mark - CAANimationDelegate
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)complete {
if (!_isAnimationPlaying || !complete) {
[_compContainer displayWithFrame:_compContainer.currentFrame forceUpdate:YES];
}
if (!_isAnimationPlaying || !complete || ![anim isKindOfClass:[CABasicAnimation class]]) return;
NSNumber *frame = [(CABasicAnimation *)anim toValue];
_animationProgress = frame.floatValue / (_sceneModel.endFrame.floatValue - _sceneModel.startFrame.floatValue);
_isAnimationPlaying = NO;
_playAnimation.delegate = nil;
[_compContainer removeAllAnimations];
_playAnimation = nil;
[CATransaction begin];
[CATransaction setDisableActions:YES];
_compContainer.currentFrame = frame;
[CATransaction commit];
[self _removeCurrentAnimationIfNecessary];
[self setProgressWithFrame:_playRangeEndFrame callCompletionIfNecessary:NO];
[self _callCompletionIfNecessary:complete];
}
- (void)logHierarchyKeypaths {
[_compContainer logHierarchyKeypathsWithParent:nil];
}
@end

View File

@ -31,6 +31,7 @@
return nil;
}
// Change keyframe data
- (BOOL)setValue:(id)value atFrame:(NSNumber *)frame {
id data = [self keyframeDataForValue:value];
if (data == nil) {

View File

@ -68,9 +68,9 @@
if (modifier) {
modifier(inputNode);
}
} forceLocalUpdate:(localUpdate || forceUpdate)];
return inputUpdated;
}

View File

@ -28,7 +28,7 @@
LOTAnimatorNode *_rootNode;
LOTBezierPath *_outputPath;
LOTBezierPath *_localPath;
BOOL _rootNodeHasUpdate;
LOTNumberInterpolator *_opacityInterpolator;
LOTTransformInterpolator *_transformInterolator;
}
@ -126,11 +126,12 @@
- (BOOL)needsUpdateForFrame:(NSNumber *)frame {
return ([_opacityInterpolator hasUpdateForFrame:frame] ||
[_transformInterolator hasUpdateForFrame:frame] ||
[_rootNode needsUpdateForFrame:frame]);
_rootNodeHasUpdate);
}
- (BOOL)updateWithFrame:(NSNumber *)frame withModifierBlock:(void (^ _Nullable)(LOTAnimatorNode * _Nonnull))modifier forceLocalUpdate:(BOOL)forceUpdate {
_rootNodeHasUpdate = [_rootNode needsUpdateForFrame:frame];
indentation_level = indentation_level + 1;
[_rootNode updateWithFrame:frame withModifierBlock:modifier forceLocalUpdate:forceUpdate];
indentation_level = indentation_level - 1;