LOTComposition.m 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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. #import "LOTComposition.h"
  9. #import "LOTLayer.h"
  10. #import "LOTAssetGroup.h"
  11. #import "LOTLayerGroup.h"
  12. #import "LOTAnimationCache.h"
  13. @implementation LOTComposition
  14. # pragma mark - Convenience Initializers
  15. + (nullable instancetype)animationNamed:(nonnull NSString *)animationName {
  16. return [self animationNamed:animationName inBundle:[NSBundle mainBundle]];
  17. }
  18. + (nullable instancetype)animationNamed:(nonnull NSString *)animationName inBundle:(nonnull NSBundle *)bundle {
  19. if (!animationName) {
  20. return nil;
  21. }
  22. NSArray *components = [animationName componentsSeparatedByString:@"."];
  23. animationName = components.firstObject;
  24. LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName];
  25. if (comp) {
  26. return comp;
  27. }
  28. NSError *error;
  29. NSString *filePath = [bundle pathForResource:animationName ofType:@"json"];
  30. NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
  31. if (@available(iOS 9.0, *)) {
  32. if (!jsonData) {
  33. jsonData = [[NSDataAsset alloc] initWithName:animationName bundle:bundle].data;
  34. }
  35. }
  36. NSDictionary *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
  37. options:0 error:&error] : nil;
  38. if (JSONObject && !error) {
  39. LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:bundle];
  40. [[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName];
  41. laScene.cacheKey = animationName;
  42. return laScene;
  43. }
  44. NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__);
  45. return nil;
  46. }
  47. + (nullable instancetype)animationWithFilePath:(nonnull NSString *)filePath {
  48. NSString *animationName = filePath;
  49. LOTComposition *comp = [[LOTAnimationCache sharedCache] animationForKey:animationName];
  50. if (comp) {
  51. return comp;
  52. }
  53. NSError *error;
  54. NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
  55. NSDictionary *JSONObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
  56. options:0 error:&error] : nil;
  57. if (JSONObject && !error) {
  58. LOTComposition *laScene = [[self alloc] initWithJSON:JSONObject withAssetBundle:[NSBundle mainBundle]];
  59. laScene.rootDirectory = [filePath stringByDeletingLastPathComponent];
  60. [[LOTAnimationCache sharedCache] addAnimation:laScene forKey:animationName];
  61. laScene.cacheKey = animationName;
  62. return laScene;
  63. }
  64. NSLog(@"%s: Animation Not Found", __PRETTY_FUNCTION__);
  65. return nil;
  66. }
  67. + (nonnull instancetype)animationFromJSON:(nonnull NSDictionary *)animationJSON {
  68. return [self animationFromJSON:animationJSON inBundle:[NSBundle mainBundle]];
  69. }
  70. + (nonnull instancetype)animationFromJSON:(nullable NSDictionary *)animationJSON inBundle:(nullable NSBundle *)bundle {
  71. return [[self alloc] initWithJSON:animationJSON withAssetBundle:bundle];
  72. }
  73. #pragma mark - Initializer
  74. - (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nullable)jsonDictionary
  75. withAssetBundle:(NSBundle * _Nullable)bundle {
  76. self = [super init];
  77. if (self) {
  78. if (jsonDictionary) {
  79. [self _mapFromJSON:jsonDictionary withAssetBundle:bundle];
  80. }
  81. }
  82. return self;
  83. }
  84. #pragma mark - Internal Methods
  85. - (void)_mapFromJSON:(NSDictionary *)jsonDictionary
  86. withAssetBundle:(NSBundle *)bundle {
  87. NSNumber *width = jsonDictionary[@"w"];
  88. NSNumber *height = jsonDictionary[@"h"];
  89. if (width && height) {
  90. CGRect bounds = CGRectMake(0, 0, width.floatValue, height.floatValue);
  91. _compBounds = bounds;
  92. }
  93. _startFrame = [jsonDictionary[@"ip"] copy];
  94. _endFrame = [jsonDictionary[@"op"] copy];
  95. _framerate = [jsonDictionary[@"fr"] copy];
  96. if (_startFrame && _endFrame && _framerate) {
  97. NSInteger frameDuration = (_endFrame.integerValue - _startFrame.integerValue) - 1;
  98. NSTimeInterval timeDuration = frameDuration / _framerate.floatValue;
  99. _timeDuration = timeDuration;
  100. }
  101. NSArray *assetArray = jsonDictionary[@"assets"];
  102. if (assetArray.count) {
  103. _assetGroup = [[LOTAssetGroup alloc] initWithJSON:assetArray withAssetBundle:bundle withFramerate:_framerate];
  104. }
  105. NSArray *layersJSON = jsonDictionary[@"layers"];
  106. if (layersJSON) {
  107. _layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON
  108. withAssetGroup:_assetGroup
  109. withFramerate:_framerate];
  110. }
  111. [_assetGroup finalizeInitializationWithFramerate:_framerate];
  112. }
  113. - (void)setRootDirectory:(NSString *)rootDirectory {
  114. _rootDirectory = rootDirectory;
  115. self.assetGroup.rootDirectory = rootDirectory;
  116. }
  117. @end