LOTGradientFillRender.m 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. //
  2. // LOTGradientFillRender.m
  3. // Lottie
  4. //
  5. // Created by brandon_withrow on 7/27/17.
  6. // Copyright © 2017 Airbnb. All rights reserved.
  7. //
  8. #import "LOTGradientFillRender.h"
  9. #import "LOTArrayInterpolator.h"
  10. #import "LOTPointInterpolator.h"
  11. #import "LOTNumberInterpolator.h"
  12. #import "CGGeometry+LOTAdditions.h"
  13. #import "LOTHelpers.h"
  14. #import "LOTRadialGradientLayer.h"
  15. @implementation LOTGradientFillRender {
  16. BOOL _evenOddFillRule;
  17. CALayer *centerPoint_DEBUG;
  18. CAShapeLayer *_maskShape;
  19. LOTRadialGradientLayer *_gradientOpacityLayer;
  20. LOTRadialGradientLayer *_gradientLayer;
  21. NSInteger _numberOfPositions;
  22. CGPoint _startPoint;
  23. CGPoint _endPoint;
  24. LOTArrayInterpolator *_gradientInterpolator;
  25. LOTPointInterpolator *_startPointInterpolator;
  26. LOTPointInterpolator *_endPointInterpolator;
  27. LOTNumberInterpolator *_opacityInterpolator;
  28. }
  29. - (instancetype)initWithInputNode:(LOTAnimatorNode *)inputNode
  30. shapeGradientFill:(LOTShapeGradientFill *)fill {
  31. self = [super initWithInputNode:inputNode keyName:fill.keyname];
  32. if (self) {
  33. _gradientInterpolator = [[LOTArrayInterpolator alloc] initWithKeyframes:fill.gradient.keyframes];
  34. _startPointInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:fill.startPoint.keyframes];
  35. _endPointInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:fill.endPoint.keyframes];
  36. _opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:fill.opacity.keyframes];
  37. _numberOfPositions = fill.numberOfColors.integerValue;
  38. _evenOddFillRule = fill.evenOddFillRule;
  39. CALayer *wrapperLayer = [CALayer new];
  40. _maskShape = [CAShapeLayer new];
  41. _maskShape.fillRule = _evenOddFillRule ? @"even-odd" : @"non-zero";
  42. _maskShape.fillColor = [UIColor whiteColor].CGColor;
  43. _maskShape.actions = @{@"path": [NSNull null]};
  44. _gradientOpacityLayer = [LOTRadialGradientLayer new];
  45. _gradientOpacityLayer.isRadial = (fill.type == LOTGradientTypeRadial);
  46. _gradientOpacityLayer.actions = @{@"startPoint" : [NSNull null],
  47. @"endPoint" : [NSNull null],
  48. @"opacity" : [NSNull null],
  49. @"locations" : [NSNull null],
  50. @"colors" : [NSNull null],
  51. @"bounds" : [NSNull null],
  52. @"anchorPoint" : [NSNull null],
  53. @"isRadial" : [NSNull null]};
  54. _gradientOpacityLayer.mask = _maskShape;
  55. [wrapperLayer addSublayer:_gradientOpacityLayer];
  56. _gradientLayer = [LOTRadialGradientLayer new];
  57. _gradientLayer.isRadial = (fill.type == LOTGradientTypeRadial);
  58. _gradientLayer.mask = wrapperLayer;
  59. _gradientLayer.actions = [_gradientOpacityLayer.actions copy];
  60. [self.outputLayer addSublayer:_gradientLayer];
  61. centerPoint_DEBUG = [CALayer layer];
  62. centerPoint_DEBUG.bounds = CGRectMake(0, 0, 20, 20);
  63. if (ENABLE_DEBUG_SHAPES) {
  64. [self.outputLayer addSublayer:centerPoint_DEBUG];
  65. }
  66. }
  67. return self;
  68. }
  69. - (NSDictionary *)valueInterpolators {
  70. return @{@"Start Point" : _startPointInterpolator,
  71. @"End Point" : _endPointInterpolator,
  72. @"Opacity" : _opacityInterpolator};
  73. }
  74. - (BOOL)needsUpdateForFrame:(NSNumber *)frame {
  75. return ([_gradientInterpolator hasUpdateForFrame:frame] ||
  76. [_startPointInterpolator hasUpdateForFrame:frame] ||
  77. [_endPointInterpolator hasUpdateForFrame:frame] ||
  78. [_opacityInterpolator hasUpdateForFrame:frame]);
  79. }
  80. - (void)performLocalUpdate {
  81. centerPoint_DEBUG.backgroundColor = [UIColor magentaColor].CGColor;
  82. centerPoint_DEBUG.borderColor = [UIColor lightGrayColor].CGColor;
  83. centerPoint_DEBUG.borderWidth = 2.f;
  84. _startPoint = [_startPointInterpolator pointValueForFrame:self.currentFrame];
  85. _endPoint = [_endPointInterpolator pointValueForFrame:self.currentFrame];
  86. self.outputLayer.opacity = [_opacityInterpolator floatValueForFrame:self.currentFrame];
  87. NSArray *numberArray = [_gradientInterpolator numberArrayForFrame:self.currentFrame];
  88. NSMutableArray *colorArray = [NSMutableArray array];
  89. NSMutableArray *locationsArray = [NSMutableArray array];
  90. NSMutableArray *opacityArray = [NSMutableArray array];
  91. NSMutableArray *opacitylocationsArray = [NSMutableArray array];
  92. for (int i = 0; i < _numberOfPositions; i++) {
  93. int ix = i * 4;
  94. NSNumber *location = numberArray[ix];
  95. NSNumber *r = numberArray[(ix + 1)];
  96. NSNumber *g = numberArray[(ix + 2)];
  97. NSNumber *b = numberArray[(ix + 3)];
  98. [locationsArray addObject:location];
  99. UIColor *color = [UIColor colorWithRed:r.floatValue green:g.floatValue blue:b.floatValue alpha:1];
  100. [colorArray addObject:(id)(color.CGColor)];
  101. }
  102. for (NSInteger i = (_numberOfPositions * 4); i < numberArray.count; i = i + 2) {
  103. NSNumber *opacityLocation = numberArray[i];
  104. [opacitylocationsArray addObject:opacityLocation];
  105. NSNumber *opacity = numberArray[i + 1];
  106. UIColor *opacityColor = [UIColor colorWithWhite:1 alpha:opacity.floatValue];
  107. [opacityArray addObject:(id)(opacityColor.CGColor)];
  108. }
  109. if (opacityArray.count == 0) {
  110. _gradientOpacityLayer.backgroundColor = [UIColor whiteColor].CGColor;
  111. } else {
  112. _gradientOpacityLayer.startPoint = _startPoint;
  113. _gradientOpacityLayer.endPoint = _endPoint;
  114. _gradientOpacityLayer.locations = opacitylocationsArray;
  115. _gradientOpacityLayer.colors = opacityArray;
  116. }
  117. _gradientLayer.startPoint = _startPoint;
  118. _gradientLayer.endPoint = _endPoint;
  119. _gradientLayer.locations = locationsArray;
  120. _gradientLayer.colors = colorArray;
  121. }
  122. - (void)rebuildOutputs {
  123. CGRect frame = [self.inputNode.outputPath bounds];
  124. CGPoint modifiedAnchor = CGPointMake(-frame.origin.x / frame.size.width,
  125. -frame.origin.y / frame.size.height);
  126. _maskShape.path = self.inputNode.outputPath.CGPath;
  127. _gradientOpacityLayer.bounds = frame;
  128. _gradientOpacityLayer.anchorPoint = modifiedAnchor;
  129. _gradientLayer.bounds = frame;
  130. _gradientLayer.anchorPoint = modifiedAnchor;
  131. }
  132. - (NSDictionary *)actionsForRenderLayer {
  133. return @{@"backgroundColor": [NSNull null],
  134. @"fillColor": [NSNull null],
  135. @"opacity" : [NSNull null]};
  136. }
  137. @end