├── .DS_Store ├── README.md ├── lottie-ios_Oc.podspec └── oc 版本代码 ├── .DS_Store └── lottie-ios ├── .DS_Store └── Classes ├── .DS_Store ├── AnimatableLayers ├── LOTCompositionContainer.h ├── LOTCompositionContainer.m ├── LOTLayerContainer.h ├── LOTLayerContainer.m ├── LOTMaskContainer.h └── LOTMaskContainer.m ├── AnimatableProperties ├── LOTBezierData.h ├── LOTBezierData.m ├── LOTKeyframe.h └── LOTKeyframe.m ├── Extensions ├── CGGeometry+LOTAdditions.h ├── CGGeometry+LOTAdditions.m ├── LOTBezierPath.h ├── LOTBezierPath.m ├── LOTHelpers.h ├── LOTRadialGradientLayer.h ├── LOTRadialGradientLayer.m ├── UIColor+Expanded.h └── UIColor+Expanded.m ├── MacCompatibility ├── CALayer+Compat.h ├── CALayer+Compat.m ├── LOTPlatformCompat.h ├── NSValue+Compat.h ├── NSValue+Compat.m ├── UIBezierPath.h ├── UIBezierPath.m ├── UIColor.h └── UIColor.m ├── Models ├── LOTAsset.h ├── LOTAsset.m ├── LOTAssetGroup.h ├── LOTAssetGroup.m ├── LOTLayer.h ├── LOTLayer.m ├── LOTLayerGroup.h ├── LOTLayerGroup.m ├── LOTMask.h ├── LOTMask.m ├── LOTModels.h ├── LOTShapeCircle.h ├── LOTShapeCircle.m ├── LOTShapeFill.h ├── LOTShapeFill.m ├── LOTShapeGradientFill.h ├── LOTShapeGradientFill.m ├── LOTShapeGroup.h ├── LOTShapeGroup.m ├── LOTShapePath.h ├── LOTShapePath.m ├── LOTShapeRectangle.h ├── LOTShapeRectangle.m ├── LOTShapeRepeater.h ├── LOTShapeRepeater.m ├── LOTShapeStar.h ├── LOTShapeStar.m ├── LOTShapeStroke.h ├── LOTShapeStroke.m ├── LOTShapeTransform.h ├── LOTShapeTransform.m ├── LOTShapeTrimPath.h └── LOTShapeTrimPath.m ├── Private ├── LOTAnimatedControl.m ├── LOTAnimatedSwitch.m ├── LOTAnimationCache.m ├── LOTAnimationTransitionController.m ├── LOTAnimationView.m ├── LOTAnimationView_Internal.h ├── LOTBlockCallback.m ├── LOTCacheProvider.m ├── LOTComposition.m ├── LOTInterpolatorCallback.m ├── LOTKeypath.m └── LOTValueCallback.m ├── PublicHeaders ├── LOTAnimatedControl.h ├── LOTAnimatedSwitch.h ├── LOTAnimationCache.h ├── LOTAnimationTransitionController.h ├── LOTAnimationView.h ├── LOTAnimationView_Compat.h ├── LOTBlockCallback.h ├── LOTCacheProvider.h ├── LOTComposition.h ├── LOTInterpolatorCallback.h ├── LOTKeypath.h ├── LOTValueCallback.h ├── LOTValueDelegate.h └── Lottie.h └── RenderSystem ├── AnimatorNodes ├── LOTCircleAnimator.h ├── LOTCircleAnimator.m ├── LOTPathAnimator.h ├── LOTPathAnimator.m ├── LOTPolygonAnimator.h ├── LOTPolygonAnimator.m ├── LOTPolystarAnimator.h ├── LOTPolystarAnimator.m ├── LOTRoundedRectAnimator.h └── LOTRoundedRectAnimator.m ├── InterpolatorNodes ├── LOTArrayInterpolator.h ├── LOTArrayInterpolator.m ├── LOTColorInterpolator.h ├── LOTColorInterpolator.m ├── LOTNumberInterpolator.h ├── LOTNumberInterpolator.m ├── LOTPathInterpolator.h ├── LOTPathInterpolator.m ├── LOTPointInterpolator.h ├── LOTPointInterpolator.m ├── LOTSizeInterpolator.h ├── LOTSizeInterpolator.m ├── LOTTransformInterpolator.h ├── LOTTransformInterpolator.m ├── LOTValueInterpolator.h └── LOTValueInterpolator.m ├── LOTAnimatorNode.h ├── LOTAnimatorNode.m ├── LOTRenderNode.h ├── LOTRenderNode.m ├── ManipulatorNodes ├── LOTTrimPathNode.h └── LOTTrimPathNode.m └── RenderNodes ├── LOTFillRenderer.h ├── LOTFillRenderer.m ├── LOTGradientFillRender.h ├── LOTGradientFillRender.m ├── LOTRenderGroup.h ├── LOTRenderGroup.m ├── LOTRepeaterRenderer.h ├── LOTRepeaterRenderer.m ├── LOTStrokeRenderer.h └── LOTStrokeRenderer.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanligang/lottie-ios_Oc/e13f334cf7967c75968d1d3d4c30b778db2e7835/.DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lottie-ios_Oc 2 | lottie-ios oc版本代码库存,很多人都说找不到这个版本的了 我就传一份保存了 3 | # 支持 cocoapod 安装 4 | ``` 5 | pod 'lottie-ios_Oc' 6 | ``` 7 | -------------------------------------------------------------------------------- /lottie-ios_Oc.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'lottie-ios_Oc' 3 | s.version = '0.0.1' 4 | s.license = { :type => 'MIT' } 5 | s.summary = 'lottie-ios oc版本代码库存,很多人都说找不到这个版本的了 我就传一份保存了' 6 | s.description = <<-DESC 7 | lottie-ios oc版本代码库存,很多人都说找不到这个版本的了 我就传一份保存了. 8 | DESC 9 | s.homepage = 'https://github.com/lanligang/lottie-ios_Oc' 10 | s.authors = { 'LenSky' => 'lslanligang@sina.com' } 11 | s.source = { :git => 'https://github.com/lanligang/lottie-ios_Oc.git', :tag => s.version } 12 | s.source_files = 'oc 版本代码/lottie-ios/**/*' 13 | s.requires_arc = true 14 | s.ios.deployment_target = '7.0' 15 | s.ios.frameworks = ['UIKit', 'CoreGraphics', 'QuartzCore'] 16 | end -------------------------------------------------------------------------------- /oc 版本代码/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanligang/lottie-ios_Oc/e13f334cf7967c75968d1d3d4c30b778db2e7835/oc 版本代码/.DS_Store -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanligang/lottie-ios_Oc/e13f334cf7967c75968d1d3d4c30b778db2e7835/oc 版本代码/lottie-ios/.DS_Store -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanligang/lottie-ios_Oc/e13f334cf7967c75968d1d3d4c30b778db2e7835/oc 版本代码/lottie-ios/Classes/.DS_Store -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/AnimatableLayers/LOTCompositionContainer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTCompositionContainer.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/18/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTLayerContainer.h" 10 | #import "LOTAssetGroup.h" 11 | 12 | @interface LOTCompositionContainer : LOTLayerContainer 13 | 14 | - (instancetype _Nonnull)initWithModel:(LOTLayer * _Nullable)layer 15 | inLayerGroup:(LOTLayerGroup * _Nullable)layerGroup 16 | withLayerGroup:(LOTLayerGroup * _Nullable)childLayerGroup 17 | withAssestGroup:(LOTAssetGroup * _Nullable)assetGroup; 18 | 19 | - (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath; 20 | 21 | - (CGPoint)convertPoint:(CGPoint)point 22 | toKeypathLayer:(nonnull LOTKeypath *)keypath 23 | withParentLayer:(CALayer *_Nonnull)parent; 24 | 25 | - (CGRect)convertRect:(CGRect)rect 26 | toKeypathLayer:(nonnull LOTKeypath *)keypath 27 | withParentLayer:(CALayer *_Nonnull)parent; 28 | 29 | - (CGPoint)convertPoint:(CGPoint)point 30 | fromKeypathLayer:(nonnull LOTKeypath *)keypath 31 | withParentLayer:(CALayer *_Nonnull)parent; 32 | 33 | - (CGRect)convertRect:(CGRect)rect 34 | fromKeypathLayer:(nonnull LOTKeypath *)keypath 35 | withParentLayer:(CALayer *_Nonnull)parent; 36 | 37 | - (void)addSublayer:(nonnull CALayer *)subLayer 38 | toKeypathLayer:(nonnull LOTKeypath *)keypath; 39 | 40 | - (void)maskSublayer:(nonnull CALayer *)subLayer 41 | toKeypathLayer:(nonnull LOTKeypath *)keypath; 42 | 43 | @property (nonatomic, readonly, nonnull) NSArray *childLayers; 44 | @property (nonatomic, readonly, nonnull) NSDictionary *childMap; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/AnimatableLayers/LOTLayerContainer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTLayerContainer.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/18/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTPlatformCompat.h" 10 | #import "LOTLayer.h" 11 | #import "LOTLayerGroup.h" 12 | #import "LOTKeypath.h" 13 | #import "LOTValueDelegate.h" 14 | 15 | @class LOTValueCallback; 16 | 17 | @interface LOTLayerContainer : CALayer 18 | 19 | - (instancetype _Nonnull)initWithModel:(LOTLayer * _Nullable)layer 20 | inLayerGroup:(LOTLayerGroup * _Nullable)layerGroup; 21 | 22 | @property (nonatomic, readonly, strong, nullable) NSString *layerName; 23 | @property (nonatomic, nullable) NSNumber *currentFrame; 24 | @property (nonatomic, readonly, nonnull) NSNumber *timeStretchFactor; 25 | @property (nonatomic, assign) CGRect viewportBounds; 26 | @property (nonatomic, readonly, nonnull) CALayer *wrapperLayer; 27 | @property (nonatomic, readonly, nonnull) NSDictionary *valueInterpolators; 28 | 29 | - (void)displayWithFrame:(NSNumber * _Nonnull)frame; 30 | - (void)displayWithFrame:(NSNumber * _Nonnull)frame forceUpdate:(BOOL)forceUpdate; 31 | 32 | - (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath; 33 | 34 | - (void)setValueDelegate:(id _Nonnull)delegate 35 | forKeypath:(LOTKeypath * _Nonnull)keypath; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/AnimatableLayers/LOTMaskContainer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTMaskContainer.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/19/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTMask.h" 11 | 12 | @interface LOTMaskContainer : CALayer 13 | 14 | - (instancetype _Nonnull)initWithMasks:(NSArray * _Nonnull)masks; 15 | 16 | @property (nonatomic, strong, nullable) NSNumber *currentFrame; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/AnimatableLayers/LOTMaskContainer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTMaskContainer.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/19/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTMaskContainer.h" 10 | #import "LOTPathInterpolator.h" 11 | #import "LOTNumberInterpolator.h" 12 | 13 | @interface LOTMaskNodeLayer : CAShapeLayer 14 | 15 | @property (nonatomic, readonly) LOTMask *maskNode; 16 | 17 | - (instancetype)initWithMask:(LOTMask *)maskNode; 18 | - (BOOL)hasUpdateForFrame:(NSNumber *)frame; 19 | 20 | @end 21 | 22 | @implementation LOTMaskNodeLayer { 23 | LOTPathInterpolator *_pathInterpolator; 24 | LOTNumberInterpolator *_opacityInterpolator; 25 | LOTNumberInterpolator *_expansionInterpolator; 26 | } 27 | 28 | - (instancetype)initWithMask:(LOTMask *)maskNode { 29 | self = [super init]; 30 | if (self) { 31 | _pathInterpolator = [[LOTPathInterpolator alloc] initWithKeyframes:maskNode.maskPath.keyframes]; 32 | _opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:maskNode.opacity.keyframes]; 33 | _expansionInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:maskNode.expansion.keyframes]; 34 | _maskNode = maskNode; 35 | self.fillColor = [UIColor blueColor].CGColor; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)updateForFrame:(NSNumber *)frame withViewBounds:(CGRect)viewBounds { 41 | if ([self hasUpdateForFrame:frame]) { 42 | LOTBezierPath *path = [_pathInterpolator pathForFrame:frame cacheLengths:NO]; 43 | 44 | if (self.maskNode.maskMode == LOTMaskModeSubtract) { 45 | CGMutablePathRef pathRef = CGPathCreateMutable(); 46 | CGPathAddRect(pathRef, NULL, viewBounds); 47 | CGPathAddPath(pathRef, NULL, path.CGPath); 48 | self.path = pathRef; 49 | self.fillRule = @"even-odd"; 50 | CGPathRelease(pathRef); 51 | } else { 52 | self.path = path.CGPath; 53 | } 54 | 55 | self.opacity = [_opacityInterpolator floatValueForFrame:frame]; 56 | } 57 | } 58 | 59 | - (BOOL)hasUpdateForFrame:(NSNumber *)frame { 60 | return ([_pathInterpolator hasUpdateForFrame:frame] || 61 | [_opacityInterpolator hasUpdateForFrame:frame]); 62 | } 63 | 64 | @end 65 | 66 | @implementation LOTMaskContainer { 67 | NSArray *_masks; 68 | } 69 | 70 | - (instancetype)initWithMasks:(NSArray *)masks { 71 | self = [super init]; 72 | if (self) { 73 | NSMutableArray *maskNodes = [NSMutableArray array]; 74 | CALayer *containerLayer = [CALayer layer]; 75 | 76 | for (LOTMask *mask in masks) { 77 | LOTMaskNodeLayer *node = [[LOTMaskNodeLayer alloc] initWithMask:mask]; 78 | [maskNodes addObject:node]; 79 | if (mask.maskMode == LOTMaskModeAdd || 80 | mask == masks.firstObject) { 81 | [containerLayer addSublayer:node]; 82 | } else { 83 | containerLayer.mask = node; 84 | CALayer *newContainer = [CALayer layer]; 85 | [newContainer addSublayer:containerLayer]; 86 | containerLayer = newContainer; 87 | } 88 | } 89 | [self addSublayer:containerLayer]; 90 | _masks = maskNodes; 91 | 92 | } 93 | return self; 94 | } 95 | 96 | - (void)setCurrentFrame:(NSNumber *)currentFrame { 97 | if (_currentFrame == currentFrame) { 98 | return; 99 | } 100 | _currentFrame = currentFrame; 101 | 102 | for (LOTMaskNodeLayer *nodeLayer in _masks) { 103 | [nodeLayer updateForFrame:currentFrame withViewBounds:self.bounds]; 104 | } 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/AnimatableProperties/LOTBezierData.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTBezierData.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/10/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LOTBezierData : NSObject 15 | 16 | - (instancetype)initWithData:(NSDictionary *)bezierData; 17 | 18 | @property (nonatomic, readonly) NSInteger count; 19 | @property (nonatomic, readonly) BOOL closed; 20 | 21 | - (CGPoint)vertexAtIndex:(NSInteger)index; 22 | - (CGPoint)inTangentAtIndex:(NSInteger)index; 23 | - (CGPoint)outTangentAtIndex:(NSInteger)index; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/AnimatableProperties/LOTBezierData.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTBezierData.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/10/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTBezierData.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTBezierData { 13 | CGPoint *_vertices; 14 | CGPoint *_inTangents; 15 | CGPoint *_outTangents; 16 | } 17 | 18 | - (instancetype)initWithData:(NSDictionary *)bezierData 19 | { 20 | self = [super init]; 21 | if (self) { 22 | [self initializeData:bezierData]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)dealloc { 28 | free(_vertices); 29 | free(_inTangents); 30 | free(_outTangents); 31 | } 32 | 33 | - (CGPoint)vertexAtIndex:(NSInteger)index { 34 | NSAssert((index < _count && 35 | index >= 0), 36 | @"Lottie: Index out of bounds"); 37 | return _vertices[index]; 38 | } 39 | 40 | - (CGPoint)inTangentAtIndex:(NSInteger)index { 41 | NSAssert((index < _count && 42 | index >= 0), 43 | @"Lottie: Index out of bounds"); 44 | return _inTangents[index]; 45 | } 46 | 47 | - (CGPoint)outTangentAtIndex:(NSInteger)index { 48 | NSAssert((index < _count && 49 | index >= 0), 50 | @"Lottie: Index out of bounds"); 51 | return _outTangents[index]; 52 | } 53 | 54 | - (void)initializeData:(NSDictionary *)bezierData { 55 | 56 | NSArray *pointsArray = bezierData[@"v"]; 57 | NSArray *inTangents = bezierData[@"i"]; 58 | NSArray *outTangents = bezierData[@"o"]; 59 | 60 | if (pointsArray.count == 0) { 61 | NSLog(@"%s: Warning: shape has no vertices", __PRETTY_FUNCTION__); 62 | return ; 63 | } 64 | 65 | NSAssert((pointsArray.count == inTangents.count && 66 | pointsArray.count == outTangents.count), 67 | @"Lottie: Incorrect number of points and tangents"); 68 | _count = pointsArray.count; 69 | _vertices = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count); 70 | _inTangents = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count); 71 | _outTangents = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count); 72 | if (bezierData[@"c"]) { 73 | _closed = [bezierData[@"c"] boolValue]; 74 | } 75 | for (int i = 0; i < pointsArray.count; i ++) { 76 | CGPoint vertex = [self _vertexAtIndex:i inArray:pointsArray]; 77 | CGPoint outTan = LOT_PointAddedToPoint(vertex, [self _vertexAtIndex:i inArray:outTangents]); 78 | CGPoint inTan = LOT_PointAddedToPoint(vertex, [self _vertexAtIndex:i inArray:inTangents]); 79 | // BW BUG Straight Lines - Test Later 80 | // Bake fix for lines here 81 | _vertices[i] = vertex; 82 | _inTangents[i] = inTan; 83 | _outTangents[i] = outTan; 84 | } 85 | } 86 | 87 | - (CGPoint)_vertexAtIndex:(NSInteger)idx inArray:(NSArray *)points { 88 | NSAssert((idx < points.count), 89 | @"Lottie: Vertex Point out of bounds"); 90 | 91 | NSArray *pointArray = points[idx]; 92 | 93 | NSAssert((pointArray.count >= 2 && 94 | [pointArray.firstObject isKindOfClass:[NSNumber class]]), 95 | @"Lottie: Point Data Malformed"); 96 | 97 | return CGPointMake([(NSNumber *)pointArray[0] floatValue], [(NSNumber *)pointArray[1] floatValue]); 98 | } 99 | 100 | @end 101 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/AnimatableProperties/LOTKeyframe.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTKeyframe.h 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 7/10/17. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | #import "LOTPlatformCompat.h" 12 | #import "LOTBezierData.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface LOTKeyframe : NSObject 17 | 18 | - (instancetype)initWithKeyframe:(NSDictionary *)keyframe; 19 | - (instancetype)initWithValue:(id)value; 20 | - (void)remapValueWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock; 21 | - (LOTKeyframe *)copyWithData:(id)data; 22 | 23 | @property (nonatomic, readonly) NSNumber *keyframeTime; 24 | @property (nonatomic, readonly) BOOL isHold; 25 | @property (nonatomic, readonly) CGPoint inTangent; 26 | @property (nonatomic, readonly) CGPoint outTangent; 27 | @property (nonatomic, readonly) CGPoint spatialInTangent; 28 | @property (nonatomic, readonly) CGPoint spatialOutTangent; 29 | 30 | @property (nonatomic, readonly) CGFloat floatValue; 31 | @property (nonatomic, readonly) CGPoint pointValue; 32 | @property (nonatomic, readonly) CGSize sizeValue; 33 | @property (nonatomic, readonly) UIColor *colorValue; 34 | @property (nonatomic, readonly, nullable) LOTBezierData *pathData; 35 | @property (nonatomic, readonly) NSArray *arrayValue; 36 | 37 | @end 38 | 39 | @interface LOTKeyframeGroup : NSObject 40 | 41 | - (instancetype)initWithData:(id)data; 42 | 43 | - (void)remapKeyframesWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock; 44 | 45 | @property (nonatomic, readonly) NSArray *keyframes; 46 | 47 | @end 48 | 49 | NS_ASSUME_NONNULL_END 50 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Extensions/CGGeometry+LOTAdditions.h: -------------------------------------------------------------------------------- 1 | 2 | #import "LOTPlatformCompat.h" 3 | 4 | #import 5 | 6 | // 7 | // Core Graphics Geometry Additions 8 | // 9 | 10 | extern const CGSize CGSizeMax; 11 | 12 | CGRect LOT_RectIntegral(CGRect rect); 13 | 14 | // Centering 15 | 16 | // Returns a rectangle of the given size, centered at a point 17 | CGRect LOT_RectCenteredAtPoint(CGPoint center, CGSize size, BOOL integral); 18 | 19 | // Returns the center point of a CGRect 20 | CGPoint LOT_RectGetCenterPoint(CGRect rect); 21 | 22 | // Insetting 23 | 24 | // Inset the rectangle on a single edge 25 | CGRect LOT_RectInsetLeft(CGRect rect, CGFloat inset); 26 | CGRect LOT_RectInsetRight(CGRect rect, CGFloat inset); 27 | CGRect LOT_RectInsetTop(CGRect rect, CGFloat inset); 28 | CGRect LOT_RectInsetBottom(CGRect rect, CGFloat inset); 29 | 30 | // Inset the rectangle on two edges 31 | CGRect LOT_RectInsetHorizontal(CGRect rect, CGFloat leftInset, CGFloat rightInset); 32 | CGRect LOT_RectInsetVertical(CGRect rect, CGFloat topInset, CGFloat bottomInset); 33 | 34 | // Inset the rectangle on all edges 35 | CGRect LOT_RectInsetAll(CGRect rect, CGFloat leftInset, CGFloat rightInset, CGFloat topInset, CGFloat bottomInset); 36 | 37 | // Framing 38 | 39 | // Returns a rectangle of size framed in the center of the given rectangle 40 | CGRect LOT_RectFramedCenteredInRect(CGRect rect, CGSize size, BOOL integral); 41 | 42 | // Returns a rectangle of size framed in the given rectangle and inset 43 | CGRect LOT_RectFramedLeftInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral); 44 | CGRect LOT_RectFramedRightInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral); 45 | CGRect LOT_RectFramedTopInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral); 46 | CGRect LOT_RectFramedBottomInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral); 47 | 48 | CGRect LOT_RectFramedTopLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral); 49 | CGRect LOT_RectFramedTopRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral); 50 | CGRect LOT_RectFramedBottomLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral); 51 | CGRect LOT_RectFramedBottomRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral); 52 | 53 | // Divides a rect into sections and returns the section at specified index 54 | 55 | CGRect LOT_RectDividedSection(CGRect rect, NSInteger sections, NSInteger index, CGRectEdge fromEdge); 56 | 57 | // Returns a rectangle of size attached to the given rectangle 58 | CGRect LOT_RectAttachedLeftToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral); 59 | CGRect LOT_RectAttachedRightToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral); 60 | CGRect LOT_RectAttachedTopToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral); 61 | CGRect LOT_RectAttachedBottomToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral); 62 | 63 | CGRect LOT_RectAttachedBottomLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral); 64 | CGRect LOT_RectAttachedBottomRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral); 65 | CGRect LOT_RectAttachedTopRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral); 66 | CGRect LOT_RectAttachedTopLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral); 67 | 68 | BOOL LOT_CGPointIsZero(CGPoint point); 69 | 70 | // Combining 71 | // Adds all values of the 2nd rect to the first rect 72 | CGRect LOT_RectAddRect(CGRect rect, CGRect other); 73 | CGRect LOT_RectAddPoint(CGRect rect, CGPoint point); 74 | CGRect LOT_RectAddSize(CGRect rect, CGSize size); 75 | CGRect LOT_RectBounded(CGRect rect); 76 | 77 | CGPoint LOT_PointAddedToPoint(CGPoint point1, CGPoint point2); 78 | 79 | CGRect LOT_RectSetHeight(CGRect rect, CGFloat height); 80 | 81 | CGFloat LOT_PointDistanceFromPoint(CGPoint point1, CGPoint point2); 82 | CGFloat LOT_DegreesToRadians(CGFloat degrees); 83 | 84 | CGFloat LOT_RemapValue(CGFloat value, CGFloat low1, CGFloat high1, CGFloat low2, CGFloat high2 ); 85 | CGPoint LOT_PointByLerpingPoints(CGPoint point1, CGPoint point2, CGFloat value); 86 | 87 | CGPoint LOT_PointInLine(CGPoint A, CGPoint B, CGFloat T); 88 | CGPoint LOT_PointInCubicCurve(CGPoint start, CGPoint cp1, CGPoint cp2, CGPoint end, CGFloat T); 89 | 90 | CGFloat LOT_CubicBezierInterpolate(CGPoint P0, CGPoint P1, CGPoint P2, CGPoint P3, CGFloat x); 91 | CGFloat LOT_SolveCubic(CGFloat a, CGFloat b, CGFloat c, CGFloat d); 92 | CGFloat LOT_SolveQuadratic(CGFloat a, CGFloat b, CGFloat c); 93 | CGFloat LOT_Squared(CGFloat f); 94 | CGFloat LOT_Cubed(CGFloat f); 95 | CGFloat LOT_CubicRoot(CGFloat f); 96 | 97 | CGFloat LOT_CubicLength(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2); 98 | CGFloat LOT_CubicLengthWithPrecision(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2, CGFloat iterations); 99 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Extensions/LOTBezierPath.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTBezierPath.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/20/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTPlatformCompat.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LOTBezierPath : NSObject 14 | 15 | + (instancetype)pathWithCGPath:(CGPathRef)path; 16 | 17 | + (instancetype)newPath; 18 | 19 | - (void)LOT_moveToPoint:(CGPoint)point; 20 | 21 | - (void)LOT_addLineToPoint:(CGPoint)point; 22 | 23 | - (void)LOT_addCurveToPoint:(CGPoint)point 24 | controlPoint1:(CGPoint)cp1 25 | controlPoint2:(CGPoint)cp2; 26 | 27 | - (void)LOT_closePath; 28 | 29 | - (void)LOT_removeAllPoints; 30 | 31 | - (void)LOT_appendPath:(LOTBezierPath *)bezierPath; 32 | 33 | - (void)trimPathFromT:(CGFloat)fromT toT:(CGFloat)toT offset:(CGFloat)offset; 34 | 35 | - (void)LOT_applyTransform:(CGAffineTransform)transform; 36 | 37 | @property (nonatomic, assign) BOOL cacheLengths; 38 | 39 | @property (nonatomic, readonly) CGFloat length; 40 | 41 | @property (nonatomic, readonly) CGPathRef CGPath; 42 | @property (nonatomic, readonly) CGPoint currentPoint; 43 | @property (nonatomic) CGFloat lineWidth; 44 | @property (nonatomic) CGLineCap lineCapStyle; 45 | @property (nonatomic) CGLineJoin lineJoinStyle; 46 | @property (nonatomic) CGFloat miterLimit; 47 | @property (nonatomic) CGFloat flatness; 48 | @property (nonatomic) BOOL usesEvenOddFillRule; 49 | @property (readonly, getter=isEmpty) BOOL empty; 50 | @property (nonatomic, readonly) CGRect bounds; 51 | 52 | @end 53 | 54 | NS_ASSUME_NONNULL_END 55 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Extensions/LOTHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTHelpers.h 3 | // Lottie 4 | // 5 | // Created by Brandon Withrow on 7/28/16. 6 | // Copyright © 2016 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #ifndef LOTHelpers_h 10 | #define LOTHelpers_h 11 | 12 | #import "UIColor+Expanded.h" 13 | #import "CGGeometry+LOTAdditions.h" 14 | #import "LOTBezierPath.h" 15 | 16 | #define ENABLE_DEBUG_LOGGING NO 17 | #define ENABLE_DEBUG_SHAPES NO 18 | 19 | #endif /* LOTHelpers_h */ 20 | 21 | // TODO Feature Phase 22 | /* 23 | - Trim Path individually 24 | - Image Cache Support 25 | - Skew transform 26 | */ 27 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Extensions/LOTRadialGradientLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationView 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | #import 9 | #import 10 | 11 | @interface LOTRadialGradientLayer : CALayer 12 | 13 | @property CGPoint startPoint; 14 | @property CGPoint endPoint; 15 | 16 | @property (nonatomic, copy) NSArray *colors; 17 | @property (nonatomic, copy) NSArray *locations; 18 | @property (nonatomic, assign) BOOL isRadial; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Extensions/LOTRadialGradientLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationView 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTRadialGradientLayer.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTRadialGradientLayer 13 | 14 | @dynamic isRadial; 15 | @dynamic startPoint; 16 | @dynamic endPoint; 17 | @dynamic colors; 18 | @dynamic locations; 19 | 20 | + (BOOL)needsDisplayForKey:(NSString *)key { 21 | if ([key isEqualToString:@"startPoint"] || 22 | [key isEqualToString:@"endPoint"] || 23 | [key isEqualToString:@"colors"] || 24 | [key isEqualToString:@"locations"] || 25 | [key isEqualToString:@"isRadial"]) { 26 | return YES; 27 | } 28 | return [super needsDisplayForKey:key]; 29 | } 30 | 31 | - (id)actionForKey:(NSString *)key { 32 | id action = self.actions[key]; 33 | if (action) { 34 | if (action == [NSNull null]) { 35 | return nil; 36 | } 37 | return action; 38 | } 39 | 40 | if ([key isEqualToString:@"startPoint"] || 41 | [key isEqualToString:@"endPoint"] || 42 | [key isEqualToString:@"colors"] || 43 | [key isEqualToString:@"locations"] || 44 | [key isEqualToString:@"isRadial"]) { 45 | CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:key]; 46 | theAnimation.fromValue = [self.presentationLayer valueForKey:key]; 47 | return theAnimation; 48 | } 49 | return [super actionForKey:key]; 50 | } 51 | 52 | - (void)drawInContext:(CGContextRef)ctx { 53 | if (self.colors.count == 0) { 54 | return; 55 | } 56 | 57 | NSInteger numberOfLocations = self.locations.count; 58 | CGColorRef colorRef = (__bridge CGColorRef)[self.colors objectAtIndex:0]; 59 | NSInteger numberOfComponents = CGColorGetNumberOfComponents(colorRef); 60 | CGColorSpaceRef colorSpace = CGColorGetColorSpace(colorRef); 61 | 62 | CGPoint origin = self.startPoint; 63 | CGFloat radius = LOT_PointDistanceFromPoint(self.startPoint, self.endPoint); 64 | 65 | CGFloat gradientLocations[numberOfLocations]; 66 | CGFloat gradientComponents[numberOfLocations * numberOfComponents]; 67 | 68 | for (NSInteger locationIndex = 0; locationIndex < numberOfLocations; locationIndex++) { 69 | 70 | gradientLocations[locationIndex] = [self.locations[locationIndex] floatValue]; 71 | const CGFloat *colorComponents = CGColorGetComponents((__bridge CGColorRef)self.colors[locationIndex]); 72 | 73 | for (NSInteger componentIndex = 0; componentIndex < numberOfComponents; componentIndex++) { 74 | gradientComponents[numberOfComponents * locationIndex + componentIndex] = colorComponents[componentIndex]; 75 | } 76 | } 77 | 78 | CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientComponents, gradientLocations, numberOfLocations); 79 | 80 | if (self.isRadial) { 81 | CGContextDrawRadialGradient(ctx, gradient, origin, 0, origin, radius, kCGGradientDrawsAfterEndLocation); 82 | } else { 83 | CGContextDrawLinearGradient(ctx, gradient, self.startPoint, self.endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); 84 | } 85 | 86 | CGGradientRelease(gradient); 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Extensions/UIColor+Expanded.h: -------------------------------------------------------------------------------- 1 | #import "LOTPlatformCompat.h" 2 | 3 | // From http://github.com/ars/uicolor-utilities 4 | #define CLAMP(val,min,max) MIN(MAX(val,min),max) 5 | 6 | @interface UIColor (UIColor_Expanded) 7 | @property (nonatomic, readonly) CGColorSpaceModel colorSpaceModel; 8 | @property (nonatomic, readonly) BOOL canProvideRGBComponents; 9 | @property (nonatomic, readonly) CGFloat red; // Only valid if canProvideRGBComponents is YES 10 | @property (nonatomic, readonly) CGFloat green; // Only valid if canProvideRGBComponents is YES 11 | @property (nonatomic, readonly) CGFloat blue; // Only valid if canProvideRGBComponents is YES 12 | @property (nonatomic, readonly) CGFloat white; // Only valid if colorSpaceModel == kCGColorSpaceModelMonochrome 13 | @property (nonatomic, readonly) CGFloat alpha; 14 | @property (nonatomic, readonly) UInt32 rgbHex; 15 | 16 | - (NSString *)LOT_colorSpaceString; 17 | 18 | - (NSArray *)LOT_arrayFromRGBAComponents; 19 | 20 | - (BOOL)LOT_red:(CGFloat *)r green:(CGFloat *)g blue:(CGFloat *)b alpha:(CGFloat *)a; 21 | 22 | - (UIColor *)LOT_colorByLuminanceMapping; 23 | 24 | - (UIColor *)LOT_colorByMultiplyingByRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; 25 | - (UIColor *) LOT_colorByAddingRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; 26 | - (UIColor *) LOT_colorByLighteningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; 27 | - (UIColor *) LOT_colorByDarkeningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; 28 | 29 | - (UIColor *)LOT_colorByMultiplyingBy:(CGFloat)f; 30 | - (UIColor *) LOT_colorByAdding:(CGFloat)f; 31 | - (UIColor *) LOT_colorByLighteningTo:(CGFloat)f; 32 | - (UIColor *) LOT_colorByDarkeningTo:(CGFloat)f; 33 | 34 | - (UIColor *)LOT_colorByMultiplyingByColor:(UIColor *)color; 35 | - (UIColor *) LOT_colorByAddingColor:(UIColor *)color; 36 | - (UIColor *) LOT_colorByLighteningToColor:(UIColor *)color; 37 | - (UIColor *) LOT_colorByDarkeningToColor:(UIColor *)color; 38 | 39 | - (NSString *)LOT_stringFromColor; 40 | - (NSString *)LOT_hexStringValue; 41 | 42 | + (UIColor *)LOT_randomColor; 43 | + (UIColor *)LOT_colorWithString:(NSString *)stringToConvert; 44 | + (UIColor *)LOT_colorWithRGBHex:(UInt32)hex; 45 | + (UIColor *)LOT_colorWithHexString:(NSString *)stringToConvert; 46 | 47 | + (UIColor *)LOT_colorWithName:(NSString *)cssColorName; 48 | 49 | + (UIColor *)LOT_colorByLerpingFromColor:(UIColor *)fromColor toColor:(UIColor *)toColor amount:(CGFloat)amount; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/CALayer+Compat.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleksii Pavlovskyi on 2/2/17. 3 | // Copyright (c) 2017 Airbnb. All rights reserved. 4 | // 5 | 6 | #include 7 | 8 | #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 9 | #import 10 | #import 11 | 12 | @interface CALayer (Compat) 13 | 14 | @property (nonatomic, assign) BOOL allowsEdgeAntialiasing; 15 | 16 | @end 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/CALayer+Compat.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleksii Pavlovskyi on 2/2/17. 3 | // Copyright (c) 2017 Airbnb. All rights reserved. 4 | // 5 | 6 | #include 7 | 8 | #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 9 | #import "CALayer+Compat.h" 10 | 11 | @implementation CALayer (Compat) 12 | 13 | - (BOOL)allowsEdgeAntialiasing { return NO; } 14 | - (void)setAllowsEdgeAntialiasing:(BOOL)allowsEdgeAntialiasing { } 15 | 16 | @end 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/LOTPlatformCompat.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPlatformCompat.h 3 | // Lottie 4 | // 5 | // Created by Oleksii Pavlovskyi on 2/2/17. 6 | // Copyright (c) 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #ifndef LOTPlatformCompat_h 10 | #define LOTPlatformCompat_h 11 | 12 | #include 13 | 14 | #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 15 | 16 | #import 17 | 18 | #else 19 | 20 | #import 21 | #import "UIColor.h" 22 | #import "CALayer+Compat.h" 23 | #import "NSValue+Compat.h" 24 | #import "UIBezierPath.h" 25 | 26 | NS_INLINE NSString *NSStringFromCGRect(CGRect rect) { 27 | return NSStringFromRect(rect); 28 | } 29 | 30 | NS_INLINE NSString *NSStringFromCGPoint(CGPoint point) { 31 | return NSStringFromPoint(point); 32 | } 33 | 34 | typedef NSEdgeInsets UIEdgeInsets; 35 | 36 | #endif 37 | #endif 38 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/NSValue+Compat.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleksii Pavlovskyi on 2/2/17. 3 | // Copyright (c) 2017 Airbnb. All rights reserved. 4 | // 5 | 6 | #include 7 | 8 | #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 9 | #import 10 | 11 | @interface NSValue (Compat) 12 | 13 | + (NSValue *)valueWithCGRect:(CGRect)rect; 14 | + (NSValue *)valueWithCGPoint:(CGPoint)point; 15 | 16 | @property (nonatomic, readonly) CGRect CGRectValue; 17 | @property(nonatomic, readonly) CGPoint CGPointValue; 18 | @property (nonatomic, readonly) CGSize CGSizeValue; 19 | 20 | @end 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/NSValue+Compat.m: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Oleksii Pavlovskyi on 2/2/17. 3 | // Copyright (c) 2017 Airbnb. All rights reserved. 4 | // 5 | 6 | #include 7 | 8 | #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 9 | #import "NSValue+Compat.h" 10 | 11 | @implementation NSValue (Compat) 12 | 13 | + (NSValue *)valueWithCGRect:(CGRect)rect { 14 | return [self valueWithRect:rect]; 15 | } 16 | 17 | + (NSValue *)valueWithCGPoint:(CGPoint)point { 18 | return [self valueWithPoint:point]; 19 | } 20 | 21 | - (CGRect)CGRectValue { 22 | return self.rectValue; 23 | } 24 | 25 | - (CGPoint)CGPointValue { 26 | return self.pointValue; 27 | } 28 | 29 | - (CGSize)CGSizeValue { 30 | return self.sizeValue; 31 | } 32 | 33 | @end 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/UIBezierPath.h: -------------------------------------------------------------------------------- 1 | // Kindly stolen from https://github.com/BigZaphod/Chameleon 2 | /* 3 | * Copyright (c) 2011, The Iconfactory. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * 3. Neither the name of The Iconfactory nor the names of its contributors may 16 | * be used to endorse or promote products derived from this software without 17 | * specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT, 23 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 28 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include 32 | 33 | #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 34 | #import 35 | #import 36 | 37 | typedef NS_OPTIONS(NSUInteger, UIRectCorner) { 38 | UIRectCornerTopLeft = 1 << 0, 39 | UIRectCornerTopRight = 1 << 1, 40 | UIRectCornerBottomLeft = 1 << 2, 41 | UIRectCornerBottomRight = 1 << 3, 42 | UIRectCornerAllCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight 43 | }; 44 | 45 | @interface UIBezierPath : NSObject 46 | 47 | + (UIBezierPath *)bezierPath; 48 | + (UIBezierPath *)bezierPathWithRect:(CGRect)rect; 49 | + (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect; 50 | + (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; 51 | + (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii; 52 | + (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise; 53 | + (UIBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath; 54 | 55 | - (void)moveToPoint:(CGPoint)point; 56 | - (void)addLineToPoint:(CGPoint)point; 57 | - (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise; 58 | - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2; 59 | - (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint; 60 | - (void)closePath; 61 | - (void)removeAllPoints; 62 | - (void)appendPath:(UIBezierPath *)bezierPath; 63 | - (void)setLineDash:(const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase; 64 | - (void)getLineDash:(CGFloat *)pattern count:(NSInteger *)count phase:(CGFloat *)phase; 65 | - (BOOL)containsPoint:(CGPoint)point; 66 | - (void)applyTransform:(CGAffineTransform)transform; 67 | 68 | @property (nonatomic) CGPathRef CGPath; 69 | @property (nonatomic, readonly) CGPoint currentPoint; 70 | @property (nonatomic) CGFloat lineWidth; 71 | @property (nonatomic) CGLineCap lineCapStyle; 72 | @property (nonatomic) CGLineJoin lineJoinStyle; 73 | @property (nonatomic) CGFloat miterLimit; 74 | @property (nonatomic) CGFloat flatness; 75 | @property (nonatomic) BOOL usesEvenOddFillRule; 76 | @property (readonly, getter=isEmpty) BOOL empty; 77 | @property (nonatomic, readonly) CGRect bounds; 78 | @end 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/UIColor.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor.h 3 | // Lottie 4 | // 5 | // Created by Oleksii Pavlovskyi on 2/2/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 12 | #import 13 | #import 14 | 15 | @interface UIColor : NSObject 16 | 17 | + (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha; 18 | + (UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha; 19 | + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; 20 | + (UIColor *)colorWithCGColor:(CGColorRef)cgColor; 21 | 22 | + (UIColor *)blackColor; 23 | + (UIColor *)darkGrayColor; 24 | + (UIColor *)lightGrayColor; 25 | + (UIColor *)whiteColor; 26 | + (UIColor *)grayColor; 27 | + (UIColor *)redColor; 28 | + (UIColor *)greenColor; 29 | + (UIColor *)blueColor; 30 | + (UIColor *)cyanColor; 31 | + (UIColor *)yellowColor; 32 | + (UIColor *)magentaColor; 33 | + (UIColor *)orangeColor; 34 | + (UIColor *)purpleColor; 35 | + (UIColor *)brownColor; 36 | + (UIColor *)clearColor; 37 | 38 | - (UIColor *)colorWithAlphaComponent:(CGFloat)alpha; 39 | 40 | @property (nonatomic, readonly) CGColorRef CGColor; 41 | 42 | @end 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/MacCompatibility/UIColor.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor.m 3 | // Lottie 4 | // 5 | // Created by Oleksii Pavlovskyi on 2/2/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #include 10 | 11 | #if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR 12 | #import "UIColor.h" 13 | #import 14 | 15 | #define StaticColor(staticColor) \ 16 | static UIColor *color = nil; \ 17 | static dispatch_once_t onceToken; \ 18 | dispatch_once(&onceToken, ^{ \ 19 | color = NSColor.staticColor.UIColor; \ 20 | }); \ 21 | return color; \ 22 | 23 | @interface UIColor () 24 | 25 | @property (nonatomic, strong) NSColor *color; 26 | 27 | - (instancetype)initWithNSColor:(NSColor *)color; 28 | 29 | @end 30 | 31 | @interface NSColor (UIColor) 32 | 33 | @property (nonatomic, readonly) UIColor *UIColor; 34 | 35 | @end 36 | 37 | @implementation UIColor 38 | 39 | - (instancetype)initWithNSColor:(NSColor *)color { 40 | self = [super init]; 41 | if (self) { 42 | self.color = color; 43 | } 44 | return self; 45 | } 46 | 47 | + (UIColor *)colorWithNSColor:(NSColor *)color { 48 | return [[self alloc] initWithNSColor:color]; 49 | } 50 | 51 | + (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha { 52 | return [[NSColor colorWithWhite:white alpha:alpha] UIColor]; 53 | } 54 | 55 | + (UIColor *)colorWithHue:(CGFloat)hue 56 | saturation:(CGFloat)saturation 57 | brightness:(CGFloat)brightness 58 | alpha:(CGFloat)alpha { 59 | return [[NSColor colorWithHue:hue 60 | saturation:saturation 61 | brightness:brightness 62 | alpha:alpha] UIColor]; 63 | } 64 | 65 | + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha { 66 | return [[NSColor colorWithRed:red 67 | green:green 68 | blue:blue 69 | alpha:alpha] UIColor]; 70 | } 71 | 72 | + (UIColor *)colorWithCGColor:(CGColorRef)cgColor { 73 | return [[NSColor colorWithCGColor:cgColor] UIColor]; 74 | } 75 | 76 | + (UIColor *)blackColor { 77 | StaticColor(blackColor) 78 | } 79 | 80 | + (UIColor *)darkGrayColor { 81 | StaticColor(darkGrayColor) 82 | } 83 | 84 | + (UIColor *)lightGrayColor { 85 | StaticColor(lightGrayColor) 86 | } 87 | 88 | + (UIColor *)whiteColor { 89 | StaticColor(whiteColor) 90 | } 91 | 92 | + (UIColor *)grayColor { 93 | StaticColor(grayColor) 94 | } 95 | 96 | + (UIColor *)redColor { 97 | StaticColor(redColor) 98 | } 99 | 100 | + (UIColor *)greenColor { 101 | StaticColor(greenColor) 102 | } 103 | 104 | + (UIColor *)blueColor { 105 | StaticColor(blueColor) 106 | } 107 | 108 | + (UIColor *)cyanColor { 109 | StaticColor(cyanColor) 110 | } 111 | 112 | + (UIColor *)yellowColor { 113 | StaticColor(yellowColor) 114 | } 115 | 116 | + (UIColor *)magentaColor { 117 | StaticColor(magentaColor) 118 | } 119 | 120 | + (UIColor *)orangeColor { 121 | StaticColor(orangeColor) 122 | } 123 | 124 | + (UIColor *)purpleColor { 125 | StaticColor(purpleColor) 126 | } 127 | 128 | + (UIColor *)brownColor { 129 | StaticColor(brownColor) 130 | } 131 | 132 | + (UIColor *)clearColor { 133 | StaticColor(clearColor) 134 | } 135 | 136 | - (CGColorRef)CGColor { 137 | return self.color.CGColor; 138 | } 139 | 140 | - (UIColor *)colorWithAlphaComponent:(CGFloat)alpha { 141 | return [self.color colorWithAlphaComponent:alpha].UIColor; 142 | } 143 | 144 | - (id)copyWithZone:(NSZone *)zone { 145 | return [[self.color copyWithZone:zone] UIColor]; 146 | } 147 | 148 | @end 149 | 150 | @implementation NSColor (UIColor) 151 | 152 | - (UIColor *)UIColor { 153 | return [UIColor colorWithNSColor:self]; 154 | } 155 | 156 | @end 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTAsset.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAsset.h 3 | // Pods 4 | // 5 | // Created by Brandon Withrow on 2/16/17. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @class LOTLayerGroup; 15 | @class LOTLayer; 16 | @class LOTAssetGroup; 17 | 18 | @interface LOTAsset : NSObject 19 | 20 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary 21 | withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup 22 | withAssetBundle:(NSBundle *_Nonnull)bundle 23 | withFramerate:(NSNumber *)framerate; 24 | 25 | @property (nonatomic, readonly, nullable) NSString *referenceID; 26 | @property (nonatomic, readonly, nullable) NSNumber *assetWidth; 27 | @property (nonatomic, readonly, nullable) NSNumber *assetHeight; 28 | 29 | @property (nonatomic, readonly, nullable) NSString *imageName; 30 | @property (nonatomic, readonly, nullable) NSString *imageDirectory; 31 | 32 | @property (nonatomic, readonly, nullable) LOTLayerGroup *layerGroup; 33 | 34 | @property (nonatomic, readwrite) NSString *rootDirectory; 35 | @property (nonatomic, readonly) NSBundle *assetBundle; 36 | @end 37 | 38 | NS_ASSUME_NONNULL_END 39 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTAsset.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAsset.m 3 | // Pods 4 | // 5 | // Created by Brandon Withrow on 2/16/17. 6 | // 7 | // 8 | 9 | #import "LOTAsset.h" 10 | #import "LOTLayer.h" 11 | #import "LOTLayerGroup.h" 12 | #import "LOTAssetGroup.h" 13 | 14 | @implementation LOTAsset 15 | 16 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary 17 | withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup 18 | withAssetBundle:(NSBundle *_Nonnull)bundle 19 | withFramerate:(NSNumber *)framerate { 20 | self = [super init]; 21 | if (self) { 22 | _assetBundle = bundle; 23 | [self _mapFromJSON:jsonDictionary 24 | withAssetGroup:assetGroup 25 | withFramerate:framerate]; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary 31 | withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup 32 | withFramerate:(NSNumber *)framerate { 33 | _referenceID = [jsonDictionary[@"id"] copy]; 34 | 35 | if (jsonDictionary[@"w"]) { 36 | _assetWidth = [jsonDictionary[@"w"] copy]; 37 | } 38 | 39 | if (jsonDictionary[@"h"]) { 40 | _assetHeight = [jsonDictionary[@"h"] copy]; 41 | } 42 | 43 | if (jsonDictionary[@"u"]) { 44 | _imageDirectory = [jsonDictionary[@"u"] copy]; 45 | } 46 | 47 | if (jsonDictionary[@"p"]) { 48 | _imageName = [jsonDictionary[@"p"] copy]; 49 | } 50 | 51 | NSArray *layersJSON = jsonDictionary[@"layers"]; 52 | if (layersJSON) { 53 | _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON 54 | withAssetGroup:assetGroup 55 | withFramerate:framerate]; 56 | } 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTAssetGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAssetGroup.h 3 | // Pods 4 | // 5 | // Created by Brandon Withrow on 2/17/17. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class LOTAsset; 13 | @class LOTLayerGroup; 14 | @interface LOTAssetGroup : NSObject 15 | @property (nonatomic, readwrite) NSString * _Nullable rootDirectory; 16 | @property (nonatomic, readonly, nullable) NSBundle *assetBundle; 17 | 18 | - (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray 19 | withAssetBundle:(NSBundle *_Nullable)bundle 20 | withFramerate:(NSNumber * _Nonnull)framerate; 21 | 22 | - (void)buildAssetNamed:(NSString * _Nonnull)refID withFramerate:(NSNumber * _Nonnull)framerate; 23 | 24 | - (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate; 25 | 26 | - (LOTAsset * _Nullable)assetModelForID:(NSString * _Nonnull)assetID; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTAssetGroup.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAssetGroup.m 3 | // Pods 4 | // 5 | // Created by Brandon Withrow on 2/17/17. 6 | // 7 | // 8 | 9 | #import "LOTAssetGroup.h" 10 | #import "LOTAsset.h" 11 | 12 | @implementation LOTAssetGroup { 13 | NSMutableDictionary *_assetMap; 14 | NSDictionary *_assetJSONMap; 15 | } 16 | 17 | - (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray 18 | withAssetBundle:(NSBundle * _Nullable)bundle 19 | withFramerate:(NSNumber * _Nonnull)framerate { 20 | self = [super init]; 21 | if (self) { 22 | _assetBundle = bundle; 23 | _assetMap = [NSMutableDictionary dictionary]; 24 | NSMutableDictionary *assetJSONMap = [NSMutableDictionary dictionary]; 25 | for (NSDictionary *assetDictionary in jsonArray) { 26 | NSString *referenceID = assetDictionary[@"id"]; 27 | if (referenceID) { 28 | assetJSONMap[referenceID] = assetDictionary; 29 | } 30 | } 31 | _assetJSONMap = assetJSONMap; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)buildAssetNamed:(NSString *)refID 37 | withFramerate:(NSNumber * _Nonnull)framerate { 38 | 39 | if ([self assetModelForID:refID]) { 40 | return; 41 | } 42 | 43 | NSDictionary *assetDictionary = _assetJSONMap[refID]; 44 | if (assetDictionary) { 45 | LOTAsset *asset = [[LOTAsset alloc] initWithJSON:assetDictionary 46 | withAssetGroup:self 47 | withAssetBundle:_assetBundle 48 | withFramerate:framerate]; 49 | _assetMap[refID] = asset; 50 | } 51 | } 52 | 53 | - (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate { 54 | for (NSString *refID in _assetJSONMap.allKeys) { 55 | [self buildAssetNamed:refID withFramerate:framerate]; 56 | } 57 | _assetJSONMap = nil; 58 | } 59 | 60 | - (LOTAsset *)assetModelForID:(NSString *)assetID { 61 | return _assetMap[assetID]; 62 | } 63 | 64 | - (void)setRootDirectory:(NSString *)rootDirectory { 65 | _rootDirectory = rootDirectory; 66 | [_assetMap enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, LOTAsset * _Nonnull obj, BOOL * _Nonnull stop) { 67 | obj.rootDirectory = rootDirectory; 68 | }]; 69 | } 70 | @end 71 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTLayer.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTPlatformCompat.h" 11 | #import "LOTKeyframe.h" 12 | 13 | @class LOTShapeGroup; 14 | @class LOTMask; 15 | @class LOTAsset; 16 | @class LOTAssetGroup; 17 | 18 | typedef enum : NSInteger { 19 | LOTLayerTypePrecomp, 20 | LOTLayerTypeSolid, 21 | LOTLayerTypeImage, 22 | LOTLayerTypeNull, 23 | LOTLayerTypeShape, 24 | LOTLayerTypeUnknown 25 | } LOTLayerType; 26 | 27 | typedef enum : NSInteger { 28 | LOTMatteTypeNone, 29 | LOTMatteTypeAdd, 30 | LOTMatteTypeInvert, 31 | LOTMatteTypeUnknown 32 | } LOTMatteType; 33 | 34 | NS_ASSUME_NONNULL_BEGIN 35 | 36 | @interface LOTLayer : NSObject 37 | 38 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary 39 | withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup 40 | withFramerate:(NSNumber *)framerate; 41 | 42 | @property (nonatomic, readonly) NSString *layerName; 43 | @property (nonatomic, readonly, nullable) NSString *referenceID; 44 | @property (nonatomic, readonly) NSNumber *layerID; 45 | @property (nonatomic, readonly) LOTLayerType layerType; 46 | @property (nonatomic, readonly, nullable) NSNumber *parentID; 47 | @property (nonatomic, readonly) NSNumber *startFrame; 48 | @property (nonatomic, readonly) NSNumber *inFrame; 49 | @property (nonatomic, readonly) NSNumber *outFrame; 50 | @property (nonatomic, readonly) NSNumber *timeStretch; 51 | @property (nonatomic, readonly) CGRect layerBounds; 52 | 53 | @property (nonatomic, readonly, nullable) NSArray *shapes; 54 | @property (nonatomic, readonly, nullable) NSArray *masks; 55 | 56 | @property (nonatomic, readonly, nullable) NSNumber *layerWidth; 57 | @property (nonatomic, readonly, nullable) NSNumber *layerHeight; 58 | @property (nonatomic, readonly, nullable) UIColor *solidColor; 59 | @property (nonatomic, readonly, nullable) LOTAsset *imageAsset; 60 | 61 | @property (nonatomic, readonly) LOTKeyframeGroup *opacity; 62 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *timeRemapping; 63 | @property (nonatomic, readonly) LOTKeyframeGroup *rotation; 64 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *position; 65 | 66 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *positionX; 67 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *positionY; 68 | 69 | @property (nonatomic, readonly) LOTKeyframeGroup *anchor; 70 | @property (nonatomic, readonly) LOTKeyframeGroup *scale; 71 | 72 | @property (nonatomic, readonly) LOTMatteType matteType; 73 | 74 | @end 75 | 76 | NS_ASSUME_NONNULL_END 77 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTLayer.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTLayer.h" 10 | #import "LOTAsset.h" 11 | #import "LOTAssetGroup.h" 12 | #import "LOTShapeGroup.h" 13 | #import "LOTComposition.h" 14 | #import "LOTHelpers.h" 15 | #import "LOTMask.h" 16 | #import "LOTHelpers.h" 17 | 18 | @implementation LOTLayer 19 | 20 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary 21 | withAssetGroup:(LOTAssetGroup *)assetGroup 22 | withFramerate:(NSNumber *)framerate { 23 | self = [super init]; 24 | if (self) { 25 | [self _mapFromJSON:jsonDictionary 26 | withAssetGroup:assetGroup 27 | withFramerate:framerate]; 28 | } 29 | return self; 30 | } 31 | 32 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary 33 | withAssetGroup:(LOTAssetGroup *)assetGroup 34 | withFramerate:(NSNumber *)framerate { 35 | 36 | _layerName = [jsonDictionary[@"nm"] copy]; 37 | _layerID = [jsonDictionary[@"ind"] copy]; 38 | 39 | NSNumber *layerType = jsonDictionary[@"ty"]; 40 | _layerType = layerType.integerValue; 41 | 42 | if (jsonDictionary[@"refId"]) { 43 | _referenceID = [jsonDictionary[@"refId"] copy]; 44 | } 45 | 46 | _parentID = [jsonDictionary[@"parent"] copy]; 47 | 48 | if (jsonDictionary[@"st"]) { 49 | _startFrame = [jsonDictionary[@"st"] copy]; 50 | } 51 | _inFrame = [jsonDictionary[@"ip"] copy]; 52 | _outFrame = [jsonDictionary[@"op"] copy]; 53 | 54 | if (jsonDictionary[@"sr"]) { 55 | _timeStretch = [jsonDictionary[@"sr"] copy]; 56 | } else { 57 | _timeStretch = @1; 58 | } 59 | 60 | if (_layerType == LOTLayerTypePrecomp) { 61 | _layerHeight = [jsonDictionary[@"h"] copy]; 62 | _layerWidth = [jsonDictionary[@"w"] copy]; 63 | [assetGroup buildAssetNamed:_referenceID withFramerate:framerate]; 64 | } else if (_layerType == LOTLayerTypeImage) { 65 | [assetGroup buildAssetNamed:_referenceID withFramerate:framerate]; 66 | _imageAsset = [assetGroup assetModelForID:_referenceID]; 67 | _layerWidth = [_imageAsset.assetWidth copy]; 68 | _layerHeight = [_imageAsset.assetHeight copy]; 69 | } else if (_layerType == LOTLayerTypeSolid) { 70 | _layerWidth = jsonDictionary[@"sw"]; 71 | _layerHeight = jsonDictionary[@"sh"]; 72 | NSString *solidColor = jsonDictionary[@"sc"]; 73 | _solidColor = [UIColor LOT_colorWithHexString:solidColor]; 74 | } 75 | 76 | _layerBounds = CGRectMake(0, 0, _layerWidth.floatValue, _layerHeight.floatValue); 77 | 78 | NSDictionary *ks = jsonDictionary[@"ks"]; 79 | 80 | NSDictionary *opacity = ks[@"o"]; 81 | if (opacity) { 82 | _opacity = [[LOTKeyframeGroup alloc] initWithData:opacity]; 83 | [_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 84 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 85 | }]; 86 | } 87 | 88 | NSDictionary *timeRemap = jsonDictionary[@"tm"]; 89 | if (timeRemap) { 90 | _timeRemapping = [[LOTKeyframeGroup alloc] initWithData:timeRemap]; 91 | [_timeRemapping remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 92 | return inValue * framerate.doubleValue; 93 | }]; 94 | } 95 | 96 | NSDictionary *rotation = ks[@"r"]; 97 | if (rotation == nil) { 98 | rotation = ks[@"rz"]; 99 | } 100 | if (rotation) { 101 | _rotation = [[LOTKeyframeGroup alloc] initWithData:rotation]; 102 | [_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 103 | return LOT_DegreesToRadians(inValue); 104 | }]; 105 | } 106 | 107 | NSDictionary *position = ks[@"p"]; 108 | if ([position[@"s"] boolValue]) { 109 | // Separate dimensions 110 | _positionX = [[LOTKeyframeGroup alloc] initWithData:position[@"x"]]; 111 | _positionY = [[LOTKeyframeGroup alloc] initWithData:position[@"y"]]; 112 | } else { 113 | _position = [[LOTKeyframeGroup alloc] initWithData:position ]; 114 | } 115 | 116 | NSDictionary *anchor = ks[@"a"]; 117 | if (anchor) { 118 | _anchor = [[LOTKeyframeGroup alloc] initWithData:anchor]; 119 | } 120 | 121 | NSDictionary *scale = ks[@"s"]; 122 | if (scale) { 123 | _scale = [[LOTKeyframeGroup alloc] initWithData:scale]; 124 | [_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 125 | return LOT_RemapValue(inValue, -100, 100, -1, 1); 126 | }]; 127 | } 128 | 129 | _matteType = [jsonDictionary[@"tt"] integerValue]; 130 | 131 | 132 | NSMutableArray *masks = [NSMutableArray array]; 133 | for (NSDictionary *maskJSON in jsonDictionary[@"masksProperties"]) { 134 | LOTMask *mask = [[LOTMask alloc] initWithJSON:maskJSON]; 135 | [masks addObject:mask]; 136 | } 137 | _masks = masks.count ? masks : nil; 138 | 139 | NSMutableArray *shapes = [NSMutableArray array]; 140 | for (NSDictionary *shapeJSON in jsonDictionary[@"shapes"]) { 141 | id shapeItem = [LOTShapeGroup shapeItemWithJSON:shapeJSON]; 142 | if (shapeItem) { 143 | [shapes addObject:shapeItem]; 144 | } 145 | } 146 | _shapes = shapes; 147 | 148 | NSArray *effects = jsonDictionary[@"ef"]; 149 | if (effects.count > 0) { 150 | 151 | NSDictionary *effectNames = @{ @0: @"slider", 152 | @1: @"angle", 153 | @2: @"color", 154 | @3: @"point", 155 | @4: @"checkbox", 156 | @5: @"group", 157 | @6: @"noValue", 158 | @7: @"dropDown", 159 | @9: @"customValue", 160 | @10: @"layerIndex", 161 | @20: @"tint", 162 | @21: @"fill" }; 163 | 164 | for (NSDictionary *effect in effects) { 165 | NSNumber *typeNumber = effect[@"ty"]; 166 | NSString *name = effect[@"nm"]; 167 | NSString *internalName = effect[@"mn"]; 168 | NSString *typeString = effectNames[typeNumber]; 169 | if (typeString) { 170 | NSLog(@"%s: Warning: %@ effect not supported: %@ / %@", __PRETTY_FUNCTION__, typeString, internalName, name); 171 | } 172 | } 173 | } 174 | } 175 | 176 | - (NSString *)description { 177 | NSMutableString *text = [[super description] mutableCopy]; 178 | [text appendFormat:@" %@ id: %d pid: %d frames: %d-%d", _layerName, (int)_layerID.integerValue, (int)_parentID.integerValue, 179 | (int)_inFrame.integerValue, (int)_outFrame.integerValue]; 180 | return text; 181 | } 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTLayerGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTLayerGroup.h 3 | // Pods 4 | // 5 | // Created by Brandon Withrow on 2/16/17. 6 | // 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @class LOTLayer; 15 | @class LOTAssetGroup; 16 | 17 | @interface LOTLayerGroup : NSObject 18 | 19 | - (instancetype)initWithLayerJSON:(NSArray *)layersJSON 20 | withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup 21 | withFramerate:(NSNumber *)framerate; 22 | 23 | @property (nonatomic, readonly) NSArray *layers; 24 | 25 | - (LOTLayer *)layerModelForID:(NSNumber *)layerID; 26 | - (LOTLayer *)layerForReferenceID:(NSString *)referenceID; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTLayerGroup.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTLayerGroup.m 3 | // Pods 4 | // 5 | // Created by Brandon Withrow on 2/16/17. 6 | // 7 | // 8 | 9 | #import "LOTLayerGroup.h" 10 | #import "LOTLayer.h" 11 | #import "LOTAssetGroup.h" 12 | 13 | @implementation LOTLayerGroup { 14 | NSDictionary *_modelMap; 15 | NSDictionary *_referenceIDMap; 16 | } 17 | 18 | - (instancetype)initWithLayerJSON:(NSArray *)layersJSON 19 | withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup 20 | withFramerate:(NSNumber *)framerate { 21 | self = [super init]; 22 | if (self) { 23 | [self _mapFromJSON:layersJSON withAssetGroup:assetGroup withFramerate:framerate]; 24 | } 25 | return self; 26 | } 27 | 28 | - (void)_mapFromJSON:(NSArray *)layersJSON 29 | withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup 30 | withFramerate:(NSNumber *)framerate { 31 | 32 | NSMutableArray *layers = [NSMutableArray array]; 33 | NSMutableDictionary *modelMap = [NSMutableDictionary dictionary]; 34 | NSMutableDictionary *referenceMap = [NSMutableDictionary dictionary]; 35 | 36 | for (NSDictionary *layerJSON in layersJSON) { 37 | LOTLayer *layer = [[LOTLayer alloc] initWithJSON:layerJSON 38 | withAssetGroup:assetGroup 39 | withFramerate:framerate]; 40 | [layers addObject:layer]; 41 | modelMap[layer.layerID] = layer; 42 | if (layer.referenceID) { 43 | referenceMap[layer.referenceID] = layer; 44 | } 45 | } 46 | 47 | _referenceIDMap = referenceMap; 48 | _modelMap = modelMap; 49 | _layers = layers; 50 | } 51 | 52 | - (LOTLayer *)layerModelForID:(NSNumber *)layerID { 53 | return _modelMap[layerID]; 54 | } 55 | 56 | - (LOTLayer *)layerForReferenceID:(NSString *)referenceID { 57 | return _referenceIDMap[referenceID]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTMask.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTMask.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | typedef enum : NSUInteger { 13 | LOTMaskModeAdd, 14 | LOTMaskModeSubtract, 15 | LOTMaskModeIntersect, 16 | LOTMaskModeUnknown 17 | } LOTMaskMode; 18 | 19 | @interface LOTMask : NSObject 20 | 21 | - (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nonnull)jsonDictionary; 22 | 23 | @property (nonatomic, readonly) BOOL closed; 24 | @property (nonatomic, readonly) BOOL inverted; 25 | @property (nonatomic, readonly) LOTMaskMode maskMode; 26 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *maskPath; 27 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *opacity; 28 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *expansion; 29 | @end 30 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTMask.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTMask.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTMask.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTMask 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 15 | self = [super init]; 16 | if (self) { 17 | [self _mapFromJSON:jsonDictionary]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 23 | NSNumber *closed = jsonDictionary[@"cl"]; 24 | _closed = closed.boolValue; 25 | 26 | NSNumber *inverted = jsonDictionary[@"inv"]; 27 | _inverted = inverted.boolValue; 28 | 29 | NSString *mode = jsonDictionary[@"mode"]; 30 | if ([mode isEqualToString:@"a"]) { 31 | _maskMode = LOTMaskModeAdd; 32 | } else if ([mode isEqualToString:@"s"]) { 33 | _maskMode = LOTMaskModeSubtract; 34 | } else if ([mode isEqualToString:@"i"]) { 35 | _maskMode = LOTMaskModeIntersect; 36 | } else { 37 | _maskMode = LOTMaskModeUnknown; 38 | } 39 | 40 | NSDictionary *maskshape = jsonDictionary[@"pt"]; 41 | if (maskshape) { 42 | _maskPath = [[LOTKeyframeGroup alloc] initWithData:maskshape]; 43 | } 44 | 45 | NSDictionary *opacity = jsonDictionary[@"o"]; 46 | if (opacity) { 47 | _opacity = [[LOTKeyframeGroup alloc] initWithData:opacity]; 48 | [_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 49 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 50 | }]; 51 | } 52 | 53 | NSDictionary *expansion = jsonDictionary[@"x"]; 54 | if (expansion) { 55 | _expansion = [[LOTKeyframeGroup alloc] initWithData:expansion]; 56 | } 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTModels.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTModels.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #ifndef LOTModels_h 10 | #define LOTModels_h 11 | 12 | #import "LOTKeyframe.h" 13 | #import "LOTComposition.h" 14 | #import "LOTLayer.h" 15 | #import "LOTMask.h" 16 | #import "LOTShapeCircle.h" 17 | #import "LOTShapeFill.h" 18 | #import "LOTShapeGroup.h" 19 | #import "LOTShapePath.h" 20 | #import "LOTShapeRectangle.h" 21 | #import "LOTShapeStroke.h" 22 | #import "LOTShapeTransform.h" 23 | #import "LOTShapeTrimPath.h" 24 | #import "LOTLayerGroup.h" 25 | #import "LOTAsset.h" 26 | #import "LOTShapeGradientFill.h" 27 | 28 | #endif /* LOTModels_h */ 29 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeCircle.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeCircle.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LOTShapeCircle : NSObject 15 | 16 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 17 | 18 | @property (nonatomic, readonly) NSString *keyname; 19 | @property (nonatomic, readonly) LOTKeyframeGroup *position; 20 | @property (nonatomic, readonly) LOTKeyframeGroup *size; 21 | @property (nonatomic, readonly) BOOL reversed; 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeCircle.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeCircle.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeCircle.h" 10 | 11 | @implementation LOTShapeCircle 12 | 13 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 14 | self = [super init]; 15 | if (self) { 16 | [self _mapFromJSON:jsonDictionary]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 22 | 23 | if (jsonDictionary[@"nm"] ) { 24 | _keyname = [jsonDictionary[@"nm"] copy]; 25 | } 26 | 27 | NSDictionary *position = jsonDictionary[@"p"]; 28 | if (position) { 29 | _position = [[LOTKeyframeGroup alloc] initWithData:position]; 30 | } 31 | 32 | NSDictionary *size= jsonDictionary[@"s"]; 33 | if (size) { 34 | _size = [[LOTKeyframeGroup alloc] initWithData:size]; 35 | } 36 | NSNumber *reversed = jsonDictionary[@"d"]; 37 | _reversed = (reversed.integerValue == 3); 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeFill.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeFill.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LOTShapeFill : NSObject 15 | 16 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 17 | 18 | @property (nonatomic, readonly) NSString *keyname; 19 | @property (nonatomic, readonly) BOOL fillEnabled; 20 | @property (nonatomic, readonly) LOTKeyframeGroup *color; 21 | @property (nonatomic, readonly) LOTKeyframeGroup *opacity; 22 | @property (nonatomic, readonly) BOOL evenOddFillRule; 23 | 24 | @end 25 | 26 | NS_ASSUME_NONNULL_END 27 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeFill.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeFill.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeFill.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTShapeFill 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 15 | self = [super init]; 16 | if (self) { 17 | [self _mapFromJSON:jsonDictionary]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 23 | 24 | if (jsonDictionary[@"nm"] ) { 25 | _keyname = [jsonDictionary[@"nm"] copy]; 26 | } 27 | 28 | NSDictionary *color = jsonDictionary[@"c"]; 29 | if (color) { 30 | _color = [[LOTKeyframeGroup alloc] initWithData:color]; 31 | } 32 | 33 | NSDictionary *opacity = jsonDictionary[@"o"]; 34 | if (opacity) { 35 | _opacity = [[LOTKeyframeGroup alloc] initWithData:opacity]; 36 | [_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 37 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 38 | }]; 39 | } 40 | 41 | NSNumber *evenOdd = jsonDictionary[@"r"]; 42 | if (evenOdd.integerValue == 2) { 43 | _evenOddFillRule = YES; 44 | } else { 45 | _evenOddFillRule = NO; 46 | } 47 | 48 | NSNumber *fillEnabled = jsonDictionary[@"fillEnabled"]; 49 | _fillEnabled = fillEnabled.boolValue; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeGradientFill.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeGradientFill.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/26/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | typedef enum : NSUInteger { 15 | LOTGradientTypeLinear, 16 | LOTGradientTypeRadial 17 | } LOTGradientType; 18 | 19 | @interface LOTShapeGradientFill : NSObject 20 | 21 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 22 | 23 | @property (nonatomic, readonly) NSString *keyname; 24 | @property (nonatomic, readonly) NSNumber *numberOfColors; 25 | @property (nonatomic, readonly) LOTKeyframeGroup *startPoint; 26 | @property (nonatomic, readonly) LOTKeyframeGroup *endPoint; 27 | @property (nonatomic, readonly) LOTKeyframeGroup *gradient; 28 | @property (nonatomic, readonly) LOTKeyframeGroup *opacity; 29 | @property (nonatomic, readonly) BOOL evenOddFillRule; 30 | @property (nonatomic, readonly) LOTGradientType type; 31 | 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeGradientFill.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeGradientFill.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/26/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeGradientFill.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTShapeGradientFill 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 15 | self = [super init]; 16 | if (self) { 17 | [self _mapFromJSON:jsonDictionary]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 23 | if (jsonDictionary[@"nm"] ) { 24 | _keyname = [jsonDictionary[@"nm"] copy]; 25 | } 26 | 27 | NSNumber *type = jsonDictionary[@"t"]; 28 | 29 | if (type.integerValue != 1) { 30 | _type = LOTGradientTypeRadial; 31 | } else { 32 | _type = LOTGradientTypeLinear; 33 | } 34 | 35 | NSDictionary *start = jsonDictionary[@"s"]; 36 | if (start) { 37 | _startPoint = [[LOTKeyframeGroup alloc] initWithData:start]; 38 | } 39 | 40 | NSDictionary *end = jsonDictionary[@"e"]; 41 | if (end) { 42 | _endPoint = [[LOTKeyframeGroup alloc] initWithData:end]; 43 | } 44 | 45 | NSDictionary *gradient = jsonDictionary[@"g"]; 46 | if (gradient) { 47 | NSDictionary *unwrappedGradient = gradient[@"k"]; 48 | _numberOfColors = gradient[@"p"]; 49 | _gradient = [[LOTKeyframeGroup alloc] initWithData:unwrappedGradient]; 50 | } 51 | 52 | NSDictionary *opacity = jsonDictionary[@"o"]; 53 | if (opacity) { 54 | _opacity = [[LOTKeyframeGroup alloc] initWithData:opacity]; 55 | [_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 56 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 57 | }]; 58 | } 59 | 60 | NSNumber *evenOdd = jsonDictionary[@"r"]; 61 | if (evenOdd.integerValue == 2) { 62 | _evenOddFillRule = YES; 63 | } else { 64 | _evenOddFillRule = NO; 65 | } 66 | } 67 | @end 68 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShape.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface LOTShapeGroup : NSObject 13 | 14 | - (instancetype _Nonnull)initWithJSON:(NSDictionary *_Nonnull)jsonDictionary; 15 | 16 | @property (nonatomic, readonly, nonnull) NSString *keyname; 17 | @property (nonatomic, readonly, nonnull) NSArray *items; 18 | 19 | + (id _Nullable)shapeItemWithJSON:(NSDictionary * _Nonnull)itemJSON; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeGroup.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShape.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeGroup.h" 10 | #import "LOTShapeFill.h" 11 | #import "LOTShapePath.h" 12 | #import "LOTShapeCircle.h" 13 | #import "LOTShapeStroke.h" 14 | #import "LOTShapeTransform.h" 15 | #import "LOTShapeRectangle.h" 16 | #import "LOTShapeTrimPath.h" 17 | #import "LOTShapeGradientFill.h" 18 | #import "LOTShapeStar.h" 19 | #import "LOTShapeRepeater.h" 20 | 21 | @implementation LOTShapeGroup 22 | 23 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 24 | self = [super init]; 25 | if (self) { 26 | [self _mapFromJSON:jsonDictionary]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 32 | 33 | if (jsonDictionary[@"nm"] ) { 34 | _keyname = [jsonDictionary[@"nm"] copy]; 35 | } 36 | 37 | NSArray *itemsJSON = jsonDictionary[@"it"]; 38 | NSMutableArray *items = [NSMutableArray array]; 39 | for (NSDictionary *itemJSON in itemsJSON) { 40 | id newItem = [LOTShapeGroup shapeItemWithJSON:itemJSON]; 41 | if (newItem) { 42 | [items addObject:newItem]; 43 | } 44 | } 45 | _items = items; 46 | } 47 | 48 | + (id)shapeItemWithJSON:(NSDictionary *)itemJSON { 49 | NSString *type = itemJSON[@"ty"]; 50 | if ([type isEqualToString:@"gr"]) { 51 | LOTShapeGroup *group = [[LOTShapeGroup alloc] initWithJSON:itemJSON]; 52 | return group; 53 | } else if ([type isEqualToString:@"st"]) { 54 | LOTShapeStroke *stroke = [[LOTShapeStroke alloc] initWithJSON:itemJSON]; 55 | return stroke; 56 | } else if ([type isEqualToString:@"fl"]) { 57 | LOTShapeFill *fill = [[LOTShapeFill alloc] initWithJSON:itemJSON]; 58 | return fill; 59 | } else if ([type isEqualToString:@"tr"]) { 60 | LOTShapeTransform *transform = [[LOTShapeTransform alloc] initWithJSON:itemJSON]; 61 | return transform; 62 | } else if ([type isEqualToString:@"sh"]) { 63 | LOTShapePath *path = [[LOTShapePath alloc] initWithJSON:itemJSON]; 64 | return path; 65 | } else if ([type isEqualToString:@"el"]) { 66 | LOTShapeCircle *circle = [[LOTShapeCircle alloc] initWithJSON:itemJSON]; 67 | return circle; 68 | } else if ([type isEqualToString:@"rc"]) { 69 | LOTShapeRectangle *rectangle = [[LOTShapeRectangle alloc] initWithJSON:itemJSON]; 70 | return rectangle; 71 | } else if ([type isEqualToString:@"tm"]) { 72 | LOTShapeTrimPath *trim = [[LOTShapeTrimPath alloc] initWithJSON:itemJSON]; 73 | return trim; 74 | } else if ([type isEqualToString:@"gs"]) { 75 | NSLog(@"%s: Warning: gradient strokes are not supported", __PRETTY_FUNCTION__); 76 | } else if ([type isEqualToString:@"gf"]) { 77 | LOTShapeGradientFill *gradientFill = [[LOTShapeGradientFill alloc] initWithJSON:itemJSON]; 78 | return gradientFill; 79 | } else if ([type isEqualToString:@"sr"]) { 80 | LOTShapeStar *star = [[LOTShapeStar alloc] initWithJSON:itemJSON]; 81 | return star; 82 | } else if ([type isEqualToString:@"mm"]) { 83 | NSString *name = itemJSON[@"nm"]; 84 | NSLog(@"%s: Warning: merge shape is not supported. name: %@", __PRETTY_FUNCTION__, name); 85 | } else if ([type isEqualToString:@"rp"]) { 86 | LOTShapeRepeater *repeater = [[LOTShapeRepeater alloc] initWithJSON:itemJSON]; 87 | return repeater; 88 | } else { 89 | NSString *name = itemJSON[@"nm"]; 90 | NSLog(@"%s: Unsupported shape: %@ name: %@", __PRETTY_FUNCTION__, type, name); 91 | } 92 | 93 | return nil; 94 | } 95 | 96 | - (NSString *)description { 97 | NSMutableString *text = [[super description] mutableCopy]; 98 | [text appendFormat:@" items: %@", self.items]; 99 | return text; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapePath.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapePath.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | @interface LOTShapePath : NSObject 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 15 | 16 | @property (nonatomic, readonly) NSString *keyname; 17 | @property (nonatomic, readonly) BOOL closed; 18 | @property (nonatomic, readonly) NSNumber *index; 19 | @property (nonatomic, readonly) LOTKeyframeGroup *shapePath; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapePath.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapePath.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapePath.h" 10 | 11 | @implementation LOTShapePath 12 | 13 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 14 | self = [super init]; 15 | if (self) { 16 | [self _mapFromJSON:jsonDictionary]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 22 | 23 | if (jsonDictionary[@"nm"] ) { 24 | _keyname = [jsonDictionary[@"nm"] copy]; 25 | } 26 | 27 | _index = jsonDictionary[@"ind"]; 28 | _closed = [jsonDictionary[@"closed"] boolValue]; 29 | NSDictionary *shape = jsonDictionary[@"ks"]; 30 | if (shape) { 31 | _shapePath = [[LOTKeyframeGroup alloc] initWithData:shape]; 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeRectangle.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeRectangle.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | @interface LOTShapeRectangle : NSObject 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 15 | 16 | @property (nonatomic, readonly) NSString *keyname; 17 | @property (nonatomic, readonly) LOTKeyframeGroup *position; 18 | @property (nonatomic, readonly) LOTKeyframeGroup *size; 19 | @property (nonatomic, readonly) LOTKeyframeGroup *cornerRadius; 20 | @property (nonatomic, readonly) BOOL reversed; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeRectangle.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeRectangle.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeRectangle.h" 10 | 11 | @implementation LOTShapeRectangle 12 | 13 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 14 | self = [super init]; 15 | if (self) { 16 | [self _mapFromJSON:jsonDictionary]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 22 | 23 | if (jsonDictionary[@"nm"] ) { 24 | _keyname = [jsonDictionary[@"nm"] copy]; 25 | } 26 | 27 | NSDictionary *position = jsonDictionary[@"p"]; 28 | if (position) { 29 | _position = [[LOTKeyframeGroup alloc] initWithData:position]; 30 | } 31 | 32 | NSDictionary *cornerRadius = jsonDictionary[@"r"]; 33 | if (cornerRadius) { 34 | _cornerRadius = [[LOTKeyframeGroup alloc] initWithData:cornerRadius]; 35 | } 36 | 37 | NSDictionary *size = jsonDictionary[@"s"]; 38 | if (size) { 39 | _size = [[LOTKeyframeGroup alloc] initWithData:size]; 40 | } 41 | NSNumber *reversed = jsonDictionary[@"d"]; 42 | _reversed = (reversed.integerValue == 3); 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeRepeater.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeRepeater.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/28/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LOTShapeRepeater : NSObject 15 | 16 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 17 | 18 | @property (nonatomic, readonly) NSString *keyname; 19 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *copies; 20 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *offset; 21 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *anchorPoint; 22 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *scale; 23 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *position; 24 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *rotation; 25 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *startOpacity; 26 | @property (nonatomic, readonly, nullable) LOTKeyframeGroup *endOpacity; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeRepeater.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeRepeater.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/28/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeRepeater.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTShapeRepeater 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 15 | self = [super init]; 16 | if (self) { 17 | [self _mapFromJSON:jsonDictionary]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 23 | 24 | if (jsonDictionary[@"nm"] ) { 25 | _keyname = [jsonDictionary[@"nm"] copy]; 26 | } 27 | 28 | NSDictionary *copies = jsonDictionary[@"c"]; 29 | if (copies) { 30 | _copies = [[LOTKeyframeGroup alloc] initWithData:copies]; 31 | } 32 | 33 | NSDictionary *offset = jsonDictionary[@"o"]; 34 | if (offset) { 35 | _offset = [[LOTKeyframeGroup alloc] initWithData:offset]; 36 | } 37 | 38 | NSDictionary *transform = jsonDictionary[@"tr"]; 39 | 40 | NSDictionary *rotation = transform[@"r"]; 41 | if (rotation) { 42 | _rotation = [[LOTKeyframeGroup alloc] initWithData:rotation]; 43 | [_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 44 | return LOT_DegreesToRadians(inValue); 45 | }]; 46 | } 47 | 48 | NSDictionary *startOpacity = transform[@"so"]; 49 | if (startOpacity) { 50 | _startOpacity = [[LOTKeyframeGroup alloc] initWithData:startOpacity]; 51 | [_startOpacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 52 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 53 | }]; 54 | } 55 | 56 | NSDictionary *endOpacity = transform[@"eo"]; 57 | if (endOpacity) { 58 | _endOpacity = [[LOTKeyframeGroup alloc] initWithData:endOpacity]; 59 | [_endOpacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 60 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 61 | }]; 62 | } 63 | 64 | NSDictionary *anchorPoint = transform[@"a"]; 65 | if (anchorPoint) { 66 | _anchorPoint = [[LOTKeyframeGroup alloc] initWithData:anchorPoint]; 67 | } 68 | 69 | NSDictionary *position = transform[@"p"]; 70 | if (position) { 71 | _position = [[LOTKeyframeGroup alloc] initWithData:position]; 72 | } 73 | 74 | NSDictionary *scale = transform[@"s"]; 75 | if (scale) { 76 | _scale = [[LOTKeyframeGroup alloc] initWithData:scale]; 77 | [_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 78 | return LOT_RemapValue(inValue, -100, 100, -1, 1); 79 | }]; 80 | } 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeStar.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeStar.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | typedef enum : NSUInteger { 13 | LOTPolystarShapeNone, 14 | LOTPolystarShapeStar, 15 | LOTPolystarShapePolygon 16 | } LOTPolystarShape; 17 | 18 | @interface LOTShapeStar : NSObject 19 | 20 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 21 | 22 | @property (nonatomic, readonly) NSString *keyname; 23 | @property (nonatomic, readonly) LOTKeyframeGroup *outerRadius; 24 | @property (nonatomic, readonly) LOTKeyframeGroup *outerRoundness; 25 | 26 | @property (nonatomic, readonly) LOTKeyframeGroup *innerRadius; 27 | @property (nonatomic, readonly) LOTKeyframeGroup *innerRoundness; 28 | 29 | @property (nonatomic, readonly) LOTKeyframeGroup *position; 30 | @property (nonatomic, readonly) LOTKeyframeGroup *numberOfPoints; 31 | @property (nonatomic, readonly) LOTKeyframeGroup *rotation; 32 | 33 | @property (nonatomic, readonly) LOTPolystarShape type; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeStar.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeStar.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeStar.h" 10 | 11 | @implementation LOTShapeStar 12 | 13 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 14 | self = [super init]; 15 | if (self) { 16 | [self _mapFromJSON:jsonDictionary]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 22 | 23 | if (jsonDictionary[@"nm"] ) { 24 | _keyname = [jsonDictionary[@"nm"] copy]; 25 | } 26 | 27 | NSDictionary *outerRadius = jsonDictionary[@"or"]; 28 | if (outerRadius) { 29 | _outerRadius = [[LOTKeyframeGroup alloc] initWithData:outerRadius]; 30 | } 31 | 32 | NSDictionary *outerRoundness = jsonDictionary[@"os"]; 33 | if (outerRoundness) { 34 | _outerRoundness = [[LOTKeyframeGroup alloc] initWithData:outerRoundness]; 35 | } 36 | 37 | NSDictionary *innerRadius = jsonDictionary[@"ir"]; 38 | if (innerRadius) { 39 | _innerRadius = [[LOTKeyframeGroup alloc] initWithData:innerRadius]; 40 | } 41 | 42 | NSDictionary *innerRoundness = jsonDictionary[@"is"]; 43 | if (innerRoundness) { 44 | _innerRoundness = [[LOTKeyframeGroup alloc] initWithData:innerRoundness]; 45 | } 46 | 47 | NSDictionary *position = jsonDictionary[@"p"]; 48 | if (position) { 49 | _position = [[LOTKeyframeGroup alloc] initWithData:position]; 50 | } 51 | 52 | NSDictionary *numberOfPoints = jsonDictionary[@"pt"]; 53 | if (numberOfPoints) { 54 | _numberOfPoints = [[LOTKeyframeGroup alloc] initWithData:numberOfPoints]; 55 | } 56 | 57 | NSDictionary *rotation = jsonDictionary[@"r"]; 58 | if (rotation) { 59 | _rotation = [[LOTKeyframeGroup alloc] initWithData:rotation]; 60 | } 61 | 62 | NSNumber *type = jsonDictionary[@"sy"]; 63 | _type = type.integerValue; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeStroke.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeStroke.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | typedef enum : NSUInteger { 13 | LOTLineCapTypeButt, 14 | LOTLineCapTypeRound, 15 | LOTLineCapTypeUnknown 16 | } LOTLineCapType; 17 | 18 | typedef enum : NSUInteger { 19 | LOTLineJoinTypeMiter, 20 | LOTLineJoinTypeRound, 21 | LOTLineJoinTypeBevel 22 | } LOTLineJoinType; 23 | 24 | @interface LOTShapeStroke : NSObject 25 | 26 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 27 | 28 | @property (nonatomic, readonly) NSString *keyname; 29 | @property (nonatomic, readonly) BOOL fillEnabled; 30 | @property (nonatomic, readonly) LOTKeyframeGroup *color; 31 | @property (nonatomic, readonly) LOTKeyframeGroup *opacity; 32 | @property (nonatomic, readonly) LOTKeyframeGroup *width; 33 | @property (nonatomic, readonly) LOTKeyframeGroup *dashOffset; 34 | @property (nonatomic, readonly) LOTLineCapType capType; 35 | @property (nonatomic, readonly) LOTLineJoinType joinType; 36 | 37 | @property (nonatomic, readonly) NSArray *lineDashPattern; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeStroke.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeStroke.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeStroke.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTShapeStroke 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 15 | self = [super init]; 16 | if (self) { 17 | [self _mapFromJSON:jsonDictionary]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 23 | 24 | if (jsonDictionary[@"nm"] ) { 25 | _keyname = [jsonDictionary[@"nm"] copy]; 26 | } 27 | 28 | NSDictionary *color = jsonDictionary[@"c"]; 29 | if (color) { 30 | _color = [[LOTKeyframeGroup alloc] initWithData:color]; 31 | } 32 | 33 | NSDictionary *width = jsonDictionary[@"w"]; 34 | if (width) { 35 | _width = [[LOTKeyframeGroup alloc] initWithData:width]; 36 | } 37 | 38 | NSDictionary *opacity = jsonDictionary[@"o"]; 39 | if (opacity) { 40 | _opacity = [[LOTKeyframeGroup alloc] initWithData:opacity]; 41 | [_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 42 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 43 | }]; 44 | } 45 | 46 | _capType = [jsonDictionary[@"lc"] integerValue] - 1; 47 | _joinType = [jsonDictionary[@"lj"] integerValue] - 1; 48 | 49 | NSNumber *fillEnabled = jsonDictionary[@"fillEnabled"]; 50 | _fillEnabled = fillEnabled.boolValue; 51 | 52 | NSDictionary *dashOffset = nil; 53 | NSArray *dashes = jsonDictionary[@"d"]; 54 | if (dashes) { 55 | NSMutableArray *dashPattern = [NSMutableArray array]; 56 | for (NSDictionary *dash in dashes) { 57 | if ([dash[@"n"] isEqualToString:@"o"]) { 58 | dashOffset = dash[@"v"]; 59 | continue; 60 | } 61 | // TODO DASH PATTERNS 62 | NSDictionary *value = dash[@"v"]; 63 | LOTKeyframeGroup *keyframeGroup = [[LOTKeyframeGroup alloc] initWithData:value]; 64 | [dashPattern addObject:keyframeGroup]; 65 | } 66 | _lineDashPattern = dashPattern; 67 | } 68 | if (dashOffset) { 69 | _dashOffset = [[LOTKeyframeGroup alloc] initWithData:dashOffset]; 70 | } 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeTransform.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeTransform.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import "LOTKeyframe.h" 13 | 14 | @interface LOTShapeTransform : NSObject 15 | 16 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 17 | 18 | @property (nonatomic, readonly) NSString *keyname; 19 | @property (nonatomic, readonly) LOTKeyframeGroup *position; 20 | @property (nonatomic, readonly) LOTKeyframeGroup *anchor; 21 | @property (nonatomic, readonly) LOTKeyframeGroup *scale; 22 | @property (nonatomic, readonly) LOTKeyframeGroup *rotation; 23 | @property (nonatomic, readonly) LOTKeyframeGroup *opacity; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeTransform.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeTransform.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/15/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeTransform.h" 10 | #import "LOTHelpers.h" 11 | 12 | @implementation LOTShapeTransform 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 15 | self = [super init]; 16 | if (self) { 17 | [self _mapFromJSON:jsonDictionary]; 18 | } 19 | return self; 20 | } 21 | 22 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 23 | 24 | if (jsonDictionary[@"nm"] ) { 25 | _keyname = [jsonDictionary[@"nm"] copy]; 26 | } 27 | 28 | NSDictionary *position = jsonDictionary[@"p"]; 29 | if (position) { 30 | _position = [[LOTKeyframeGroup alloc] initWithData:position]; 31 | } 32 | 33 | NSDictionary *anchor = jsonDictionary[@"a"]; 34 | if (anchor) { 35 | _anchor = [[LOTKeyframeGroup alloc] initWithData:anchor]; 36 | } 37 | 38 | NSDictionary *scale = jsonDictionary[@"s"]; 39 | if (scale) { 40 | _scale = [[LOTKeyframeGroup alloc] initWithData:scale]; 41 | [_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 42 | return LOT_RemapValue(inValue, -100, 100, -1, 1); 43 | }]; 44 | } 45 | 46 | NSDictionary *rotation = jsonDictionary[@"r"]; 47 | if (rotation) { 48 | _rotation = [[LOTKeyframeGroup alloc] initWithData:rotation]; 49 | [_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 50 | return LOT_DegreesToRadians(inValue); 51 | }]; 52 | } 53 | 54 | NSDictionary *opacity = jsonDictionary[@"o"]; 55 | if (opacity) { 56 | _opacity = [[LOTKeyframeGroup alloc] initWithData:opacity]; 57 | [_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) { 58 | return LOT_RemapValue(inValue, 0, 100, 0, 1); 59 | }]; 60 | } 61 | 62 | NSString *name = jsonDictionary[@"nm"]; 63 | 64 | NSDictionary *skew = jsonDictionary[@"sk"]; 65 | BOOL hasSkew = (skew && [skew[@"k"] isEqual:@0] == NO); 66 | NSDictionary *skewAxis = jsonDictionary[@"sa"]; 67 | BOOL hasSkewAxis = (skewAxis && [skewAxis[@"k"] isEqual:@0] == NO); 68 | 69 | if (hasSkew || hasSkewAxis) { 70 | NSLog(@"%s: Warning: skew is not supported: %@", __PRETTY_FUNCTION__, name); 71 | } 72 | } 73 | 74 | - (NSString *)description { 75 | return [NSString stringWithFormat:@"LOTShapeTransform \"Position: %@ Anchor: %@ Scale: %@ Rotation: %@ Opacity: %@\"", _position.description, _anchor.description, _scale.description, _rotation.description, _opacity.description]; 76 | } 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeTrimPath.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeTrimPath.h 3 | // LottieAnimator 4 | // 5 | // Created by brandon_withrow on 7/26/16. 6 | // Copyright © 2016 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | 12 | @interface LOTShapeTrimPath : NSObject 13 | 14 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary; 15 | 16 | @property (nonatomic, readonly) NSString *keyname; 17 | @property (nonatomic, readonly) LOTKeyframeGroup *start; 18 | @property (nonatomic, readonly) LOTKeyframeGroup *end; 19 | @property (nonatomic, readonly) LOTKeyframeGroup *offset; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Models/LOTShapeTrimPath.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTShapeTrimPath.m 3 | // LottieAnimator 4 | // 5 | // Created by brandon_withrow on 7/26/16. 6 | // Copyright © 2016 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTShapeTrimPath.h" 10 | 11 | @implementation LOTShapeTrimPath 12 | 13 | - (instancetype)initWithJSON:(NSDictionary *)jsonDictionary { 14 | self = [super init]; 15 | if (self) { 16 | [self _mapFromJSON:jsonDictionary]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary { 22 | 23 | if (jsonDictionary[@"nm"] ) { 24 | _keyname = [jsonDictionary[@"nm"] copy]; 25 | } 26 | 27 | NSDictionary *start = jsonDictionary[@"s"]; 28 | if (start) { 29 | _start = [[LOTKeyframeGroup alloc] initWithData:start]; 30 | } 31 | 32 | NSDictionary *end = jsonDictionary[@"e"]; 33 | if (end) { 34 | _end = [[LOTKeyframeGroup alloc] initWithData:end]; 35 | } 36 | 37 | NSDictionary *offset = jsonDictionary[@"o"]; 38 | if (offset) { 39 | _offset = [[LOTKeyframeGroup alloc] initWithData:offset]; 40 | } 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTAnimatedControl.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimatedControl.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 8/25/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimatedControl.h" 10 | #import "LOTAnimationView_Internal.h" 11 | 12 | @implementation LOTAnimatedControl { 13 | UIControlState _priorState; 14 | NSMutableDictionary *_layerMap; 15 | } 16 | 17 | - (instancetype)initWithFrame:(CGRect)frame { 18 | self = [super initWithFrame:frame]; 19 | if (self) { 20 | [self _commonInit]; 21 | } 22 | return self; 23 | } 24 | 25 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 26 | self = [super initWithCoder:aDecoder]; 27 | if (self) { 28 | [self _commonInit]; 29 | } 30 | return self; 31 | } 32 | 33 | - (void)_commonInit { 34 | _animationView = [[LOTAnimationView alloc] init]; 35 | _animationView.contentMode = UIViewContentModeScaleAspectFit; 36 | _animationView.userInteractionEnabled = NO; 37 | [self addSubview:_animationView]; 38 | _layerMap = [NSMutableDictionary dictionary]; 39 | } 40 | 41 | - (LOTComposition *)animationComp { 42 | return _animationView.sceneModel; 43 | } 44 | 45 | - (void)setAnimationComp:(LOTComposition *)animationComp { 46 | [_animationView setSceneModel:animationComp]; 47 | [self checkStateChangedAndUpdate:YES]; 48 | } 49 | 50 | - (void)setLayerName:(NSString * _Nonnull)layerName forState:(UIControlState)state { 51 | _layerMap[@(state)] = layerName; 52 | [self checkStateChangedAndUpdate:YES]; 53 | } 54 | 55 | #pragma mark - Setter Overrides 56 | 57 | - (void)setEnabled:(BOOL)enabled { 58 | _priorState = self.state; 59 | [super setEnabled:enabled]; 60 | [self checkStateChangedAndUpdate:NO]; 61 | } 62 | 63 | - (void)setSelected:(BOOL)selected { 64 | _priorState = self.state; 65 | [super setSelected:selected]; 66 | [self checkStateChangedAndUpdate:NO]; 67 | } 68 | 69 | - (void)setHighlighted:(BOOL)highlighted { 70 | _priorState = self.state; 71 | [super setHighlighted:highlighted]; 72 | [self checkStateChangedAndUpdate:NO]; 73 | } 74 | 75 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 76 | _priorState = self.state; 77 | [super touchesBegan:touches withEvent:event]; 78 | [self checkStateChangedAndUpdate:NO]; 79 | } 80 | 81 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 82 | _priorState = self.state; 83 | [super touchesMoved:touches withEvent:event]; 84 | [self checkStateChangedAndUpdate:NO]; 85 | } 86 | 87 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 88 | _priorState = self.state; 89 | [super touchesEnded:touches withEvent:event]; 90 | [self checkStateChangedAndUpdate:NO]; 91 | } 92 | 93 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { 94 | _priorState = self.state; 95 | [super touchesCancelled:touches withEvent:event]; 96 | [self checkStateChangedAndUpdate:NO]; 97 | } 98 | 99 | - (CGSize)intrinsicContentSize { 100 | return _animationView.intrinsicContentSize; 101 | } 102 | 103 | - (void)layoutSubviews { 104 | [super layoutSubviews]; 105 | _animationView.frame = self.bounds; 106 | } 107 | 108 | - (UIAccessibilityTraits)accessibilityTraits { 109 | return UIAccessibilityTraitButton; 110 | } 111 | 112 | - (BOOL)isAccessibilityElement 113 | { 114 | return YES; 115 | } 116 | 117 | #pragma mark - Private interface implementation 118 | 119 | - (void)checkStateChangedAndUpdate:(BOOL)forceUpdate { 120 | if (self.state == _priorState && !forceUpdate) { 121 | return; 122 | } 123 | _priorState = self.state; 124 | 125 | NSString *name = _layerMap[@(self.state)]; 126 | if (!name) { 127 | return; 128 | } 129 | CALayer *layer = [_animationView layerForKey:name]; 130 | if (!layer) { 131 | return; 132 | } 133 | 134 | for (CALayer *child in [_animationView compositionLayers]) { 135 | child.hidden = YES; 136 | } 137 | layer.hidden = NO; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTAnimationCache.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationCache.m 3 | // Lottie 4 | // 5 | // Created by Brandon Withrow on 1/9/17. 6 | // Copyright © 2017 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimationCache.h" 10 | 11 | const NSInteger kLOTCacheSize = 50; 12 | 13 | @implementation LOTAnimationCache { 14 | NSMutableDictionary *animationsCache_; 15 | NSMutableArray *lruOrderArray_; 16 | } 17 | 18 | + (instancetype)sharedCache { 19 | static LOTAnimationCache *sharedCache = nil; 20 | static dispatch_once_t onceToken; 21 | dispatch_once(&onceToken, ^{ 22 | sharedCache = [[self alloc] init]; 23 | }); 24 | return sharedCache; 25 | } 26 | 27 | - (instancetype)init { 28 | self = [super init]; 29 | if (self) { 30 | animationsCache_ = [[NSMutableDictionary alloc] init]; 31 | lruOrderArray_ = [[NSMutableArray alloc] init]; 32 | } 33 | return self; 34 | } 35 | 36 | - (void)addAnimation:(LOTComposition *)animation forKey:(NSString *)key { 37 | if (lruOrderArray_.count >= kLOTCacheSize) { 38 | NSString *oldKey = lruOrderArray_[0]; 39 | [animationsCache_ removeObjectForKey:oldKey]; 40 | [lruOrderArray_ removeObject:oldKey]; 41 | } 42 | [lruOrderArray_ removeObject:key]; 43 | [lruOrderArray_ addObject:key]; 44 | [animationsCache_ setObject:animation forKey:key]; 45 | } 46 | 47 | - (LOTComposition *)animationForKey:(NSString *)key { 48 | if (!key) { 49 | return nil; 50 | } 51 | LOTComposition *animation = [animationsCache_ objectForKey:key]; 52 | [lruOrderArray_ removeObject:key]; 53 | [lruOrderArray_ addObject:key]; 54 | return animation; 55 | } 56 | 57 | - (void)clearCache { 58 | [animationsCache_ removeAllObjects]; 59 | [lruOrderArray_ removeAllObjects]; 60 | } 61 | 62 | - (void)removeAnimationForKey:(NSString *)key { 63 | [lruOrderArray_ removeObject:key]; 64 | [animationsCache_ removeObjectForKey:key]; 65 | } 66 | 67 | - (void)disableCaching { 68 | [self clearCache]; 69 | animationsCache_ = nil; 70 | lruOrderArray_ = nil; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTAnimationTransitionController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationTransitionController.m 3 | // Lottie 4 | // 5 | // Created by Brandon Withrow on 1/18/17. 6 | // Copyright © 2017 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimationTransitionController.h" 10 | #import "LOTAnimationView.h" 11 | 12 | @implementation LOTAnimationTransitionController { 13 | LOTAnimationView *transitionAnimationView_; 14 | NSString *fromLayerName_; 15 | NSString *toLayerName_; 16 | NSBundle *inBundle_; 17 | BOOL _applyTransform; 18 | } 19 | 20 | - (nonnull instancetype)initWithAnimationNamed:(nonnull NSString *)animation 21 | fromLayerNamed:(nullable NSString *)fromLayer 22 | toLayerNamed:(nullable NSString *)toLayer 23 | applyAnimationTransform:(BOOL)applyAnimationTransform { 24 | 25 | return [self initWithAnimationNamed:animation 26 | fromLayerNamed:fromLayer 27 | toLayerNamed:toLayer 28 | applyAnimationTransform:applyAnimationTransform 29 | inBundle:[NSBundle mainBundle]]; 30 | } 31 | 32 | - (instancetype)initWithAnimationNamed:(NSString *)animation 33 | fromLayerNamed:(NSString *)fromLayer 34 | toLayerNamed:(NSString *)toLayer 35 | applyAnimationTransform:(BOOL)applyAnimationTransform 36 | inBundle:(NSBundle *)bundle { 37 | self = [super init]; 38 | if (self) { 39 | transitionAnimationView_ = [LOTAnimationView animationNamed:animation inBundle:bundle]; 40 | fromLayerName_ = fromLayer; 41 | toLayerName_ = toLayer; 42 | _applyTransform = applyAnimationTransform; 43 | } 44 | return self; 45 | } 46 | 47 | - (NSTimeInterval)transitionDuration:(id)transitionContext { 48 | return transitionAnimationView_.animationDuration; 49 | } 50 | 51 | - (void)animateTransition:(id)transitionContext { 52 | UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 53 | UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 54 | UIView *containerView = transitionContext.containerView; 55 | 56 | UIView *toSnapshot = [toVC.view resizableSnapshotViewFromRect:containerView.bounds 57 | afterScreenUpdates:YES 58 | withCapInsets:UIEdgeInsetsZero]; 59 | toSnapshot.frame = containerView.bounds; 60 | 61 | UIView *fromSnapshot = [fromVC.view resizableSnapshotViewFromRect:containerView.bounds 62 | afterScreenUpdates:NO 63 | withCapInsets:UIEdgeInsetsZero]; 64 | fromSnapshot.frame = containerView.bounds; 65 | 66 | transitionAnimationView_.frame = containerView.bounds; 67 | transitionAnimationView_.contentMode = UIViewContentModeScaleAspectFill; 68 | [containerView addSubview:transitionAnimationView_]; 69 | 70 | BOOL crossFadeViews = NO; 71 | 72 | if (toLayerName_.length) { 73 | LOTKeypath *toKeypath = [LOTKeypath keypathWithString:toLayerName_]; 74 | CGRect convertedBounds = [transitionAnimationView_ convertRect:containerView.bounds toKeypathLayer:toKeypath]; 75 | toSnapshot.frame = convertedBounds; 76 | if (_applyTransform) { 77 | [transitionAnimationView_ addSubview:toSnapshot toKeypathLayer:toKeypath]; 78 | } else { 79 | [transitionAnimationView_ maskSubview:toSnapshot toKeypathLayer:toKeypath]; 80 | } 81 | } else { 82 | [containerView addSubview:toSnapshot]; 83 | [containerView sendSubviewToBack:toSnapshot]; 84 | toSnapshot.alpha = 0; 85 | crossFadeViews = YES; 86 | } 87 | 88 | if (fromLayerName_.length) { 89 | LOTKeypath *fromKeypath = [LOTKeypath keypathWithString:fromLayerName_]; 90 | CGRect convertedBounds = [transitionAnimationView_ convertRect:containerView.bounds fromKeypathLayer:fromKeypath]; 91 | fromSnapshot.frame = convertedBounds; 92 | if (_applyTransform) { 93 | [transitionAnimationView_ addSubview:fromSnapshot toKeypathLayer:fromKeypath]; 94 | } else { 95 | [transitionAnimationView_ maskSubview:fromSnapshot toKeypathLayer:fromKeypath]; 96 | } 97 | } else { 98 | [containerView addSubview:fromSnapshot]; 99 | [containerView sendSubviewToBack:fromSnapshot]; 100 | } 101 | 102 | [containerView addSubview:toVC.view]; 103 | toVC.view.hidden = YES; 104 | 105 | if (crossFadeViews) { 106 | CGFloat duration = transitionAnimationView_.animationDuration * 0.25; 107 | CGFloat delay = (transitionAnimationView_.animationDuration - duration) / 2.f; 108 | 109 | [UIView animateWithDuration:duration 110 | delay:delay 111 | options:(UIViewAnimationOptionCurveEaseInOut) 112 | animations:^{ 113 | toSnapshot.alpha = 1; 114 | } completion:^(BOOL finished) { 115 | 116 | }]; 117 | } 118 | 119 | [transitionAnimationView_ playWithCompletion:^(BOOL animationFinished) { 120 | toVC.view.hidden = false; 121 | [self->transitionAnimationView_ removeFromSuperview]; 122 | [transitionContext completeTransition:animationFinished]; 123 | }]; 124 | } 125 | 126 | @end 127 | 128 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTAnimationView_Internal.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationView_Internal.h 3 | // Lottie 4 | // 5 | // Created by Brandon Withrow on 12/7/16. 6 | // Copyright © 2016 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimationView.h" 10 | 11 | typedef enum : NSUInteger { 12 | LOTConstraintTypeAlignToBounds, 13 | LOTConstraintTypeAlignToLayer, 14 | LOTConstraintTypeNone 15 | } LOTConstraintType; 16 | 17 | @interface LOTAnimationView () 18 | 19 | - (CALayer * _Nullable)layerForKey:(NSString * _Nonnull)keyname; 20 | - (NSArray * _Nonnull)compositionLayers; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTBlockCallback.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTBlockCallback.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 12/15/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTBlockCallback.h" 10 | 11 | @implementation LOTColorBlockCallback 12 | 13 | + (instancetype)withBlock:(LOTColorValueCallbackBlock)block { 14 | LOTColorBlockCallback *colorCallback = [[self alloc] init]; 15 | colorCallback.callback = block; 16 | return colorCallback; 17 | } 18 | 19 | - (CGColorRef)colorForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startColor:(CGColorRef)startColor endColor:(CGColorRef)endColor currentColor:(CGColorRef)interpolatedColor { 20 | return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startColor, endColor, interpolatedColor); 21 | } 22 | 23 | @end 24 | 25 | @implementation LOTNumberBlockCallback 26 | 27 | + (instancetype)withBlock:(LOTNumberValueCallbackBlock)block { 28 | LOTNumberBlockCallback *numberCallback = [[self alloc] init]; 29 | numberCallback.callback = block; 30 | return numberCallback; 31 | } 32 | 33 | - (CGFloat)floatValueForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startValue:(CGFloat)startValue endValue:(CGFloat)endValue currentValue:(CGFloat)interpolatedValue { 34 | return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startValue, endValue, interpolatedValue); 35 | } 36 | 37 | @end 38 | 39 | @implementation LOTPointBlockCallback 40 | 41 | + (instancetype)withBlock:(LOTPointValueCallbackBlock)block { 42 | LOTPointBlockCallback *callback = [[self alloc] init]; 43 | callback.callback = block; 44 | return callback; 45 | } 46 | 47 | - (CGPoint)pointForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint currentPoint:(CGPoint)interpolatedPoint { 48 | return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startPoint, endPoint, interpolatedPoint); 49 | } 50 | 51 | @end 52 | 53 | @implementation LOTSizeBlockCallback 54 | 55 | + (instancetype)withBlock:(LOTSizeValueCallbackBlock)block { 56 | LOTSizeBlockCallback *callback = [[self alloc] init]; 57 | callback.callback = block; 58 | return callback; 59 | } 60 | 61 | - (CGSize)sizeForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startSize:(CGSize)startSize endSize:(CGSize)endSize currentSize:(CGSize)interpolatedSize { 62 | return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress, startSize, endSize, interpolatedSize); 63 | } 64 | 65 | @end 66 | 67 | @implementation LOTPathBlockCallback 68 | 69 | + (instancetype)withBlock:(LOTPathValueCallbackBlock)block { 70 | LOTPathBlockCallback *callback = [[self alloc] init]; 71 | callback.callback = block; 72 | return callback; 73 | } 74 | 75 | - (CGPathRef)pathForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress { 76 | return self.callback(currentFrame, startKeyframe, endKeyframe, interpolatedProgress); 77 | } 78 | 79 | @end 80 | 81 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTCacheProvider.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTCacheProvider.m 3 | // Lottie 4 | // 5 | // Created by punmy on 2017/7/8. 6 | // 7 | // 8 | 9 | #import "LOTCacheProvider.h" 10 | 11 | @implementation LOTCacheProvider 12 | 13 | static id _imageCache; 14 | 15 | + (id)imageCache { 16 | return _imageCache; 17 | } 18 | 19 | + (void)setImageCache:(id)cache { 20 | _imageCache = cache; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTComposition.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTScene.m 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import "LOTComposition.h" 10 | #import "LOTLayer.h" 11 | #import "LOTAssetGroup.h" 12 | #import "LOTLayerGroup.h" 13 | #import "LOTAnimationCache.h" 14 | 15 | @implementation LOTComposition 16 | 17 | # pragma mark - Convenience Initializers 18 | 19 | + (nullable instancetype)animationNamed:(nonnull NSString *)animationName { 20 | return [self animationNamed:animationName inBundle:[NSBundle mainBundle]]; 21 | } 22 | 23 | + (nullable instancetype)animationNamed:(nonnull NSString *)animationName inBundle:(nonnull NSBundle *)bundle { 24 | if (!animationName) { 25 | return nil; 26 | } 27 | NSArray *components = [animationName componentsSeparatedByString:@"."]; 28 | animationName = components.firstObject; 29 | 30 | LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName]; 31 | if (comp) { 32 | return comp; 33 | } 34 | 35 | NSError *error; 36 | NSString *filePath = [bundle pathForResource:animationName ofType:@"json"]; 37 | NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath]; 38 | 39 | if (@available(iOS 9.0, *)) { 40 | if (!jsonData) { 41 | jsonData = [[NSDataAsset alloc] initWithName:animationName bundle:bundle].data; 42 | } 43 | } 44 | 45 | NSDictionary *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData 46 | options:0 error:&error] : nil; 47 | if (JSONObject && !error) { 48 | LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:bundle]; 49 | [[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName]; 50 | laScene.cacheKey = animationName; 51 | return laScene; 52 | } 53 | NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__); 54 | return nil; 55 | } 56 | 57 | + (nullable instancetype)animationWithFilePath:(nonnull NSString *)filePath { 58 | NSString *animationName = filePath; 59 | 60 | LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName]; 61 | if (comp) { 62 | return comp; 63 | } 64 | 65 | NSError *error; 66 | NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath]; 67 | NSDictionary *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData 68 | options:0 error:&error] : nil; 69 | if (JSONObject && !error) { 70 | LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:[NSBundle mainBundle]]; 71 | laScene.rootDirectory = [filePath stringByDeletingLastPathComponent]; 72 | [[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName]; 73 | laScene.cacheKey = animationName; 74 | return laScene; 75 | } 76 | 77 | NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__); 78 | return nil; 79 | } 80 | 81 | + (nonnull instancetype)animationFromJSON:(nonnull NSDictionary *)animationJSON { 82 | return [self animationFromJSON:animationJSON inBundle:[NSBundle mainBundle]]; 83 | } 84 | 85 | + (nonnull instancetype)animationFromJSON:(nullable NSDictionary *)animationJSON inBundle:(nullable NSBundle *)bundle { 86 | return [[self alloc] initWithJSON:animationJSON withAssetBundle:bundle]; 87 | } 88 | 89 | #pragma mark - Initializer 90 | 91 | - (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nullable)jsonDictionary 92 | withAssetBundle:(NSBundle * _Nullable)bundle { 93 | self = [super init]; 94 | if (self) { 95 | if (jsonDictionary) { 96 | [self _mapFromJSON:jsonDictionary withAssetBundle:bundle]; 97 | } 98 | } 99 | return self; 100 | } 101 | 102 | #pragma mark - Internal Methods 103 | 104 | - (void)_mapFromJSON:(NSDictionary *)jsonDictionary 105 | withAssetBundle:(NSBundle *)bundle { 106 | NSNumber *width = jsonDictionary[@"w"]; 107 | NSNumber *height = jsonDictionary[@"h"]; 108 | if (width && height) { 109 | CGRect bounds = CGRectMake(0, 0, width.floatValue, height.floatValue); 110 | _compBounds = bounds; 111 | } 112 | 113 | _startFrame = [jsonDictionary[@"ip"] copy]; 114 | _endFrame = [jsonDictionary[@"op"] copy]; 115 | _framerate = [jsonDictionary[@"fr"] copy]; 116 | 117 | if (_startFrame && _endFrame && _framerate) { 118 | NSInteger frameDuration = (_endFrame.integerValue - _startFrame.integerValue) - 1; 119 | NSTimeInterval timeDuration = frameDuration / _framerate.floatValue; 120 | _timeDuration = timeDuration; 121 | } 122 | 123 | NSArray *assetArray = jsonDictionary[@"assets"]; 124 | if (assetArray.count) { 125 | _assetGroup = [[LOTAssetGroup alloc] initWithJSON:assetArray withAssetBundle:bundle withFramerate:_framerate]; 126 | } 127 | 128 | NSArray *layersJSON = jsonDictionary[@"layers"]; 129 | if (layersJSON) { 130 | _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON 131 | withAssetGroup:_assetGroup 132 | withFramerate:_framerate]; 133 | } 134 | 135 | [_assetGroup finalizeInitializationWithFramerate:_framerate]; 136 | } 137 | 138 | - (void)setRootDirectory:(NSString *)rootDirectory { 139 | _rootDirectory = rootDirectory; 140 | self.assetGroup.rootDirectory = rootDirectory; 141 | } 142 | 143 | @end 144 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTInterpolatorCallback.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTInterpolatorCallback.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 1/5/18. 6 | // Copyright © 2018 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTInterpolatorCallback.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTFloatInterpolatorCallback 13 | 14 | + (instancetype _Nonnull)withFromFloat:(CGFloat)fromFloat toFloat:(CGFloat)toFloat { 15 | LOTFloatInterpolatorCallback *interpolator = [[self alloc] init]; 16 | interpolator.fromFloat = fromFloat; 17 | interpolator.toFloat = toFloat; 18 | return interpolator; 19 | } 20 | - (CGFloat)floatValueForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startValue:(CGFloat)startValue endValue:(CGFloat)endValue currentValue:(CGFloat)interpolatedValue { 21 | return LOT_RemapValue(self.currentProgress, 0, 1, self.fromFloat, self.toFloat); 22 | } 23 | 24 | @end 25 | 26 | @implementation LOTPointInterpolatorCallback 27 | 28 | + (instancetype _Nonnull)withFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint { 29 | LOTPointInterpolatorCallback *interpolator = [[self alloc] init]; 30 | interpolator.fromPoint = fromPoint; 31 | interpolator.toPoint = toPoint; 32 | return interpolator; 33 | } 34 | - (CGPoint)pointForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint currentPoint:(CGPoint)interpolatedPoint { 35 | return LOT_PointInLine(self.fromPoint, self.toPoint, self.currentProgress); 36 | } 37 | 38 | @end 39 | 40 | @implementation LOTSizeInterpolatorCallback 41 | 42 | + (instancetype)withFromSize:(CGSize)fromSize toSize:(CGSize)toSize { 43 | LOTSizeInterpolatorCallback *interpolator = [[self alloc] init]; 44 | interpolator.fromSize = fromSize; 45 | interpolator.toSize = toSize; 46 | return interpolator; 47 | } 48 | 49 | - (CGSize)sizeForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startSize:(CGSize)startSize endSize:(CGSize)endSize currentSize:(CGSize)interpolatedSize { 50 | CGPoint from = CGPointMake(self.fromSize.width, self.fromSize.height); 51 | CGPoint to = CGPointMake(self.toSize.width, self.toSize.height); 52 | CGPoint returnPoint = LOT_PointInLine(from, to, self.currentProgress); 53 | return CGSizeMake(returnPoint.x, returnPoint.y); 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTKeypath.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTKeypath.m 3 | // Lottie_iOS 4 | // 5 | // Created by brandon_withrow on 12/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTKeypath.h" 10 | 11 | NSString *const kLOTKeypathEnd = @"LOTENDKEYPATH"; 12 | 13 | @implementation LOTKeypath { 14 | NSInteger _currentDepth; 15 | NSMutableArray *_fuzzyDepthStack; 16 | NSMutableArray *_currentStack; 17 | NSArray *_keys; 18 | NSMutableDictionary *_searchResults; 19 | } 20 | 21 | + (nonnull LOTKeypath *)keypathWithString:(nonnull NSString *)keypath { 22 | return [[self alloc] initWithKeys:[keypath componentsSeparatedByString:@"."]]; 23 | } 24 | 25 | + (nonnull LOTKeypath *)keypathWithKeys:(nonnull NSString *)firstKey, ... { 26 | NSMutableArray *keys = [NSMutableArray array]; 27 | va_list args; 28 | va_start(args, firstKey); 29 | for (NSString *arg = firstKey; arg != nil; arg = va_arg(args, NSString*)) 30 | { 31 | [keys addObject:arg]; 32 | } 33 | va_end(args); 34 | return [[self alloc] initWithKeys:keys]; 35 | } 36 | 37 | - (instancetype)initWithKeys:(NSArray *)keys { 38 | self = [super init]; 39 | if (self) { 40 | _keys = [NSArray arrayWithArray:keys]; 41 | NSMutableString *absolutePath = [NSMutableString string]; 42 | for (int i = 0; i < _keys.count; i++) { 43 | if (i > 0) { 44 | [absolutePath appendString:@"."]; 45 | } 46 | [absolutePath appendString:_keys[i]]; 47 | } 48 | _currentStack = [NSMutableArray array]; 49 | _absoluteKeypath = absolutePath; 50 | _currentDepth = 0; 51 | _fuzzyDepthStack = [NSMutableArray array]; 52 | _searchResults = [NSMutableDictionary dictionary]; 53 | } 54 | return self; 55 | } 56 | 57 | - (BOOL)pushKey:(nonnull NSString *)key { 58 | if (_currentDepth == _keys.count && 59 | self.hasFuzzyWildcard == NO) { 60 | return NO; 61 | } 62 | NSString *current = self.currentKey; 63 | if (self.hasWildcard || 64 | [current isEqualToString:key]) { 65 | [_currentStack addObject:[key copy]]; 66 | _currentDepth ++; 67 | if (self.hasFuzzyWildcard) { 68 | [_fuzzyDepthStack addObject:@(_currentDepth)]; 69 | } 70 | return YES; 71 | } else if (self.hasFuzzyWildcard) { 72 | [_currentStack addObject:[key copy]]; 73 | return YES; 74 | } 75 | return NO; 76 | } 77 | 78 | - (void)popKey { 79 | if (_currentDepth == 0) { 80 | return; 81 | } 82 | NSInteger stackCount = _currentStack.count; 83 | [_currentStack removeLastObject]; 84 | 85 | if (self.hasFuzzyWildcard ) { 86 | if (stackCount == _fuzzyDepthStack.lastObject.integerValue) { 87 | [_fuzzyDepthStack removeLastObject]; 88 | } else { 89 | return; 90 | } 91 | } 92 | _currentDepth --; 93 | } 94 | 95 | - (void)popToRootKey { 96 | _currentDepth = 0; 97 | [_currentStack removeAllObjects]; 98 | [_fuzzyDepthStack removeAllObjects]; 99 | } 100 | 101 | - (NSString *)currentKey { 102 | if (_currentDepth == _keys.count) { 103 | return kLOTKeypathEnd; 104 | } 105 | return _keys[_currentDepth]; 106 | } 107 | 108 | - (NSString *)currentKeyPath { 109 | return [_currentStack componentsJoinedByString:@"."]; 110 | } 111 | 112 | - (BOOL)hasWildcard { 113 | if (_currentDepth == _keys.count) { 114 | return NO; 115 | } 116 | return ([_keys[_currentDepth] isEqualToString:@"**"] || 117 | [_keys[_currentDepth] isEqualToString:@"*"]); 118 | } 119 | 120 | - (BOOL)hasFuzzyWildcard { 121 | if (_currentDepth == 0 || 122 | _currentDepth > _keys.count) { 123 | return NO; 124 | } 125 | return [_keys[_currentDepth - 1] isEqualToString:@"**"]; 126 | } 127 | 128 | - (BOOL)endOfKeypath { 129 | return (_currentDepth == _keys.count); 130 | } 131 | 132 | - (void)addSearchResultForCurrentPath:(id _Nonnull)result { 133 | [_searchResults setObject:result forKey:self.currentKeyPath]; 134 | } 135 | 136 | - (NSDictionary *)searchResults { 137 | return _searchResults; 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/Private/LOTValueCallback.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTValueCallback.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 12/15/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTValueCallback.h" 10 | 11 | @implementation LOTColorValueCallback 12 | 13 | + (instancetype _Nonnull)withCGColor:(CGColorRef _Nonnull)color { 14 | LOTColorValueCallback *colorCallback = [[self alloc] init]; 15 | colorCallback.colorValue = color; 16 | return colorCallback; 17 | } 18 | 19 | - (CGColorRef)colorForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startColor:(CGColorRef)startColor endColor:(CGColorRef)endColor currentColor:(CGColorRef)interpolatedColor { 20 | return self.colorValue; 21 | } 22 | 23 | @end 24 | 25 | @implementation LOTNumberValueCallback 26 | 27 | + (instancetype _Nonnull)withFloatValue:(CGFloat)numberValue { 28 | LOTNumberValueCallback *numberCallback = [[self alloc] init]; 29 | numberCallback.numberValue = numberValue; 30 | return numberCallback; 31 | } 32 | 33 | - (CGFloat)floatValueForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startValue:(CGFloat)startValue endValue:(CGFloat)endValue currentValue:(CGFloat)interpolatedValue { 34 | return self.numberValue; 35 | } 36 | 37 | @end 38 | 39 | @implementation LOTPointValueCallback 40 | 41 | + (instancetype _Nonnull)withPointValue:(CGPoint)pointValue { 42 | LOTPointValueCallback *callback = [[self alloc] init]; 43 | callback.pointValue = pointValue; 44 | return callback; 45 | } 46 | 47 | - (CGPoint)pointForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint currentPoint:(CGPoint)interpolatedPoint { 48 | return self.pointValue; 49 | } 50 | 51 | @end 52 | 53 | @implementation LOTSizeValueCallback 54 | 55 | + (instancetype _Nonnull)withPointValue:(CGSize)sizeValue { 56 | LOTSizeValueCallback *callback = [[self alloc] init]; 57 | callback.sizeValue = sizeValue; 58 | return callback; 59 | } 60 | 61 | - (CGSize)sizeForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress startSize:(CGSize)startSize endSize:(CGSize)endSize currentSize:(CGSize)interpolatedSize { 62 | return self.sizeValue; 63 | } 64 | 65 | @end 66 | 67 | @implementation LOTPathValueCallback 68 | 69 | + (instancetype _Nonnull)withCGPath:(CGPathRef _Nonnull)path { 70 | LOTPathValueCallback *callback = [[self alloc] init]; 71 | callback.pathValue = path; 72 | return callback; 73 | } 74 | 75 | - (CGPathRef)pathForFrame:(CGFloat)currentFrame startKeyframe:(CGFloat)startKeyframe endKeyframe:(CGFloat)endKeyframe interpolatedProgress:(CGFloat)interpolatedProgress { 76 | return self.pathValue; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTAnimatedControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimatedControl.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 8/25/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class LOTAnimationView; 12 | @class LOTComposition; 13 | 14 | @interface LOTAnimatedControl : UIControl 15 | 16 | // This class is a base class that is intended to be subclassed 17 | 18 | /** 19 | * Map a specific animation layer to a control state. 20 | * When the state is set all layers will be hidden except the specified layer. 21 | **/ 22 | 23 | - (void)setLayerName:(NSString * _Nonnull)layerName forState:(UIControlState)state; 24 | 25 | @property (nonatomic, strong, readonly, nonnull) LOTAnimationView *animationView; 26 | @property (nonatomic, strong, nullable) LOTComposition *animationComp; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTAnimatedSwitch.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimatedSwitch.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 8/25/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimatedControl.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LOTAnimatedSwitch : LOTAnimatedControl 14 | 15 | /// Convenience method to initialize a control from the Main Bundle by name 16 | + (instancetype _Nonnull)switchNamed:(NSString * _Nonnull)toggleName; 17 | 18 | /// Convenience method to initialize a control from the specified bundle by name 19 | + (instancetype _Nonnull)switchNamed:(NSString * _Nonnull)toggleName inBundle:(NSBundle * _Nonnull)bundle; 20 | 21 | 22 | /// The ON/OFF state of the control. Setting will toggle without animation 23 | @property (nonatomic, getter=isOn) BOOL on; 24 | 25 | /// Enable interactive sliding gesture for toggle 26 | @property (nonatomic) BOOL interactiveGesture; 27 | 28 | /// Set the state of the control with animation 29 | - (void)setOn:(BOOL)on animated:(BOOL)animated; // does not send action 30 | 31 | /// Styling 32 | 33 | /** 34 | * Sets the animation play range for the ON state animation. 35 | * fromProgress is the start of the animation 36 | * toProgress is the end of the animation and also the ON static state 37 | * Defaults 0-1 38 | **/ 39 | - (void)setProgressRangeForOnState:(CGFloat)fromProgress 40 | toProgress:(CGFloat)toProgress NS_SWIFT_NAME(setProgressRangeForOnState(fromProgress:toProgress:)); 41 | 42 | /** 43 | * Sets the animation play range for the OFF state animation. 44 | * fromProgress is the start of the animation 45 | * toProgress is the end of the animation and also the OFF static state 46 | * Defaults 1-0 47 | **/ 48 | - (void)setProgressRangeForOffState:(CGFloat)fromProgress 49 | toProgress:(CGFloat)toProgress NS_SWIFT_NAME(setProgressRangeForOffState(fromProgress:toProgress:)); 50 | 51 | @end 52 | 53 | NS_ASSUME_NONNULL_END 54 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTAnimationCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationCache.h 3 | // Lottie 4 | // 5 | // Created by Brandon Withrow on 1/9/17. 6 | // Copyright © 2017 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class LOTComposition; 14 | 15 | @interface LOTAnimationCache : NSObject 16 | 17 | /// Global Cache 18 | + (instancetype)sharedCache; 19 | 20 | /// Adds animation to the cache 21 | - (void)addAnimation:(LOTComposition *)animation forKey:(NSString *)key; 22 | 23 | /// Returns animation from cache. 24 | - (LOTComposition * _Nullable)animationForKey:(NSString *)key; 25 | 26 | /// Removes a specific animation from the cache 27 | - (void)removeAnimationForKey:(NSString *)key; 28 | 29 | /// Clears Everything from the Cache 30 | - (void)clearCache; 31 | 32 | /// Disables Caching Animation Model Objects 33 | - (void)disableCaching; 34 | 35 | @end 36 | 37 | NS_ASSUME_NONNULL_END 38 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTAnimationTransitionController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationTransitionController.h 3 | // Lottie 4 | // 5 | // Created by Brandon Withrow on 1/18/17. 6 | // Copyright © 2017 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | /** LOTAnimationTransitionController 13 | * 14 | * This class creates a custom UIViewController transition animation 15 | * using a Lottie animation to transition between two view controllers 16 | * The transition can use custom defined layers in After Effects for to/from 17 | * 18 | * When referencing After Effects layers the animator masks or transforms the to/from viewController 19 | * with the referenced layer. 20 | * 21 | */ 22 | 23 | @interface LOTAnimationTransitionController : NSObject 24 | 25 | /** 26 | The initializer to create a new transition animation. 27 | 28 | @param animation The name of the Lottie Animation to load for the transition 29 | 30 | @param fromLayer The name of the custom layer to mask the fromVC screenshot with. 31 | If no layer is specified then the screenshot is added behind the Lottie Animation 32 | 33 | @param toLayer The name of the custom layer to mask the toVC screenshot with. 34 | If no layer is specified then the screenshot is added behind the Lottie Animation 35 | and a fade transition is performed along with the Lottie animation. 36 | 37 | @param applyAnimationTransform A boolean that determines if the custom layer should 38 | have the transform animation from the After Effects layer applied to it. If NO the 39 | layer will be masked by the After Effects Layer 40 | 41 | */ 42 | - (nonnull instancetype)initWithAnimationNamed:(nonnull NSString *)animation 43 | fromLayerNamed:(nullable NSString *)fromLayer 44 | toLayerNamed:(nullable NSString *)toLayer 45 | applyAnimationTransform:(BOOL)applyAnimationTransform; 46 | 47 | /** 48 | The initializer to create a new transition animation. 49 | 50 | @param animation The name of the Lottie Animation to load for the transition 51 | 52 | @param fromLayer The name of the custom layer to mask the fromVC screenshot with. 53 | If no layer is specified then the screenshot is added behind the Lottie Animation 54 | 55 | @param toLayer The name of the custom layer to mask the toVC screenshot with. 56 | If no layer is specified then the screenshot is added behind the Lottie Animation 57 | and a fade transition is performed along with the Lottie animation. 58 | 59 | @param applyAnimationTransform A boolean that determines if the custom layer should 60 | have the transform animation from the After Effects layer applied to it. If NO the 61 | layer will be masked by the After Effects Layer 62 | 63 | @param bundle custom bundle to load animation and images, if no bundle is specified will load 64 | from mainBundle 65 | */ 66 | - (instancetype _Nonnull)initWithAnimationNamed:(NSString *_Nonnull)animation 67 | fromLayerNamed:(NSString *_Nullable)fromLayer 68 | toLayerNamed:(NSString *_Nullable)toLayer 69 | applyAnimationTransform:(BOOL)applyAnimationTransform 70 | inBundle:(NSBundle *_Nonnull)bundle; 71 | 72 | @end 73 | 74 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTAnimationView_Compat.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimationView_Compat.h 3 | // Lottie 4 | // 5 | // Created by Oleksii Pavlovskyi on 2/2/17. 6 | // Copyright (c) 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 10 | 11 | #import 12 | @compatibility_alias LOTView UIView; 13 | 14 | #else 15 | 16 | #import 17 | @compatibility_alias LOTView NSView; 18 | 19 | typedef NS_ENUM(NSInteger, LOTViewContentMode) { 20 | LOTViewContentModeScaleToFill, 21 | LOTViewContentModeScaleAspectFit, 22 | LOTViewContentModeScaleAspectFill, 23 | LOTViewContentModeRedraw, 24 | LOTViewContentModeCenter, 25 | LOTViewContentModeTop, 26 | LOTViewContentModeBottom, 27 | LOTViewContentModeLeft, 28 | LOTViewContentModeRight, 29 | LOTViewContentModeTopLeft, 30 | LOTViewContentModeTopRight, 31 | LOTViewContentModeBottomLeft, 32 | LOTViewContentModeBottomRight, 33 | }; 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTCacheProvider.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTCacheProvider.h 3 | // Lottie 4 | // 5 | // Created by punmy on 2017/7/8. 6 | // 7 | // 8 | 9 | #import 10 | 11 | #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 12 | 13 | #import 14 | @compatibility_alias LOTImage UIImage; 15 | 16 | @protocol LOTImageCache; 17 | 18 | #pragma mark - LOTCacheProvider 19 | 20 | @interface LOTCacheProvider : NSObject 21 | 22 | + (id)imageCache; 23 | + (void)setImageCache:(id)cache; 24 | 25 | @end 26 | 27 | #pragma mark - LOTImageCache 28 | 29 | /** 30 | This protocol represent the interface of a image cache which lottie can use. 31 | */ 32 | @protocol LOTImageCache 33 | 34 | @required 35 | - (LOTImage *)imageForKey:(NSString *)key; 36 | - (void)setImage:(LOTImage *)image forKey:(NSString *)key; 37 | 38 | @end 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTComposition.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTScene.h 3 | // LottieAnimator 4 | // 5 | // Created by Brandon Withrow on 12/14/15. 6 | // Copyright © 2015 Brandon Withrow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class LOTLayerGroup; 13 | @class LOTLayer; 14 | @class LOTAssetGroup; 15 | 16 | @interface LOTComposition : NSObject 17 | 18 | /// Load animation by name from the default bundle, Images are also loaded from the bundle 19 | + (nullable instancetype)animationNamed:(nonnull NSString *)animationName NS_SWIFT_NAME(init(name:)); 20 | 21 | /// Loads animation by name from specified bundle, Images are also loaded from the bundle 22 | + (nullable instancetype)animationNamed:(nonnull NSString *)animationName 23 | inBundle:(nonnull NSBundle *)bundle NS_SWIFT_NAME(init(name:bundle:)); 24 | 25 | /// Loads an animation from a specific file path. WARNING Do not use a web URL for file path. 26 | + (nullable instancetype)animationWithFilePath:(nonnull NSString *)filePath NS_SWIFT_NAME(init(filePath:)); 27 | 28 | /// Creates an animation from the deserialized JSON Dictionary 29 | + (nonnull instancetype)animationFromJSON:(nonnull NSDictionary *)animationJSON NS_SWIFT_NAME(init(json:)); 30 | 31 | /// Creates an animation from the deserialized JSON Dictionary, images are loaded from the specified bundle 32 | + (nonnull instancetype)animationFromJSON:(nullable NSDictionary *)animationJSON 33 | inBundle:(nullable NSBundle *)bundle NS_SWIFT_NAME(init(json:bundle:)); 34 | 35 | - (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nullable)jsonDictionary 36 | withAssetBundle:(NSBundle * _Nullable)bundle; 37 | 38 | @property (nonatomic, readonly) CGRect compBounds; 39 | @property (nonatomic, strong, readonly, nullable) NSNumber *startFrame; 40 | @property (nonatomic, strong, readonly, nullable) NSNumber *endFrame; 41 | @property (nonatomic, strong, readonly, nullable) NSNumber *framerate; 42 | @property (nonatomic, readonly) NSTimeInterval timeDuration; 43 | @property (nonatomic, strong, readonly, nullable) LOTLayerGroup *layerGroup; 44 | @property (nonatomic, strong, readonly, nullable) LOTAssetGroup *assetGroup; 45 | @property (nonatomic, strong, readwrite, nullable) NSString *rootDirectory; 46 | @property (nonatomic, strong, readonly, nullable) NSBundle *assetBundle; 47 | @property (nonatomic, copy, nullable) NSString *cacheKey; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTInterpolatorCallback.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTInterpolatorCallback.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 12/15/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "LOTValueDelegate.h" 12 | 13 | /*! 14 | @brief LOTPointInterpolatorCallback is a container for a CGPointRef. This container is a LOTPointValueDelegate that will return the point interpolated at currentProgress between fromPoint and toPoint. Externally changing currentProgress will change the point of the animation. 15 | @discussion LOTPointInterpolatorCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeypoint to set a point value of an animation property. 16 | */ 17 | 18 | @interface LOTPointInterpolatorCallback : NSObject 19 | 20 | + (instancetype _Nonnull)withFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint NS_SWIFT_NAME(init(from:to:)); 21 | 22 | @property (nonatomic) CGPoint fromPoint; 23 | @property (nonatomic) CGPoint toPoint; 24 | 25 | /*! 26 | @brief As currentProgress changes from 0 to 1 the point sent to the animation view is interpolated between fromPoint and toPoint. 27 | */ 28 | 29 | @property (nonatomic, assign) CGFloat currentProgress; 30 | 31 | @end 32 | 33 | /*! 34 | @brief LOTSizeInterpolatorCallback is a container for a CGSizeRef. This container is a LOTSizeValueDelegate that will return the size interpolated at currentProgress between fromSize and toSize. Externally changing currentProgress will change the size of the animation. 35 | @discussion LOTSizeInterpolatorCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeysize to set a size value of an animation property. 36 | */ 37 | 38 | @interface LOTSizeInterpolatorCallback : NSObject 39 | 40 | + (instancetype _Nonnull)withFromSize:(CGSize)fromSize toSize:(CGSize)toSize NS_SWIFT_NAME(init(from:to:)); 41 | 42 | @property (nonatomic) CGSize fromSize; 43 | @property (nonatomic) CGSize toSize; 44 | 45 | /*! 46 | @brief As currentProgress changes from 0 to 1 the size sent to the animation view is interpolated between fromSize and toSize. 47 | */ 48 | 49 | @property (nonatomic, assign) CGFloat currentProgress; 50 | 51 | @end 52 | 53 | /*! 54 | @brief LOTFloatInterpolatorCallback is a container for a CGFloatRef. This container is a LOTFloatValueDelegate that will return the float interpolated at currentProgress between fromFloat and toFloat. Externally changing currentProgress will change the float of the animation. 55 | @discussion LOTFloatInterpolatorCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeyfloat to set a float value of an animation property. 56 | */ 57 | 58 | @interface LOTFloatInterpolatorCallback : NSObject 59 | 60 | + (instancetype _Nonnull)withFromFloat:(CGFloat)fromFloat toFloat:(CGFloat)toFloat NS_SWIFT_NAME(init(from:to:)); 61 | 62 | @property (nonatomic) CGFloat fromFloat; 63 | @property (nonatomic) CGFloat toFloat; 64 | 65 | /*! 66 | @brief As currentProgress changes from 0 to 1 the float sent to the animation view is interpolated between fromFloat and toFloat. 67 | */ 68 | 69 | @property (nonatomic, assign) CGFloat currentProgress; 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTKeypath.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTKeypath.h 3 | // Lottie_iOS 4 | // 5 | // Created by brandon_withrow on 12/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString * _Nonnull const kLOTKeypathEnd; 12 | 13 | /*! 14 | @brief LOTKeypath is an object that describes a keypath search for nodes in the animation JSON. LOTKeypath matches views inside of LOTAnimationView to their After Effects counterparts. 15 | 16 | @discussion 17 | LOTKeypath is used with LOTAnimationView to set animation properties dynamically at runtime, to add or mask subviews, converting geometry, and numerous other functions. 18 | 19 | LOTKeypath can describe a specific object, or can use wildcards for fuzzy matching of objects. Acceptable wildcards are either "*" (star) or "**" (double star). Single star will search a single depth for the next object, double star will search any depth. 20 | 21 | Read More at http://airbnb.io/lottie/ios/dynamic.html 22 | 23 | EG: 24 | @"Layer.Shape Group.Stroke 1.Color" 25 | Represents a specific color node on a specific stroke. 26 | 27 | @"**.Stroke 1.Color" 28 | Represents the color node for every "Stroke 1" in the animation scene. 29 | 30 | */ 31 | 32 | @interface LOTKeypath : NSObject 33 | 34 | /*! 35 | @brief Creates a LOTKeypath from a dot separated string, can use wildcards @"*" and fuzzy depth wild cards @"**". 36 | 37 | @discussion LOTKeypath is an object that describes a keypath search for nodes in the animation JSON. 38 | 39 | LOTKeypath is used with LOTAnimationView to set animation properties dynamically at runtime, to add or mask subviews, converting geometry, and numerous other functions. 40 | 41 | LOTKeypath can describe a specific object, or can use wildcards for fuzzy matching of objects. Acceptable wildcards are either "*" (star) or "**" (double star). Single star will search a single depth for the next object, double star will search any depth. 42 | 43 | @param keypath A dot separated string describing a keypath from the JSON animation. EG @"Layer.Shape Group.Stroke 1.Color" 44 | 45 | @return A new LOTKeypath 46 | */ 47 | 48 | + (nonnull LOTKeypath *)keypathWithString:(nonnull NSString *)keypath; 49 | 50 | /*! 51 | @brief Creates a LOTKeypath from a list of keypath string objects, can use wildcards @"*" and fuzzy depth wild cards @"**". 52 | 53 | @discussion LOTKeypath is an object that describes a keypath search for nodes in the animation JSON. 54 | 55 | LOTKeypath is used with LOTAnimationView to set animation properties dynamically at runtime, to add or mask subviews, converting geometry, and numerous other functions. 56 | 57 | LOTKeypath can describe a specific object, or can use wildcards for fuzzy matching of objects. Acceptable wildcards are either "*" (star) or "**" (double star). Single star will search a single depth for the next object, double star will search any depth. 58 | 59 | @param firstKey A nil terminated list of strings describing a keypath. EG @"Layer", @"Shape Group", @"Stroke 1", @"Color", nil 60 | 61 | @return A new LOTKeypath 62 | */ 63 | 64 | + (nonnull LOTKeypath *)keypathWithKeys:(nonnull NSString *)firstKey, ... 65 | NS_REQUIRES_NIL_TERMINATION; 66 | 67 | @property (nonatomic, readonly, nonnull) NSString *absoluteKeypath; 68 | @property (nonatomic, readonly, nonnull) NSString *currentKey; 69 | @property (nonatomic, readonly, nonnull) NSString *currentKeyPath; 70 | 71 | @property (nonatomic, readonly, nonnull) NSDictionary *searchResults; 72 | 73 | @property (nonatomic, readonly) BOOL hasFuzzyWildcard; 74 | @property (nonatomic, readonly) BOOL hasWildcard; 75 | @property (nonatomic, readonly) BOOL endOfKeypath; 76 | 77 | - (BOOL)pushKey:(nonnull NSString *)key; 78 | - (void)popKey; 79 | - (void)popToRootKey; 80 | 81 | - (void)addSearchResultForCurrentPath:(id _Nonnull)result; 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/LOTValueCallback.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTValueCallback.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 12/15/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "LOTValueDelegate.h" 12 | 13 | /*! 14 | @brief LOTColorValueCallback is a container for a CGColorRef. This container is a LOTColorValueDelegate that always returns the colorValue property to its animation delegate. 15 | @discussion LOTColorValueCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeypath to set a color value of an animation property. 16 | */ 17 | 18 | @interface LOTColorValueCallback : NSObject 19 | 20 | + (instancetype _Nonnull)withCGColor:(CGColorRef _Nonnull)color NS_SWIFT_NAME(init(color:)); 21 | 22 | @property (nonatomic, nonnull) CGColorRef colorValue; 23 | 24 | @end 25 | 26 | /*! 27 | @brief LOTNumberValueCallback is a container for a CGFloat value. This container is a LOTNumberValueDelegate that always returns the numberValue property to its animation delegate. 28 | @discussion LOTNumberValueCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeypath to set a number value of an animation property. 29 | */ 30 | 31 | @interface LOTNumberValueCallback : NSObject 32 | 33 | + (instancetype _Nonnull)withFloatValue:(CGFloat)numberValue NS_SWIFT_NAME(init(number:)); 34 | 35 | @property (nonatomic, assign) CGFloat numberValue; 36 | 37 | @end 38 | 39 | /*! 40 | @brief LOTPointValueCallback is a container for a CGPoint value. This container is a LOTPointValueDelegate that always returns the pointValue property to its animation delegate. 41 | @discussion LOTPointValueCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeypath to set a point value of an animation property. 42 | */ 43 | 44 | @interface LOTPointValueCallback : NSObject 45 | 46 | + (instancetype _Nonnull)withPointValue:(CGPoint)pointValue; 47 | 48 | @property (nonatomic, assign) CGPoint pointValue; 49 | 50 | @end 51 | 52 | /*! 53 | @brief LOTSizeValueCallback is a container for a CGSize value. This container is a LOTSizeValueDelegate that always returns the sizeValue property to its animation delegate. 54 | @discussion LOTSizeValueCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeypath to set a size value of an animation property. 55 | */ 56 | 57 | @interface LOTSizeValueCallback : NSObject 58 | 59 | + (instancetype _Nonnull)withPointValue:(CGSize)sizeValue NS_SWIFT_NAME(init(size:)); 60 | 61 | @property (nonatomic, assign) CGSize sizeValue; 62 | 63 | @end 64 | 65 | /*! 66 | @brief LOTPathValueCallback is a container for a CGPathRef value. This container is a LOTPathValueDelegate that always returns the pathValue property to its animation delegate. 67 | @discussion LOTPathValueCallback is used in conjunction with LOTAnimationView setValueDelegate:forKeypath to set a path value of an animation property. 68 | */ 69 | 70 | @interface LOTPathValueCallback : NSObject 71 | 72 | + (instancetype _Nonnull)withCGPath:(CGPathRef _Nonnull)path NS_SWIFT_NAME(init(path:)); 73 | 74 | @property (nonatomic, nonnull) CGPathRef pathValue; 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/PublicHeaders/Lottie.h: -------------------------------------------------------------------------------- 1 | // 2 | // Lottie.h 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 1/27/17. 6 | // 7 | // Dream Big. 8 | 9 | #if __has_feature(modules) 10 | @import Foundation; 11 | #else 12 | #import 13 | #endif 14 | 15 | #ifndef Lottie_h 16 | #define Lottie_h 17 | 18 | //! Project version number for Lottie. 19 | FOUNDATION_EXPORT double LottieVersionNumber; 20 | 21 | //! Project version string for Lottie. 22 | FOUNDATION_EXPORT const unsigned char LottieVersionString[]; 23 | 24 | #include 25 | 26 | #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 27 | #import "LOTAnimationTransitionController.h" 28 | #import "LOTAnimatedSwitch.h" 29 | #import "LOTAnimatedControl.h" 30 | #endif 31 | 32 | #if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR 33 | #import "LOTCacheProvider.h" 34 | #endif 35 | 36 | #import "LOTAnimationView.h" 37 | #import "LOTAnimationCache.h" 38 | #import "LOTComposition.h" 39 | #import "LOTBlockCallback.h" 40 | #import "LOTInterpolatorCallback.h" 41 | #import "LOTValueCallback.h" 42 | #import "LOTValueDelegate.h" 43 | 44 | #endif /* Lottie_h */ 45 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTCircleAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTCircleAnimator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/19/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | #import "LOTShapeCircle.h" 11 | 12 | @interface LOTCircleAnimator : LOTAnimatorNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapeCircle:(LOTShapeCircle *_Nonnull)shapeCircle; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTCircleAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTCircleAnimator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/19/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTCircleAnimator.h" 10 | #import "LOTPointInterpolator.h" 11 | 12 | const CGFloat kLOTEllipseControlPointPercentage = 0.55228; 13 | 14 | @implementation LOTCircleAnimator { 15 | LOTPointInterpolator *_centerInterpolator; 16 | LOTPointInterpolator *_sizeInterpolator; 17 | BOOL _reversed; 18 | } 19 | 20 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 21 | shapeCircle:(LOTShapeCircle *_Nonnull)shapeCircle { 22 | self = [super initWithInputNode:inputNode keyName:shapeCircle.keyname]; 23 | if (self) { 24 | _centerInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:shapeCircle.position.keyframes]; 25 | _sizeInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:shapeCircle.size.keyframes]; 26 | _reversed = shapeCircle.reversed; 27 | } 28 | return self; 29 | } 30 | 31 | - (NSDictionary *)valueInterpolators { 32 | return @{@"Size" : _sizeInterpolator, 33 | @"Position" : _centerInterpolator}; 34 | } 35 | 36 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 37 | return [_centerInterpolator hasUpdateForFrame:frame] || [_sizeInterpolator hasUpdateForFrame:frame]; 38 | } 39 | 40 | - (void)performLocalUpdate { 41 | // Unfortunately we HAVE to manually build out the ellipse. 42 | // Every Apple method constructs from the 3 o-clock position 43 | // After effects constructs from the Noon position. 44 | // After effects does clockwise, but also has a flag for reversed. 45 | CGPoint center = [_centerInterpolator pointValueForFrame:self.currentFrame]; 46 | CGPoint size = [_sizeInterpolator pointValueForFrame:self.currentFrame]; 47 | 48 | CGFloat halfWidth = size.x / 2; 49 | CGFloat halfHeight = size.y / 2; 50 | 51 | if (_reversed) { 52 | halfWidth = halfWidth * -1; 53 | } 54 | 55 | CGPoint circleQ1 = CGPointMake(center.x, center.y - halfHeight); 56 | CGPoint circleQ2 = CGPointMake(center.x + halfWidth, center.y); 57 | CGPoint circleQ3 = CGPointMake(center.x, center.y + halfHeight); 58 | CGPoint circleQ4 = CGPointMake(center.x - halfWidth, center.y); 59 | 60 | CGFloat cpW = halfWidth * kLOTEllipseControlPointPercentage; 61 | CGFloat cpH = halfHeight * kLOTEllipseControlPointPercentage; 62 | 63 | LOTBezierPath *path = [[LOTBezierPath alloc] init]; 64 | path.cacheLengths = self.pathShouldCacheLengths; 65 | [path LOT_moveToPoint:circleQ1]; 66 | [path LOT_addCurveToPoint:circleQ2 controlPoint1:CGPointMake(circleQ1.x + cpW, circleQ1.y) controlPoint2:CGPointMake(circleQ2.x, circleQ2.y - cpH)]; 67 | 68 | [path LOT_addCurveToPoint:circleQ3 controlPoint1:CGPointMake(circleQ2.x, circleQ2.y + cpH) controlPoint2:CGPointMake(circleQ3.x + cpW, circleQ3.y)]; 69 | 70 | [path LOT_addCurveToPoint:circleQ4 controlPoint1:CGPointMake(circleQ3.x - cpW, circleQ3.y) controlPoint2:CGPointMake(circleQ4.x, circleQ4.y + cpH)]; 71 | 72 | [path LOT_addCurveToPoint:circleQ1 controlPoint1:CGPointMake(circleQ4.x, circleQ4.y - cpH) controlPoint2:CGPointMake(circleQ1.x - cpW, circleQ1.y)]; 73 | 74 | self.localPath = path; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTPathAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPathAnimator.h 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | #import "LOTShapePath.h" 11 | 12 | @interface LOTPathAnimator : LOTAnimatorNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapePath:(LOTShapePath *_Nonnull)shapePath; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTPathAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPathAnimator.m 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // 7 | // 8 | 9 | #import "LOTPathAnimator.h" 10 | #import "LOTPathInterpolator.h" 11 | 12 | @implementation LOTPathAnimator { 13 | LOTShapePath *_pathConent; 14 | LOTPathInterpolator *_interpolator; 15 | } 16 | 17 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 18 | shapePath:(LOTShapePath *_Nonnull)shapePath { 19 | self = [super initWithInputNode:inputNode keyName:shapePath.keyname]; 20 | if (self) { 21 | _pathConent = shapePath; 22 | _interpolator = [[LOTPathInterpolator alloc] initWithKeyframes:_pathConent.shapePath.keyframes]; 23 | } 24 | return self; 25 | } 26 | 27 | - (NSDictionary *)valueInterpolators { 28 | return @{@"Path" : _interpolator}; 29 | } 30 | 31 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 32 | return [_interpolator hasUpdateForFrame:frame]; 33 | } 34 | 35 | - (void)performLocalUpdate { 36 | self.localPath = [_interpolator pathForFrame:self.currentFrame cacheLengths:self.pathShouldCacheLengths]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTPolygonAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPolygonAnimator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | #import "LOTShapeStar.h" 11 | 12 | @interface LOTPolygonAnimator : LOTAnimatorNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapePolygon:(LOTShapeStar *_Nonnull)shapeStar; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTPolygonAnimator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPolygonAnimator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTPolygonAnimator.h" 10 | #import "LOTKeyframe.h" 11 | #import "LOTPointInterpolator.h" 12 | #import "LOTNumberInterpolator.h" 13 | #import "LOTBezierPath.h" 14 | #import "CGGeometry+LOTAdditions.h" 15 | 16 | const CGFloat kPOLYGON_MAGIC_NUMBER = .25f; 17 | 18 | @implementation LOTPolygonAnimator { 19 | LOTNumberInterpolator *_outerRadiusInterpolator; 20 | LOTNumberInterpolator *_outerRoundnessInterpolator; 21 | LOTPointInterpolator *_positionInterpolator; 22 | LOTNumberInterpolator *_pointsInterpolator; 23 | LOTNumberInterpolator *_rotationInterpolator; 24 | } 25 | 26 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 27 | shapePolygon:(LOTShapeStar *_Nonnull)shapeStar { 28 | self = [super initWithInputNode:inputNode keyName:shapeStar.keyname]; 29 | if (self) { 30 | _outerRadiusInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:shapeStar.outerRadius.keyframes]; 31 | _outerRoundnessInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:shapeStar.outerRoundness.keyframes]; 32 | _pointsInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:shapeStar.numberOfPoints.keyframes]; 33 | _rotationInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:shapeStar.rotation.keyframes]; 34 | _positionInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:shapeStar.position.keyframes]; 35 | } 36 | return self; 37 | } 38 | 39 | - (NSDictionary *)valueInterpolators { 40 | return @{@"Points" : _pointsInterpolator, 41 | @"Position" : _positionInterpolator, 42 | @"Rotation" : _rotationInterpolator, 43 | @"Outer Radius" : _outerRadiusInterpolator, 44 | @"Outer Roundness" : _outerRoundnessInterpolator}; 45 | } 46 | 47 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 48 | return ([_outerRadiusInterpolator hasUpdateForFrame:frame] || 49 | [_outerRoundnessInterpolator hasUpdateForFrame:frame] || 50 | [_pointsInterpolator hasUpdateForFrame:frame] || 51 | [_rotationInterpolator hasUpdateForFrame:frame] || 52 | [_positionInterpolator hasUpdateForFrame:frame]); 53 | } 54 | 55 | - (void)performLocalUpdate { 56 | CGFloat outerRadius = [_outerRadiusInterpolator floatValueForFrame:self.currentFrame]; 57 | CGFloat outerRoundness = [_outerRoundnessInterpolator floatValueForFrame:self.currentFrame] / 100.f; 58 | CGFloat points = [_pointsInterpolator floatValueForFrame:self.currentFrame]; 59 | CGFloat rotation = [_rotationInterpolator floatValueForFrame:self.currentFrame]; 60 | CGPoint position = [_positionInterpolator pointValueForFrame:self.currentFrame]; 61 | 62 | LOTBezierPath *path = [[LOTBezierPath alloc] init]; 63 | path.cacheLengths = self.pathShouldCacheLengths; 64 | CGFloat currentAngle = LOT_DegreesToRadians(rotation - 90); 65 | CGFloat anglePerPoint = (CGFloat)((2 * M_PI) / points); 66 | 67 | CGFloat x; 68 | CGFloat y; 69 | CGFloat previousX; 70 | CGFloat previousY; 71 | x = (CGFloat) (outerRadius * cosf(currentAngle)); 72 | y = (CGFloat) (outerRadius * sinf(currentAngle)); 73 | [path LOT_moveToPoint:CGPointMake(x, y)]; 74 | currentAngle += anglePerPoint; 75 | 76 | double numPoints = ceil(points); 77 | for (int i = 0; i < numPoints; i++) { 78 | previousX = x; 79 | previousY = y; 80 | x = (CGFloat) (outerRadius * cosf(currentAngle)); 81 | y = (CGFloat) (outerRadius * sinf(currentAngle)); 82 | 83 | if (outerRoundness != 0) { 84 | CGFloat cp1Theta = (CGFloat) (atan2(previousY, previousX) - M_PI / 2.f); 85 | CGFloat cp1Dx = (CGFloat) cosf(cp1Theta); 86 | CGFloat cp1Dy = (CGFloat) sinf(cp1Theta); 87 | 88 | CGFloat cp2Theta = (CGFloat) (atan2(y, x) - M_PI / 2.f); 89 | CGFloat cp2Dx = (CGFloat) cosf(cp2Theta); 90 | CGFloat cp2Dy = (CGFloat) sinf(cp2Theta); 91 | 92 | CGFloat cp1x = outerRadius * outerRoundness * kPOLYGON_MAGIC_NUMBER * cp1Dx; 93 | CGFloat cp1y = outerRadius * outerRoundness * kPOLYGON_MAGIC_NUMBER * cp1Dy; 94 | CGFloat cp2x = outerRadius * outerRoundness * kPOLYGON_MAGIC_NUMBER * cp2Dx; 95 | CGFloat cp2y = outerRadius * outerRoundness * kPOLYGON_MAGIC_NUMBER * cp2Dy; 96 | [path LOT_addCurveToPoint:CGPointMake(x, y) 97 | controlPoint1:CGPointMake(previousX - cp1x, previousY - cp1y) 98 | controlPoint2:CGPointMake(x + cp2x, y + cp2y)]; 99 | } else { 100 | [path LOT_addLineToPoint:CGPointMake(x, y)]; 101 | } 102 | 103 | currentAngle += anglePerPoint; 104 | } 105 | [path LOT_closePath]; 106 | [path LOT_applyTransform:CGAffineTransformMakeTranslation(position.x, position.y)]; 107 | self.localPath = path; 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTPolystarAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPolystarAnimator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | #import "LOTShapeStar.h" 11 | 12 | @interface LOTPolystarAnimator : LOTAnimatorNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapeStar:(LOTShapeStar *_Nonnull)shapeStar; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/AnimatorNodes/LOTRoundedRectAnimator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTRoundedRectAnimator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/19/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | #import "LOTShapeRectangle.h" 11 | 12 | @interface LOTRoundedRectAnimator : LOTAnimatorNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapeRectangle:(LOTShapeRectangle *_Nonnull)shapeRectangle; 16 | 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTArrayInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTArrayInterpolator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTValueInterpolator.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LOTArrayInterpolator : LOTValueInterpolator 14 | 15 | - (NSArray *)numberArrayForFrame:(NSNumber *)frame; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTArrayInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTArrayInterpolator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTArrayInterpolator.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTArrayInterpolator 13 | 14 | - (NSArray *)numberArrayForFrame:(NSNumber *)frame { 15 | CGFloat progress = [self progressForFrame:frame]; 16 | if (progress == 0) { 17 | return self.leadingKeyframe.arrayValue; 18 | } 19 | if (progress == 1) { 20 | return self.trailingKeyframe.arrayValue; 21 | } 22 | NSMutableArray *returnArray = [NSMutableArray array]; 23 | for (int i = 0; i < self.leadingKeyframe.arrayValue.count; i ++) { 24 | CGFloat from = [(NSNumber *)self.leadingKeyframe.arrayValue[i] floatValue]; 25 | CGFloat to = [(NSNumber *)self.trailingKeyframe.arrayValue[i] floatValue]; 26 | CGFloat value = LOT_RemapValue(progress, 0, 1, from, to); 27 | [returnArray addObject:@(value)]; 28 | } 29 | return returnArray; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTColorInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTColorInterpolator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTValueInterpolator.h" 10 | #import "LOTPlatformCompat.h" 11 | #import "LOTValueDelegate.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface LOTColorInterpolator : LOTValueInterpolator 16 | 17 | - (CGColorRef)colorForFrame:(NSNumber *)frame; 18 | 19 | @property (nonatomic, weak, nullable) id delegate; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTColorInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTColorInterpolator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTColorInterpolator.h" 10 | #import "LOTPlatformCompat.h" 11 | #import "UIColor+Expanded.h" 12 | 13 | @implementation LOTColorInterpolator 14 | 15 | - (CGColorRef)colorForFrame:(NSNumber *)frame { 16 | CGFloat progress = [self progressForFrame:frame]; 17 | UIColor *returnColor; 18 | 19 | if (progress == 0) { 20 | returnColor = self.leadingKeyframe.colorValue; 21 | } else if (progress == 1) { 22 | returnColor = self.trailingKeyframe.colorValue; 23 | } else { 24 | returnColor = [UIColor LOT_colorByLerpingFromColor:self.leadingKeyframe.colorValue toColor:self.trailingKeyframe.colorValue amount:progress]; 25 | } 26 | if (self.hasDelegateOverride) { 27 | return [self.delegate colorForFrame:frame.floatValue 28 | startKeyframe:self.leadingKeyframe.keyframeTime.floatValue 29 | endKeyframe:self.trailingKeyframe.keyframeTime.floatValue 30 | interpolatedProgress:progress 31 | startColor:self.leadingKeyframe.colorValue.CGColor 32 | endColor:self.trailingKeyframe.colorValue.CGColor 33 | currentColor:returnColor.CGColor]; 34 | } 35 | 36 | return returnColor.CGColor; 37 | } 38 | 39 | - (void)setValueDelegate:(id)delegate { 40 | NSAssert(([delegate conformsToProtocol:@protocol(LOTColorValueDelegate)]), @"Color Interpolator set with incorrect callback type. Expected LOTColorValueDelegate"); 41 | self.delegate = (id)delegate; 42 | } 43 | 44 | - (BOOL)hasDelegateOverride { 45 | return self.delegate != nil; 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTNumberInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTNumberInterpolator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/11/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTValueInterpolator.h" 11 | #import "LOTValueDelegate.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | @interface LOTNumberInterpolator : LOTValueInterpolator 15 | 16 | - (CGFloat)floatValueForFrame:(NSNumber *)frame; 17 | 18 | @property (nonatomic, weak, nullable) id delegate; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTNumberInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTNumberInterpolator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/11/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTNumberInterpolator.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTNumberInterpolator 13 | 14 | - (CGFloat)floatValueForFrame:(NSNumber *)frame { 15 | CGFloat progress = [self progressForFrame:frame]; 16 | CGFloat returnValue; 17 | if (progress == 0) { 18 | returnValue = self.leadingKeyframe.floatValue; 19 | } else if (progress == 1) { 20 | returnValue = self.trailingKeyframe.floatValue; 21 | } else { 22 | returnValue = LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.floatValue, self.trailingKeyframe.floatValue); 23 | } 24 | if (self.hasDelegateOverride) { 25 | return [self.delegate floatValueForFrame:frame.floatValue 26 | startKeyframe:self.leadingKeyframe.keyframeTime.floatValue 27 | endKeyframe:self.trailingKeyframe.keyframeTime.floatValue 28 | interpolatedProgress:progress 29 | startValue:self.leadingKeyframe.floatValue 30 | endValue:self.trailingKeyframe.floatValue 31 | currentValue:returnValue]; 32 | } 33 | 34 | return returnValue; 35 | } 36 | 37 | - (BOOL)hasDelegateOverride { 38 | return self.delegate != nil; 39 | } 40 | 41 | - (void)setValueDelegate:(id _Nonnull)delegate { 42 | NSAssert(([delegate conformsToProtocol:@protocol(LOTNumberValueDelegate)]), @"Number Interpolator set with incorrect callback type. Expected LOTNumberValueDelegate"); 43 | self.delegate = (id)delegate; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTPathInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPathInterpolator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTValueInterpolator.h" 10 | #import "LOTPlatformCompat.h" 11 | #import "LOTBezierPath.h" 12 | #import "LOTValueDelegate.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface LOTPathInterpolator : LOTValueInterpolator 17 | 18 | - (LOTBezierPath *)pathForFrame:(NSNumber *)frame cacheLengths:(BOOL)cacheLengths; 19 | 20 | @property (nonatomic, weak, nullable) id delegate; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTPathInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPathInterpolator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTPathInterpolator.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTPathInterpolator 13 | 14 | - (LOTBezierPath *)pathForFrame:(NSNumber *)frame cacheLengths:(BOOL)cacheLengths { 15 | CGFloat progress = [self progressForFrame:frame]; 16 | if (self.hasDelegateOverride) { 17 | CGPathRef callBackPath = [self.delegate pathForFrame:frame.floatValue 18 | startKeyframe:self.leadingKeyframe.keyframeTime.floatValue 19 | endKeyframe:self.trailingKeyframe.keyframeTime.floatValue 20 | interpolatedProgress:progress]; 21 | return [LOTBezierPath pathWithCGPath:callBackPath]; 22 | } 23 | 24 | LOTBezierPath *returnPath = [[LOTBezierPath alloc] init]; 25 | returnPath.cacheLengths = cacheLengths; 26 | LOTBezierData *leadingData = self.leadingKeyframe.pathData; 27 | LOTBezierData *trailingData = self.trailingKeyframe.pathData; 28 | NSInteger vertexCount = leadingData ? leadingData.count : trailingData.count; 29 | BOOL closePath = leadingData ? leadingData.closed : trailingData.closed; 30 | CGPoint cp1 = CGPointMake(0, 0); 31 | CGPoint cp2, p1, cp3 = CGPointZero; 32 | CGPoint startPoint = CGPointMake(0, 0); 33 | CGPoint startInTangent = CGPointMake(0, 0); 34 | for (int i = 0; i < vertexCount; i++) { 35 | if (progress == 0) { 36 | cp2 = [leadingData inTangentAtIndex:i]; 37 | p1 = [leadingData vertexAtIndex:i]; 38 | cp3 = [leadingData outTangentAtIndex:i]; 39 | } else if (progress == 1) { 40 | cp2 = [trailingData inTangentAtIndex:i]; 41 | p1 = [trailingData vertexAtIndex:i]; 42 | cp3 = [trailingData outTangentAtIndex:i]; 43 | } else { 44 | cp2 = LOT_PointInLine([leadingData inTangentAtIndex:i], 45 | [trailingData inTangentAtIndex:i], 46 | progress); 47 | p1 = LOT_PointInLine([leadingData vertexAtIndex:i], 48 | [trailingData vertexAtIndex:i], 49 | progress); 50 | cp3 = LOT_PointInLine([leadingData outTangentAtIndex:i], 51 | [trailingData outTangentAtIndex:i], 52 | progress); 53 | } 54 | if (i == 0) { 55 | startPoint = p1; 56 | startInTangent = cp2; 57 | [returnPath LOT_moveToPoint:p1]; 58 | } else { 59 | [returnPath LOT_addCurveToPoint:p1 controlPoint1:cp1 controlPoint2:cp2]; 60 | } 61 | cp1 = cp3; 62 | } 63 | 64 | if (closePath) { 65 | [returnPath LOT_addCurveToPoint:startPoint controlPoint1:cp3 controlPoint2:startInTangent]; 66 | [returnPath LOT_closePath]; 67 | } 68 | 69 | return returnPath; 70 | } 71 | 72 | - (void)setValueDelegate:(id)delegate { 73 | NSAssert(([delegate conformsToProtocol:@protocol(LOTPathValueDelegate)]), @"Path Interpolator set with incorrect callback type. Expected LOTPathValueDelegate"); 74 | self.delegate = (id)delegate; 75 | } 76 | 77 | - (BOOL)hasDelegateOverride { 78 | return self.delegate != nil; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTPointInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPointInterpolator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/12/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTValueInterpolator.h" 10 | #import "LOTValueDelegate.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LOTPointInterpolator : LOTValueInterpolator 15 | 16 | - (CGPoint)pointValueForFrame:(NSNumber *)frame; 17 | 18 | @property (nonatomic, weak, nullable) id delegate; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTPointInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTPointInterpolator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/12/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTPointInterpolator.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @implementation LOTPointInterpolator 13 | 14 | - (CGPoint)pointValueForFrame:(NSNumber *)frame { 15 | CGFloat progress = [self progressForFrame:frame]; 16 | CGPoint returnPoint; 17 | if (progress == 0) { 18 | returnPoint = self.leadingKeyframe.pointValue; 19 | } else if (progress == 1) { 20 | returnPoint = self.trailingKeyframe.pointValue; 21 | } else if (!CGPointEqualToPoint(self.leadingKeyframe.spatialOutTangent, CGPointZero) || 22 | !CGPointEqualToPoint(self.trailingKeyframe.spatialInTangent, CGPointZero)) { 23 | // Spatial Bezier path 24 | CGPoint outTan = LOT_PointAddedToPoint(self.leadingKeyframe.pointValue, self.leadingKeyframe.spatialOutTangent); 25 | CGPoint inTan = LOT_PointAddedToPoint(self.trailingKeyframe.pointValue, self.trailingKeyframe.spatialInTangent); 26 | returnPoint = LOT_PointInCubicCurve(self.leadingKeyframe.pointValue, outTan, inTan, self.trailingKeyframe.pointValue, progress); 27 | } else { 28 | returnPoint = LOT_PointInLine(self.leadingKeyframe.pointValue, self.trailingKeyframe.pointValue, progress); 29 | } 30 | if (self.hasDelegateOverride) { 31 | return [self.delegate pointForFrame:frame.floatValue 32 | startKeyframe:self.leadingKeyframe.keyframeTime.floatValue 33 | endKeyframe:self.trailingKeyframe.keyframeTime.floatValue 34 | interpolatedProgress:progress 35 | startPoint:self.leadingKeyframe.pointValue 36 | endPoint:self.trailingKeyframe.pointValue 37 | currentPoint:returnPoint]; 38 | } 39 | return returnPoint; 40 | } 41 | 42 | - (BOOL)hasDelegateOverride { 43 | return self.delegate != nil; 44 | } 45 | 46 | - (void)setValueDelegate:(id)delegate { 47 | NSAssert(([delegate conformsToProtocol:@protocol(LOTPointValueDelegate)]), @"Point Interpolator set with incorrect callback type. Expected LOTPointValueDelegate"); 48 | self.delegate = (id)delegate; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTSizeInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTSizeInterpolator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTValueInterpolator.h" 10 | #import "LOTValueDelegate.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LOTSizeInterpolator : LOTValueInterpolator 15 | 16 | - (CGSize)sizeValueForFrame:(NSNumber *)frame; 17 | 18 | @property (nonatomic, weak, nullable) id delegate; 19 | 20 | @end 21 | 22 | NS_ASSUME_NONNULL_END 23 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTSizeInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTSizeInterpolator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/13/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTPlatformCompat.h" 10 | #import "LOTSizeInterpolator.h" 11 | #import "CGGeometry+LOTAdditions.h" 12 | 13 | @implementation LOTSizeInterpolator 14 | 15 | - (CGSize)sizeValueForFrame:(NSNumber *)frame { 16 | CGFloat progress = [self progressForFrame:frame]; 17 | CGSize returnSize; 18 | if (progress == 0) { 19 | returnSize = self.leadingKeyframe.sizeValue; 20 | }else if (progress == 1) { 21 | returnSize = self.trailingKeyframe.sizeValue; 22 | } else { 23 | returnSize = CGSizeMake(LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.sizeValue.width, self.trailingKeyframe.sizeValue.width), 24 | LOT_RemapValue(progress, 0, 1, self.leadingKeyframe.sizeValue.height, self.trailingKeyframe.sizeValue.height)); 25 | } 26 | if (self.hasDelegateOverride) { 27 | return [self.delegate sizeForFrame:frame.floatValue 28 | startKeyframe:self.leadingKeyframe.keyframeTime.floatValue 29 | endKeyframe:self.trailingKeyframe.keyframeTime.floatValue 30 | interpolatedProgress:progress startSize:self.leadingKeyframe.sizeValue 31 | endSize:self.trailingKeyframe.sizeValue 32 | currentSize:returnSize]; 33 | } 34 | return returnSize; 35 | } 36 | 37 | - (BOOL)hasDelegateOverride { 38 | return self.delegate != nil; 39 | } 40 | 41 | - (void)setValueDelegate:(id)delegate { 42 | NSAssert(([delegate conformsToProtocol:@protocol(LOTSizeValueDelegate)]), @"Size Interpolator set with incorrect callback type. Expected LOTSizeValueDelegate"); 43 | self.delegate = (id)delegate; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTTransformInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTTransformInterpolator.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/18/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LOTNumberInterpolator.h" 11 | #import "LOTPointInterpolator.h" 12 | #import "LOTSizeInterpolator.h" 13 | #import "LOTKeyframe.h" 14 | #import "LOTLayer.h" 15 | 16 | NS_ASSUME_NONNULL_BEGIN 17 | 18 | @interface LOTTransformInterpolator : NSObject 19 | 20 | + (instancetype)transformForLayer:(LOTLayer *)layer; 21 | 22 | - (instancetype)initWithPosition:(NSArray *)position 23 | rotation:(NSArray *)rotation 24 | anchor:(NSArray *)anchor 25 | scale:(NSArray *)scale; 26 | 27 | - (instancetype)initWithPositionX:(NSArray *)positionX 28 | positionY:(NSArray *)positionY 29 | rotation:(NSArray *)rotation 30 | anchor:(NSArray *)anchor 31 | scale:(NSArray *)scale; 32 | 33 | @property (nonatomic, strong) LOTTransformInterpolator * inputNode; 34 | 35 | @property (nonatomic, readonly) LOTPointInterpolator *positionInterpolator; 36 | @property (nonatomic, readonly) LOTPointInterpolator *anchorInterpolator; 37 | @property (nonatomic, readonly) LOTSizeInterpolator *scaleInterpolator; 38 | @property (nonatomic, readonly) LOTNumberInterpolator *rotationInterpolator; 39 | @property (nonatomic, readonly) LOTNumberInterpolator *positionXInterpolator; 40 | @property (nonatomic, readonly) LOTNumberInterpolator *positionYInterpolator; 41 | @property (nonatomic, strong, nullable) NSString *parentKeyName; 42 | 43 | - (CATransform3D)transformForFrame:(NSNumber *)frame; 44 | - (BOOL)hasUpdateForFrame:(NSNumber *)frame; 45 | 46 | @end 47 | 48 | NS_ASSUME_NONNULL_END 49 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTTransformInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTTransformInterpolator.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/18/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTTransformInterpolator.h" 10 | 11 | // TODO BW Perf update, Cache transform 12 | 13 | @implementation LOTTransformInterpolator { 14 | LOTPointInterpolator *_positionInterpolator; 15 | LOTPointInterpolator *_anchorInterpolator; 16 | LOTSizeInterpolator *_scaleInterpolator; 17 | LOTNumberInterpolator *_rotationInterpolator; 18 | LOTNumberInterpolator *_positionXInterpolator; 19 | LOTNumberInterpolator *_positionYInterpolator; 20 | } 21 | 22 | + (instancetype)transformForLayer:(LOTLayer *)layer { 23 | LOTTransformInterpolator *interpolator = nil; 24 | if (layer.position) { 25 | interpolator = [[LOTTransformInterpolator alloc] initWithPosition:layer.position.keyframes 26 | rotation:layer.rotation.keyframes 27 | anchor:layer.anchor.keyframes 28 | scale:layer.scale.keyframes]; 29 | } else { 30 | interpolator = [[LOTTransformInterpolator alloc] initWithPositionX:layer.positionX.keyframes 31 | positionY:layer.positionY.keyframes 32 | rotation:layer.rotation.keyframes 33 | anchor:layer.anchor.keyframes 34 | scale:layer.scale.keyframes]; 35 | } 36 | interpolator.parentKeyName = [layer.layerName copy]; 37 | return interpolator; 38 | } 39 | 40 | - (instancetype)initWithPosition:(NSArray *)position 41 | rotation:(NSArray *)rotation 42 | anchor:(NSArray *)anchor 43 | scale:(NSArray *)scale { 44 | self = [super init]; 45 | if (self) { 46 | [self initializeWithPositionX:nil positionY:nil position:position rotation:rotation anchor:anchor scale:scale]; 47 | } 48 | return self; 49 | } 50 | 51 | - (instancetype)initWithPositionX:(NSArray *)positionX 52 | positionY:(NSArray *)positionY 53 | rotation:(NSArray *)rotation 54 | anchor:(NSArray *)anchor 55 | scale:(NSArray *)scale { 56 | self = [super init]; 57 | if (self) { 58 | [self initializeWithPositionX:positionX positionY:positionY position:nil rotation:rotation anchor:anchor scale:scale]; 59 | } 60 | return self; 61 | } 62 | 63 | 64 | - (void)initializeWithPositionX:(NSArray *)positionX 65 | positionY:(NSArray *)positionY 66 | position:(NSArray *)position 67 | rotation:(NSArray *)rotation 68 | anchor:(NSArray *)anchor 69 | scale:(NSArray *)scale { 70 | 71 | if (position) { 72 | _positionInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:position]; 73 | } 74 | if (positionY) { 75 | _positionYInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:positionY]; 76 | } 77 | if (positionX) { 78 | _positionXInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:positionX]; 79 | } 80 | _anchorInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:anchor]; 81 | _scaleInterpolator = [[LOTSizeInterpolator alloc] initWithKeyframes:scale]; 82 | _rotationInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:rotation]; 83 | } 84 | 85 | - (BOOL)hasUpdateForFrame:(NSNumber *)frame { 86 | BOOL inputUpdate = _inputNode ? [_inputNode hasUpdateForFrame:frame] : NO; 87 | if (inputUpdate) { 88 | return inputUpdate; 89 | } 90 | if (_positionInterpolator) { 91 | return ([_positionInterpolator hasUpdateForFrame:frame] || 92 | [_anchorInterpolator hasUpdateForFrame:frame] || 93 | [_scaleInterpolator hasUpdateForFrame:frame] || 94 | [_rotationInterpolator hasUpdateForFrame:frame]); 95 | } 96 | return ([_positionXInterpolator hasUpdateForFrame:frame] || 97 | [_positionYInterpolator hasUpdateForFrame:frame] || 98 | [_anchorInterpolator hasUpdateForFrame:frame] || 99 | [_scaleInterpolator hasUpdateForFrame:frame] || 100 | [_rotationInterpolator hasUpdateForFrame:frame]); 101 | } 102 | 103 | - (CATransform3D)transformForFrame:(NSNumber *)frame { 104 | CATransform3D baseXform = CATransform3DIdentity; 105 | if (_inputNode) { 106 | baseXform = [_inputNode transformForFrame:frame]; 107 | } 108 | CGPoint position = CGPointZero; 109 | if (_positionInterpolator) { 110 | position = [_positionInterpolator pointValueForFrame:frame]; 111 | } 112 | if (_positionXInterpolator && 113 | _positionYInterpolator) { 114 | position.x = [_positionXInterpolator floatValueForFrame:frame]; 115 | position.y = [_positionYInterpolator floatValueForFrame:frame]; 116 | } 117 | CGPoint anchor = [_anchorInterpolator pointValueForFrame:frame]; 118 | CGSize scale = [_scaleInterpolator sizeValueForFrame:frame]; 119 | CGFloat rotation = [_rotationInterpolator floatValueForFrame:frame]; 120 | CATransform3D translateXform = CATransform3DTranslate(baseXform, position.x, position.y, 0); 121 | CATransform3D rotateXform = CATransform3DRotate(translateXform, rotation, 0, 0, 1); 122 | CATransform3D scaleXform = CATransform3DScale(rotateXform, scale.width, scale.height, 1); 123 | CATransform3D anchorXform = CATransform3DTranslate(scaleXform, -1 * anchor.x, -1 * anchor.y, 0); 124 | return anchorXform; 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTValueInterpolator.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTValueInterpolator.h 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 7/10/17. 6 | // 7 | // 8 | 9 | #import 10 | #import "LOTKeyframe.h" 11 | #import "LOTValueDelegate.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | @interface LOTValueInterpolator : NSObject 16 | 17 | - (instancetype)initWithKeyframes:(NSArray *)keyframes; 18 | 19 | @property (nonatomic, weak, nullable) LOTKeyframe *leadingKeyframe; 20 | @property (nonatomic, weak, nullable) LOTKeyframe *trailingKeyframe; 21 | @property (nonatomic, readonly) BOOL hasDelegateOverride; 22 | 23 | - (void)setValueDelegate:(id _Nonnull)delegate; 24 | 25 | - (BOOL)hasUpdateForFrame:(NSNumber *)frame; 26 | - (CGFloat)progressForFrame:(NSNumber *)frame; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/InterpolatorNodes/LOTValueInterpolator.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTValueInterpolator.m 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 7/10/17. 6 | // 7 | // 8 | 9 | #import "LOTValueInterpolator.h" 10 | #import "CGGeometry+LOTAdditions.h" 11 | 12 | @interface LOTValueInterpolator () 13 | 14 | @property (nonatomic, strong) NSArray *keyframes; 15 | 16 | @end 17 | 18 | @implementation LOTValueInterpolator 19 | 20 | - (instancetype)initWithKeyframes:(NSArray *)keyframes { 21 | self = [super init]; 22 | if (self) { 23 | _keyframes = keyframes; 24 | } 25 | return self; 26 | } 27 | 28 | - (BOOL)hasUpdateForFrame:(NSNumber *)frame { 29 | if (self.hasDelegateOverride) { 30 | return YES; 31 | } 32 | /* 33 | Cases we dont update keyframe 34 | if time is in span and leading keyframe is hold 35 | if trailing keyframe is nil and time is after leading 36 | if leading keyframe is nil and time is before trailing 37 | */ 38 | if (self.leadingKeyframe && 39 | self.trailingKeyframe == nil && 40 | self.leadingKeyframe.keyframeTime.floatValue < frame.floatValue) { 41 | // Frame is after bounds of keyframes. Clip 42 | return NO; 43 | } 44 | if (self.trailingKeyframe && 45 | self.leadingKeyframe == nil && 46 | self.trailingKeyframe.keyframeTime.floatValue > frame.floatValue) { 47 | // Frame is before keyframes bounds. Clip. 48 | return NO; 49 | } 50 | if (self.leadingKeyframe && self.trailingKeyframe && 51 | self.leadingKeyframe.isHold && 52 | self.leadingKeyframe.keyframeTime.floatValue < frame.floatValue && 53 | self.trailingKeyframe.keyframeTime.floatValue > frame.floatValue) { 54 | // Frame is in span and current span is a hold keyframe 55 | return NO; 56 | } 57 | 58 | return YES; 59 | } 60 | 61 | - (void)updateKeyframeSpanForFrame:(NSNumber *)frame { 62 | if (self.leadingKeyframe == nil && 63 | self.trailingKeyframe == nil) { 64 | // Set Initial Keyframes 65 | LOTKeyframe *first = _keyframes.firstObject; 66 | if (first.keyframeTime.floatValue > 0) { 67 | self.trailingKeyframe = first; 68 | } else { 69 | self.leadingKeyframe = first; 70 | if (_keyframes.count > 1) { 71 | self.trailingKeyframe = _keyframes[1]; 72 | } 73 | } 74 | } 75 | if (self.trailingKeyframe && frame.floatValue >= self.trailingKeyframe.keyframeTime.floatValue) { 76 | // Frame is after current span, can move forward 77 | NSInteger index = [_keyframes indexOfObject:self.trailingKeyframe]; 78 | BOOL keyframeFound = NO; 79 | 80 | LOTKeyframe *testLeading = self.trailingKeyframe; 81 | LOTKeyframe *testTrailing = nil; 82 | 83 | while (keyframeFound == NO) { 84 | index ++; 85 | if (index < _keyframes.count) { 86 | testTrailing = _keyframes[index]; 87 | if (frame.floatValue < testTrailing.keyframeTime.floatValue) { 88 | // This is the span. 89 | keyframeFound = YES; 90 | } else { 91 | testLeading = testTrailing; 92 | } 93 | } else { 94 | // Leading is Last object 95 | testTrailing = nil; 96 | keyframeFound = YES; 97 | } 98 | } 99 | self.leadingKeyframe = testLeading; 100 | self.trailingKeyframe = testTrailing; 101 | } else if (self.leadingKeyframe && frame.floatValue < self.leadingKeyframe.keyframeTime.floatValue) { 102 | // Frame is before current span, can move back a span 103 | NSInteger index = [_keyframes indexOfObject:self.leadingKeyframe]; 104 | BOOL keyframeFound = NO; 105 | 106 | LOTKeyframe *testLeading = nil; 107 | LOTKeyframe *testTrailing = self.leadingKeyframe; 108 | 109 | while (keyframeFound == NO) { 110 | index --; 111 | if (index >= 0) { 112 | testLeading = _keyframes[index]; 113 | if (frame.floatValue >= testLeading.keyframeTime.floatValue) { 114 | // This is the span. 115 | keyframeFound = YES; 116 | } else { 117 | testTrailing = testLeading; 118 | } 119 | } else { 120 | // Trailing is first object 121 | testLeading = nil; 122 | keyframeFound = YES; 123 | } 124 | } 125 | self.leadingKeyframe = testLeading; 126 | self.trailingKeyframe = testTrailing; 127 | } 128 | } 129 | 130 | - (CGFloat)progressForFrame:(NSNumber *)frame { 131 | [self updateKeyframeSpanForFrame:frame]; 132 | // At this point frame definitely exists between leading and trailing keyframes 133 | if (self.leadingKeyframe.keyframeTime == frame) { 134 | // Frame is leading keyframe 135 | return 0; 136 | } 137 | if (self.trailingKeyframe == nil) { 138 | // Frame is after end of keyframe timeline 139 | return 0; 140 | } 141 | if (self.leadingKeyframe.isHold) { 142 | // Hold Keyframe 143 | return 0; 144 | } 145 | if (self.leadingKeyframe == nil) { 146 | // Frame is before start of keyframe timeline 147 | return 1; 148 | } 149 | 150 | CGFloat progression = LOT_RemapValue(frame.floatValue, self.leadingKeyframe.keyframeTime.floatValue, self.trailingKeyframe.keyframeTime.floatValue, 0, 1); 151 | 152 | if ((self.leadingKeyframe.outTangent.x != self.leadingKeyframe.outTangent.y || 153 | self.trailingKeyframe.inTangent.x != self.trailingKeyframe.inTangent.y) && 154 | (!LOT_CGPointIsZero(self.leadingKeyframe.outTangent) && 155 | !LOT_CGPointIsZero(self.trailingKeyframe.inTangent))) { 156 | // Bezier Time Curve 157 | progression = LOT_CubicBezierInterpolate(CGPointMake(0, 0), self.leadingKeyframe.outTangent, self.trailingKeyframe.inTangent, CGPointMake(1, 1), progression); 158 | } 159 | 160 | return progression; 161 | } 162 | 163 | - (void)setValueDelegate:(id _Nonnull)delegate { 164 | NSAssert((NO), @"Interpolator does not support value callbacks"); 165 | } 166 | 167 | @end 168 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/LOTAnimatorNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimatorNode.h 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // 7 | // 8 | 9 | #import 10 | #import "LOTPlatformCompat.h" 11 | #import "LOTBezierPath.h" 12 | #import "LOTKeypath.h" 13 | #import "LOTValueDelegate.h" 14 | 15 | extern NSInteger indentation_level; 16 | @interface LOTAnimatorNode : NSObject 17 | 18 | /// Initializes the node with and optional input node and keyname. 19 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 20 | keyName:(NSString *_Nullable)keyname; 21 | 22 | /// A dictionary of the value interpolators this node controls 23 | @property (nonatomic, readonly, strong) NSDictionary * _Nullable valueInterpolators; 24 | 25 | /// The keyname of the node. Used for dynamically setting keyframe data. 26 | @property (nonatomic, readonly, strong) NSString * _Nullable keyname; 27 | 28 | /// The current time in frames 29 | @property (nonatomic, readonly, strong) NSNumber * _Nullable currentFrame; 30 | /// The upstream animator node 31 | @property (nonatomic, readonly, strong) LOTAnimatorNode * _Nullable inputNode; 32 | 33 | /// This nodes path in local object space 34 | @property (nonatomic, strong) LOTBezierPath * _Nonnull localPath; 35 | /// The sum of all paths in the tree including this node 36 | @property (nonatomic, strong) LOTBezierPath * _Nonnull outputPath; 37 | 38 | /// Returns true if this node needs to update its contents for the given frame. To be overwritten by subclasses. 39 | - (BOOL)needsUpdateForFrame:(NSNumber *_Nonnull)frame; 40 | 41 | /// Sets the current frame and performs any updates. Returns true if any updates were performed, locally or upstream. 42 | - (BOOL)updateWithFrame:(NSNumber *_Nonnull)frame; 43 | - (BOOL)updateWithFrame:(NSNumber *_Nonnull)frame 44 | withModifierBlock:(void (^_Nullable)(LOTAnimatorNode * _Nonnull inputNode))modifier 45 | forceLocalUpdate:(BOOL)forceUpdate; 46 | 47 | - (void)forceSetCurrentFrame:(NSNumber *_Nonnull)frame; 48 | 49 | @property (nonatomic, assign) BOOL pathShouldCacheLengths; 50 | /// Update the local content for the frame. 51 | - (void)performLocalUpdate; 52 | 53 | /// Rebuild all outputs for the node. This is called after upstream updates have been performed. 54 | - (void)rebuildOutputs; 55 | 56 | - (void)logString:(NSString *_Nonnull)string; 57 | 58 | - (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath; 59 | 60 | - (void)setValueDelegate:(id _Nonnull)delegate 61 | forKeypath:(LOTKeypath * _Nonnull)keypath; 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/LOTAnimatorNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTAnimatorNode.m 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | #import "LOTHelpers.h" 11 | #import "LOTValueInterpolator.h" 12 | 13 | NSInteger indentation_level = 0; 14 | 15 | @implementation LOTAnimatorNode 16 | 17 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 18 | keyName:(NSString *_Nullable)keyname { 19 | self = [super init]; 20 | if (self) { 21 | _keyname = keyname; 22 | _inputNode = inputNode; 23 | } 24 | return self; 25 | } 26 | 27 | /// To be overwritten by subclass. Defaults to YES 28 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 29 | return YES; 30 | } 31 | 32 | /// The node checks if local update or if upstream update required. If upstream update outputs are rebuilt. If local update local update is performed. Returns no if no action 33 | - (BOOL)updateWithFrame:(NSNumber *_Nonnull)frame { 34 | return [self updateWithFrame:frame withModifierBlock:NULL forceLocalUpdate:NO]; 35 | } 36 | 37 | - (BOOL)updateWithFrame:(NSNumber *_Nonnull)frame 38 | withModifierBlock:(void (^_Nullable)(LOTAnimatorNode * _Nonnull inputNode))modifier 39 | forceLocalUpdate:(BOOL)forceUpdate { 40 | if ([_currentFrame isEqual:frame] && !forceUpdate) { 41 | return NO; 42 | } 43 | if (ENABLE_DEBUG_LOGGING) [self logString:[NSString stringWithFormat:@"%lu %@ Checking for update", (unsigned long)self.hash, self.keyname]]; 44 | BOOL localUpdate = [self needsUpdateForFrame:frame] || forceUpdate; 45 | if (localUpdate && ENABLE_DEBUG_LOGGING) { 46 | [self logString:[NSString stringWithFormat:@"%lu %@ Performing update", (unsigned long)self.hash, self.keyname]]; 47 | } 48 | BOOL inputUpdated = [_inputNode updateWithFrame:frame 49 | withModifierBlock:modifier 50 | forceLocalUpdate:forceUpdate]; 51 | _currentFrame = frame; 52 | if (localUpdate) { 53 | [self performLocalUpdate]; 54 | if (modifier) { 55 | modifier(self); 56 | } 57 | } 58 | 59 | if (inputUpdated || localUpdate) { 60 | [self rebuildOutputs]; 61 | } 62 | return (inputUpdated || localUpdate); 63 | } 64 | 65 | - (void)forceSetCurrentFrame:(NSNumber *_Nonnull)frame { 66 | _currentFrame = frame; 67 | } 68 | 69 | - (void)logString:(NSString *)string { 70 | NSMutableString *logString = [NSMutableString string]; 71 | [logString appendString:@"|"]; 72 | for (int i = 0; i < indentation_level; i ++) { 73 | [logString appendString:@" "]; 74 | } 75 | [logString appendString:string]; 76 | NSLog(@"%@ %@", NSStringFromClass([self class]), logString); 77 | } 78 | 79 | // TOBO BW Perf, make updates perform only when necessary. Currently everything in a node is updated 80 | /// Performs any local content update and updates self.localPath 81 | - (void)performLocalUpdate { 82 | self.localPath = [[LOTBezierPath alloc] init]; 83 | } 84 | 85 | /// Rebuilds outputs by adding localPath to inputNodes output path. 86 | - (void)rebuildOutputs { 87 | if (self.inputNode) { 88 | self.outputPath = [self.inputNode.outputPath copy]; 89 | [self.outputPath LOT_appendPath:self.localPath]; 90 | } else { 91 | self.outputPath = self.localPath; 92 | } 93 | } 94 | 95 | - (void)setPathShouldCacheLengths:(BOOL)pathShouldCacheLengths { 96 | _pathShouldCacheLengths = pathShouldCacheLengths; 97 | self.inputNode.pathShouldCacheLengths = pathShouldCacheLengths; 98 | } 99 | 100 | - (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath { 101 | [self.inputNode searchNodesForKeypath:keypath]; 102 | if ([keypath pushKey:self.keyname]) { 103 | // Matches self. Check interpolators 104 | if (keypath.endOfKeypath) { 105 | // Add self 106 | [keypath addSearchResultForCurrentPath:self]; 107 | } else if (self.valueInterpolators[keypath.currentKey] != nil) { 108 | [keypath pushKey:keypath.currentKey]; 109 | // We have a match! 110 | [keypath addSearchResultForCurrentPath:self]; 111 | [keypath popKey]; 112 | } 113 | [keypath popKey]; 114 | } 115 | } 116 | 117 | - (void)setValueDelegate:(id _Nonnull)delegate 118 | forKeypath:(LOTKeypath * _Nonnull)keypath { 119 | if ([keypath pushKey:self.keyname]) { 120 | // Matches self. Check interpolators 121 | LOTValueInterpolator *interpolator = self.valueInterpolators[keypath.currentKey]; 122 | if (interpolator) { 123 | // We have a match! 124 | [interpolator setValueDelegate:delegate]; 125 | } 126 | [keypath popKey]; 127 | } 128 | [self.inputNode setValueDelegate:delegate forKeypath:keypath]; 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/LOTRenderNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTRenderNode.h 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | 11 | @interface LOTRenderNode : LOTAnimatorNode 12 | 13 | @property (nonatomic, readonly, strong) CAShapeLayer * _Nonnull outputLayer; 14 | 15 | - (NSDictionary * _Nonnull)actionsForRenderLayer; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/LOTRenderNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTRenderNode.m 3 | // Pods 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // 7 | // 8 | 9 | #import "LOTRenderNode.h" 10 | 11 | @implementation LOTRenderNode 12 | 13 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 14 | keyName:(NSString * _Nullable)keyname { 15 | self = [super initWithInputNode:inputNode keyName:keyname]; 16 | if (self) { 17 | _outputLayer = [CAShapeLayer new]; 18 | _outputLayer.actions = [self actionsForRenderLayer]; 19 | } 20 | return self; 21 | } 22 | 23 | /// Layer Properties that need to disable implicit animations 24 | - (NSDictionary * _Nonnull)actionsForRenderLayer { 25 | return @{@"path": [NSNull null]}; 26 | } 27 | 28 | /// Local interpolators have changed. Update layer specific properties. 29 | - (void)performLocalUpdate { 30 | 31 | } 32 | 33 | /// The path for rendering has changed. Do any rendering required. 34 | - (void)rebuildOutputs { 35 | 36 | } 37 | 38 | - (LOTBezierPath *)localPath { 39 | return self.inputNode.localPath; 40 | } 41 | 42 | /// Forwards its input node's output path forwards downstream 43 | - (LOTBezierPath *)outputPath { 44 | return self.inputNode.outputPath; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/ManipulatorNodes/LOTTrimPathNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTTrimPathNode.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/21/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTAnimatorNode.h" 10 | #import "LOTShapeTrimPath.h" 11 | 12 | @interface LOTTrimPathNode : LOTAnimatorNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | trimPath:(LOTShapeTrimPath *_Nonnull)trimPath; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/ManipulatorNodes/LOTTrimPathNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTTrimPathNode.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/21/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTTrimPathNode.h" 10 | #import "LOTNumberInterpolator.h" 11 | #import "LOTPathAnimator.h" 12 | #import "LOTCircleAnimator.h" 13 | #import "LOTRoundedRectAnimator.h" 14 | #import "LOTRenderGroup.h" 15 | 16 | @implementation LOTTrimPathNode { 17 | LOTNumberInterpolator *_startInterpolator; 18 | LOTNumberInterpolator *_endInterpolator; 19 | LOTNumberInterpolator *_offsetInterpolator; 20 | 21 | CGFloat _startT; 22 | CGFloat _endT; 23 | CGFloat _offsetT; 24 | } 25 | 26 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 27 | trimPath:(LOTShapeTrimPath *_Nonnull)trimPath { 28 | self = [super initWithInputNode:inputNode keyName:trimPath.keyname]; 29 | if (self) { 30 | inputNode.pathShouldCacheLengths = YES; 31 | _startInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:trimPath.start.keyframes]; 32 | _endInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:trimPath.end.keyframes]; 33 | _offsetInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:trimPath.offset.keyframes]; 34 | } 35 | return self; 36 | } 37 | 38 | - (NSDictionary *)valueInterpolators { 39 | return @{@"Start" : _startInterpolator, 40 | @"End" : _endInterpolator, 41 | @"Offset" : _offsetInterpolator}; 42 | } 43 | 44 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 45 | return ([_startInterpolator hasUpdateForFrame:frame] || 46 | [_endInterpolator hasUpdateForFrame:frame] || 47 | [_offsetInterpolator hasUpdateForFrame:frame]); 48 | } 49 | 50 | - (BOOL)updateWithFrame:(NSNumber *)frame 51 | withModifierBlock:(void (^ _Nullable)(LOTAnimatorNode * _Nonnull))modifier 52 | forceLocalUpdate:(BOOL)forceUpdate { 53 | BOOL localUpdate = [self needsUpdateForFrame:frame]; 54 | [self forceSetCurrentFrame:frame]; 55 | if (localUpdate) { 56 | [self performLocalUpdate]; 57 | } 58 | if (self.inputNode == nil) { 59 | return localUpdate; 60 | } 61 | 62 | BOOL inputUpdated = [self.inputNode updateWithFrame:frame withModifierBlock:^(LOTAnimatorNode * _Nonnull inputNode) { 63 | if ([inputNode isKindOfClass:[LOTPathAnimator class]] || 64 | [inputNode isKindOfClass:[LOTCircleAnimator class]] || 65 | [inputNode isKindOfClass:[LOTRoundedRectAnimator class]]) { 66 | [inputNode.localPath trimPathFromT:self->_startT toT:self->_endT offset:self->_offsetT]; 67 | } 68 | if (modifier) { 69 | modifier(inputNode); 70 | } 71 | 72 | } forceLocalUpdate:(localUpdate || forceUpdate)]; 73 | 74 | return inputUpdated; 75 | } 76 | 77 | - (void)performLocalUpdate { 78 | _startT = [_startInterpolator floatValueForFrame:self.currentFrame] / 100; 79 | _endT = [_endInterpolator floatValueForFrame:self.currentFrame] / 100; 80 | _offsetT = [_offsetInterpolator floatValueForFrame:self.currentFrame] / 360; 81 | } 82 | 83 | - (void)rebuildOutputs { 84 | // Skip this step. 85 | } 86 | 87 | - (LOTBezierPath *)localPath { 88 | return self.inputNode.localPath; 89 | } 90 | 91 | /// Forwards its input node's output path forwards downstream 92 | - (LOTBezierPath *)outputPath { 93 | return self.inputNode.outputPath; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTFillRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTFillRenderer.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTRenderNode.h" 10 | #import "LOTShapeFill.h" 11 | 12 | @interface LOTFillRenderer : LOTRenderNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapeFill:(LOTShapeFill *_Nonnull)fill; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTFillRenderer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTFillRenderer.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTFillRenderer.h" 10 | #import "LOTColorInterpolator.h" 11 | #import "LOTNumberInterpolator.h" 12 | #import "LOTHelpers.h" 13 | 14 | @implementation LOTFillRenderer { 15 | LOTColorInterpolator *colorInterpolator_; 16 | LOTNumberInterpolator *opacityInterpolator_; 17 | BOOL _evenOddFillRule; 18 | CALayer *centerPoint_DEBUG; 19 | } 20 | 21 | - (instancetype)initWithInputNode:(LOTAnimatorNode *)inputNode 22 | shapeFill:(LOTShapeFill *)fill { 23 | self = [super initWithInputNode:inputNode keyName:fill.keyname]; 24 | if (self) { 25 | colorInterpolator_ = [[LOTColorInterpolator alloc] initWithKeyframes:fill.color.keyframes]; 26 | opacityInterpolator_ = [[LOTNumberInterpolator alloc] initWithKeyframes:fill.opacity.keyframes]; 27 | centerPoint_DEBUG = [CALayer layer]; 28 | centerPoint_DEBUG.bounds = CGRectMake(0, 0, 20, 20); 29 | if (ENABLE_DEBUG_SHAPES) { 30 | [self.outputLayer addSublayer:centerPoint_DEBUG]; 31 | } 32 | _evenOddFillRule = fill.evenOddFillRule; 33 | 34 | self.outputLayer.fillRule = _evenOddFillRule ? @"even-odd" : @"non-zero"; 35 | } 36 | return self; 37 | } 38 | 39 | - (NSDictionary *)valueInterpolators { 40 | return @{@"Color" : colorInterpolator_, 41 | @"Opacity" : opacityInterpolator_}; 42 | } 43 | 44 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 45 | return [colorInterpolator_ hasUpdateForFrame:frame] || [opacityInterpolator_ hasUpdateForFrame:frame]; 46 | } 47 | 48 | - (void)performLocalUpdate { 49 | centerPoint_DEBUG.backgroundColor = [colorInterpolator_ colorForFrame:self.currentFrame]; 50 | centerPoint_DEBUG.borderColor = [UIColor lightGrayColor].CGColor; 51 | centerPoint_DEBUG.borderWidth = 2.f; 52 | self.outputLayer.fillColor = [colorInterpolator_ colorForFrame:self.currentFrame]; 53 | self.outputLayer.opacity = [opacityInterpolator_ floatValueForFrame:self.currentFrame]; 54 | } 55 | 56 | - (void)rebuildOutputs { 57 | self.outputLayer.path = self.inputNode.outputPath.CGPath; 58 | } 59 | 60 | - (NSDictionary *)actionsForRenderLayer { 61 | return @{@"backgroundColor": [NSNull null], 62 | @"fillColor": [NSNull null], 63 | @"opacity" : [NSNull null]}; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTGradientFillRender.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTGradientFillRender.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTRenderNode.h" 10 | #import "LOTShapeGradientFill.h" 11 | 12 | @interface LOTGradientFillRender : LOTRenderNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapeGradientFill:(LOTShapeGradientFill *_Nonnull)fill; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTRenderGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTRenderGroup.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 6/27/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTRenderNode.h" 10 | 11 | @interface LOTRenderGroup : LOTRenderNode 12 | 13 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode * _Nullable)inputNode 14 | contents:(NSArray * _Nonnull)contents 15 | keyname:(NSString * _Nullable)keyname; 16 | 17 | @property (nonatomic, strong, readonly) CALayer * _Nonnull containerLayer; 18 | 19 | @end 20 | 21 | 22 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTRepeaterRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTRepeaterRenderer.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/28/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTRenderNode.h" 10 | #import "LOTShapeRepeater.h" 11 | 12 | @interface LOTRepeaterRenderer : LOTRenderNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapeRepeater:(LOTShapeRepeater *_Nonnull)repeater; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTRepeaterRenderer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTRepeaterRenderer.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/28/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTRepeaterRenderer.h" 10 | #import "LOTTransformInterpolator.h" 11 | #import "LOTNumberInterpolator.h" 12 | #import "LOTHelpers.h" 13 | 14 | @implementation LOTRepeaterRenderer { 15 | LOTTransformInterpolator *_transformInterpolator; 16 | LOTNumberInterpolator *_copiesInterpolator; 17 | LOTNumberInterpolator *_offsetInterpolator; 18 | LOTNumberInterpolator *_startOpacityInterpolator; 19 | LOTNumberInterpolator *_endOpacityInterpolator; 20 | 21 | CALayer *_instanceLayer; 22 | CAReplicatorLayer *_replicatorLayer; 23 | CALayer *centerPoint_DEBUG; 24 | } 25 | 26 | - (instancetype)initWithInputNode:(LOTAnimatorNode *)inputNode 27 | shapeRepeater:(LOTShapeRepeater *)repeater { 28 | self = [super initWithInputNode:inputNode keyName:repeater.keyname]; 29 | if (self) { 30 | _transformInterpolator = [[LOTTransformInterpolator alloc] initWithPosition:repeater.position.keyframes 31 | rotation:repeater.rotation.keyframes 32 | anchor:repeater.anchorPoint.keyframes 33 | scale:repeater.scale.keyframes]; 34 | _copiesInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:repeater.copies.keyframes]; 35 | _offsetInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:repeater.offset.keyframes]; 36 | _startOpacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:repeater.startOpacity.keyframes]; 37 | _endOpacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:repeater.endOpacity.keyframes]; 38 | 39 | _instanceLayer = [CALayer layer]; 40 | [self recursivelyAddChildLayers:inputNode]; 41 | 42 | _replicatorLayer = [CAReplicatorLayer layer]; 43 | _replicatorLayer.actions = @{@"instanceCount" : [NSNull null], 44 | @"instanceTransform" : [NSNull null], 45 | @"instanceAlphaOffset" : [NSNull null]}; 46 | [_replicatorLayer addSublayer:_instanceLayer]; 47 | [self.outputLayer addSublayer:_replicatorLayer]; 48 | 49 | centerPoint_DEBUG = [CALayer layer]; 50 | centerPoint_DEBUG.bounds = CGRectMake(0, 0, 20, 20); 51 | if (ENABLE_DEBUG_SHAPES) { 52 | [self.outputLayer addSublayer:centerPoint_DEBUG]; 53 | } 54 | } 55 | return self; 56 | } 57 | 58 | - (NSDictionary *)valueInterpolators { 59 | return @{@"Copies" : _copiesInterpolator, 60 | @"Offset" : _offsetInterpolator, 61 | @"Transform.Anchor Point" : _transformInterpolator.anchorInterpolator, 62 | @"Transform.Position" : _transformInterpolator.positionInterpolator, 63 | @"Transform.Scale" : _transformInterpolator.scaleInterpolator, 64 | @"Transform.Rotation" : _transformInterpolator.rotationInterpolator, 65 | @"Transform.Start Opacity" : _startOpacityInterpolator, 66 | @"Transform.End Opacity" : _endOpacityInterpolator}; 67 | } 68 | 69 | - (void)recursivelyAddChildLayers:(LOTAnimatorNode *)node { 70 | if ([node isKindOfClass:[LOTRenderNode class]]) { 71 | [_instanceLayer addSublayer:[(LOTRenderNode *)node outputLayer]]; 72 | } 73 | if (![node isKindOfClass:[LOTRepeaterRenderer class]] && 74 | node.inputNode) { 75 | [self recursivelyAddChildLayers:node.inputNode]; 76 | } 77 | } 78 | 79 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 80 | // TODO BW Add offset ability 81 | return ([_transformInterpolator hasUpdateForFrame:frame] || 82 | [_copiesInterpolator hasUpdateForFrame:frame] || 83 | [_startOpacityInterpolator hasUpdateForFrame:frame] || 84 | [_endOpacityInterpolator hasUpdateForFrame:frame]); 85 | } 86 | 87 | - (void)performLocalUpdate { 88 | centerPoint_DEBUG.backgroundColor = [UIColor greenColor].CGColor; 89 | centerPoint_DEBUG.borderColor = [UIColor lightGrayColor].CGColor; 90 | centerPoint_DEBUG.borderWidth = 2.f; 91 | 92 | CGFloat copies = ceilf([_copiesInterpolator floatValueForFrame:self.currentFrame]); 93 | _replicatorLayer.instanceCount = (NSInteger)copies; 94 | _replicatorLayer.instanceTransform = [_transformInterpolator transformForFrame:self.currentFrame]; 95 | CGFloat startOpacity = [_startOpacityInterpolator floatValueForFrame:self.currentFrame]; 96 | CGFloat endOpacity = [_endOpacityInterpolator floatValueForFrame:self.currentFrame]; 97 | CGFloat opacityStep = (endOpacity - startOpacity) / copies; 98 | _instanceLayer.opacity = startOpacity; 99 | _replicatorLayer.instanceAlphaOffset = opacityStep; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTStrokeRenderer.h: -------------------------------------------------------------------------------- 1 | // 2 | // LOTStrokeRenderer.h 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/17/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTRenderNode.h" 10 | #import "LOTShapeStroke.h" 11 | 12 | @interface LOTStrokeRenderer : LOTRenderNode 13 | 14 | - (instancetype _Nonnull)initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode 15 | shapeStroke:(LOTShapeStroke *_Nonnull)stroke; 16 | 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /oc 版本代码/lottie-ios/Classes/RenderSystem/RenderNodes/LOTStrokeRenderer.m: -------------------------------------------------------------------------------- 1 | // 2 | // LOTStrokeRenderer.m 3 | // Lottie 4 | // 5 | // Created by brandon_withrow on 7/17/17. 6 | // Copyright © 2017 Airbnb. All rights reserved. 7 | // 8 | 9 | #import "LOTStrokeRenderer.h" 10 | #import "LOTColorInterpolator.h" 11 | #import "LOTNumberInterpolator.h" 12 | 13 | @implementation LOTStrokeRenderer { 14 | LOTColorInterpolator *_colorInterpolator; 15 | LOTNumberInterpolator *_opacityInterpolator; 16 | LOTNumberInterpolator *_widthInterpolator; 17 | LOTNumberInterpolator *_dashOffsetInterpolator; 18 | NSArray *_dashPatternInterpolators; 19 | } 20 | 21 | - (instancetype)initWithInputNode:(LOTAnimatorNode *)inputNode 22 | shapeStroke:(LOTShapeStroke *)stroke { 23 | self = [super initWithInputNode:inputNode keyName:stroke.keyname]; 24 | if (self) { 25 | _colorInterpolator = [[LOTColorInterpolator alloc] initWithKeyframes:stroke.color.keyframes]; 26 | _opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:stroke.opacity.keyframes]; 27 | _widthInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:stroke.width.keyframes]; 28 | 29 | NSMutableArray *dashPatternIntpolators = [NSMutableArray array]; 30 | NSMutableArray *dashPatterns = [NSMutableArray array]; 31 | for (LOTKeyframeGroup *keyframegroup in stroke.lineDashPattern) { 32 | LOTNumberInterpolator *interpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:keyframegroup.keyframes]; 33 | [dashPatternIntpolators addObject:interpolator]; 34 | if (dashPatterns && keyframegroup.keyframes.count == 1) { 35 | LOTKeyframe *first = keyframegroup.keyframes.firstObject; 36 | [dashPatterns addObject:@(first.floatValue)]; 37 | } 38 | if (keyframegroup.keyframes.count > 1) { 39 | dashPatterns = nil; 40 | } 41 | } 42 | 43 | if (dashPatterns.count) { 44 | self.outputLayer.lineDashPattern = dashPatterns; 45 | } else { 46 | _dashPatternInterpolators = dashPatternIntpolators; 47 | } 48 | 49 | if (stroke.dashOffset) { 50 | _dashOffsetInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:stroke.dashOffset.keyframes]; 51 | } 52 | 53 | self.outputLayer.fillColor = nil; 54 | self.outputLayer.lineCap = stroke.capType == LOTLineCapTypeRound ? kCALineCapRound : kCALineCapButt; 55 | switch (stroke.joinType) { 56 | case LOTLineJoinTypeBevel: 57 | self.outputLayer.lineJoin = kCALineJoinBevel; 58 | break; 59 | case LOTLineJoinTypeMiter: 60 | self.outputLayer.lineJoin = kCALineJoinMiter; 61 | break; 62 | case LOTLineJoinTypeRound: 63 | self.outputLayer.lineJoin = kCALineJoinRound; 64 | break; 65 | default: 66 | break; 67 | } 68 | } 69 | return self; 70 | } 71 | 72 | - (NSDictionary *)valueInterpolators { 73 | return @{@"Color" : _colorInterpolator, 74 | @"Opacity" : _opacityInterpolator, 75 | @"Stroke Width" : _widthInterpolator}; 76 | } 77 | 78 | - (void)_updateLineDashPatternsForFrame:(NSNumber *)frame { 79 | if (_dashPatternInterpolators.count) { 80 | NSMutableArray *lineDashPatterns = [NSMutableArray array]; 81 | CGFloat dashTotal = 0; 82 | for (LOTNumberInterpolator *interpolator in _dashPatternInterpolators) { 83 | CGFloat patternValue = [interpolator floatValueForFrame:frame]; 84 | dashTotal = dashTotal + patternValue; 85 | [lineDashPatterns addObject:@(patternValue)]; 86 | } 87 | if (dashTotal > 0) { 88 | self.outputLayer.lineDashPattern = lineDashPatterns; 89 | } 90 | } 91 | } 92 | 93 | - (BOOL)needsUpdateForFrame:(NSNumber *)frame { 94 | [self _updateLineDashPatternsForFrame:frame]; 95 | BOOL dashOffset = NO; 96 | if (_dashOffsetInterpolator) { 97 | dashOffset = [_dashOffsetInterpolator hasUpdateForFrame:frame]; 98 | } 99 | return (dashOffset || 100 | [_colorInterpolator hasUpdateForFrame:frame] || 101 | [_opacityInterpolator hasUpdateForFrame:frame] || 102 | [_widthInterpolator hasUpdateForFrame:frame]); 103 | } 104 | 105 | - (void)performLocalUpdate { 106 | self.outputLayer.lineDashPhase = [_dashOffsetInterpolator floatValueForFrame:self.currentFrame]; 107 | self.outputLayer.strokeColor = [_colorInterpolator colorForFrame:self.currentFrame]; 108 | self.outputLayer.lineWidth = [_widthInterpolator floatValueForFrame:self.currentFrame]; 109 | self.outputLayer.opacity = [_opacityInterpolator floatValueForFrame:self.currentFrame]; 110 | } 111 | 112 | - (void)rebuildOutputs { 113 | self.outputLayer.path = self.inputNode.outputPath.CGPath; 114 | } 115 | 116 | - (NSDictionary *)actionsForRenderLayer { 117 | return @{@"strokeColor": [NSNull null], 118 | @"lineWidth": [NSNull null], 119 | @"opacity" : [NSNull null]}; 120 | } 121 | 122 | @end 123 | --------------------------------------------------------------------------------