LOTStrokeRenderer.m 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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. #import "LOTStrokeRenderer.h"
  9. #import "LOTColorInterpolator.h"
  10. #import "LOTNumberInterpolator.h"
  11. @implementation LOTStrokeRenderer {
  12. LOTColorInterpolator *_colorInterpolator;
  13. LOTNumberInterpolator *_opacityInterpolator;
  14. LOTNumberInterpolator *_widthInterpolator;
  15. LOTNumberInterpolator *_dashOffsetInterpolator;
  16. NSArray *_dashPatternInterpolators;
  17. }
  18. - (instancetype)initWithInputNode:(LOTAnimatorNode *)inputNode
  19. shapeStroke:(LOTShapeStroke *)stroke {
  20. self = [super initWithInputNode:inputNode keyName:stroke.keyname];
  21. if (self) {
  22. _colorInterpolator = [[LOTColorInterpolator alloc] initWithKeyframes:stroke.color.keyframes];
  23. _opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:stroke.opacity.keyframes];
  24. _widthInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:stroke.width.keyframes];
  25. NSMutableArray *dashPatternIntpolators = [NSMutableArray array];
  26. NSMutableArray *dashPatterns = [NSMutableArray array];
  27. for (LOTKeyframeGroup *keyframegroup in stroke.lineDashPattern) {
  28. LOTNumberInterpolator *interpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:keyframegroup.keyframes];
  29. [dashPatternIntpolators addObject:interpolator];
  30. if (dashPatterns && keyframegroup.keyframes.count == 1) {
  31. LOTKeyframe *first = keyframegroup.keyframes.firstObject;
  32. [dashPatterns addObject:@(first.floatValue)];
  33. }
  34. if (keyframegroup.keyframes.count > 1) {
  35. dashPatterns = nil;
  36. }
  37. }
  38. if (dashPatterns.count) {
  39. self.outputLayer.lineDashPattern = dashPatterns;
  40. } else {
  41. _dashPatternInterpolators = dashPatternIntpolators;
  42. }
  43. if (stroke.dashOffset) {
  44. _dashOffsetInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:stroke.dashOffset.keyframes];
  45. }
  46. self.outputLayer.fillColor = nil;
  47. self.outputLayer.lineCap = stroke.capType == LOTLineCapTypeRound ? kCALineCapRound : kCALineCapButt;
  48. switch (stroke.joinType) {
  49. case LOTLineJoinTypeBevel:
  50. self.outputLayer.lineJoin = kCALineJoinBevel;
  51. break;
  52. case LOTLineJoinTypeMiter:
  53. self.outputLayer.lineJoin = kCALineJoinMiter;
  54. break;
  55. case LOTLineJoinTypeRound:
  56. self.outputLayer.lineJoin = kCALineJoinRound;
  57. break;
  58. default:
  59. break;
  60. }
  61. }
  62. return self;
  63. }
  64. - (NSDictionary *)valueInterpolators {
  65. return @{@"Color" : _colorInterpolator,
  66. @"Opacity" : _opacityInterpolator,
  67. @"Stroke Width" : _widthInterpolator};
  68. }
  69. - (void)_updateLineDashPatternsForFrame:(NSNumber *)frame {
  70. if (_dashPatternInterpolators.count) {
  71. NSMutableArray *lineDashPatterns = [NSMutableArray array];
  72. CGFloat dashTotal = 0;
  73. for (LOTNumberInterpolator *interpolator in _dashPatternInterpolators) {
  74. CGFloat patternValue = [interpolator floatValueForFrame:frame];
  75. dashTotal = dashTotal + patternValue;
  76. [lineDashPatterns addObject:@(patternValue)];
  77. }
  78. if (dashTotal > 0) {
  79. self.outputLayer.lineDashPattern = lineDashPatterns;
  80. }
  81. }
  82. }
  83. - (BOOL)needsUpdateForFrame:(NSNumber *)frame {
  84. [self _updateLineDashPatternsForFrame:frame];
  85. BOOL dashOffset = NO;
  86. if (_dashOffsetInterpolator) {
  87. dashOffset = [_dashOffsetInterpolator hasUpdateForFrame:frame];
  88. }
  89. return (dashOffset ||
  90. [_colorInterpolator hasUpdateForFrame:frame] ||
  91. [_opacityInterpolator hasUpdateForFrame:frame] ||
  92. [_widthInterpolator hasUpdateForFrame:frame]);
  93. }
  94. - (void)performLocalUpdate {
  95. self.outputLayer.lineDashPhase = [_dashOffsetInterpolator floatValueForFrame:self.currentFrame];
  96. self.outputLayer.strokeColor = [_colorInterpolator colorForFrame:self.currentFrame];
  97. self.outputLayer.lineWidth = [_widthInterpolator floatValueForFrame:self.currentFrame];
  98. self.outputLayer.opacity = [_opacityInterpolator floatValueForFrame:self.currentFrame];
  99. }
  100. - (void)rebuildOutputs {
  101. self.outputLayer.path = self.inputNode.outputPath.CGPath;
  102. }
  103. - (NSDictionary *)actionsForRenderLayer {
  104. return @{@"strokeColor": [NSNull null],
  105. @"lineWidth": [NSNull null],
  106. @"opacity" : [NSNull null]};
  107. }
  108. @end