LOTRadialGradientLayer.m 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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 "LOTRadialGradientLayer.h"
  9. #import "CGGeometry+LOTAdditions.h"
  10. @implementation LOTRadialGradientLayer
  11. @dynamic isRadial;
  12. @dynamic startPoint;
  13. @dynamic endPoint;
  14. @dynamic colors;
  15. @dynamic locations;
  16. + (BOOL)needsDisplayForKey:(NSString *)key {
  17. if ([key isEqualToString:@"startPoint"] ||
  18. [key isEqualToString:@"endPoint"] ||
  19. [key isEqualToString:@"colors"] ||
  20. [key isEqualToString:@"locations"] ||
  21. [key isEqualToString:@"isRadial"]) {
  22. return YES;
  23. }
  24. return [super needsDisplayForKey:key];
  25. }
  26. - (id)actionForKey:(NSString *)key {
  27. id action = self.actions[key];
  28. if (action) {
  29. if (action == [NSNull null]) {
  30. return nil;
  31. }
  32. return action;
  33. }
  34. if ([key isEqualToString:@"startPoint"] ||
  35. [key isEqualToString:@"endPoint"] ||
  36. [key isEqualToString:@"colors"] ||
  37. [key isEqualToString:@"locations"] ||
  38. [key isEqualToString:@"isRadial"]) {
  39. CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:key];
  40. theAnimation.fromValue = [self.presentationLayer valueForKey:key];
  41. return theAnimation;
  42. }
  43. return [super actionForKey:key];
  44. }
  45. - (void)drawInContext:(CGContextRef)ctx {
  46. if (self.colors.count == 0) {
  47. return;
  48. }
  49. NSInteger numberOfLocations = self.locations.count;
  50. CGColorRef colorRef = (__bridge CGColorRef)[self.colors objectAtIndex:0];
  51. NSInteger numberOfComponents = CGColorGetNumberOfComponents(colorRef);
  52. CGColorSpaceRef colorSpace = CGColorGetColorSpace(colorRef);
  53. CGPoint origin = self.startPoint;
  54. CGFloat radius = LOT_PointDistanceFromPoint(self.startPoint, self.endPoint);
  55. CGFloat gradientLocations[numberOfLocations];
  56. CGFloat gradientComponents[numberOfLocations * numberOfComponents];
  57. for (NSInteger locationIndex = 0; locationIndex < numberOfLocations; locationIndex++) {
  58. gradientLocations[locationIndex] = [self.locations[locationIndex] floatValue];
  59. const CGFloat *colorComponents = CGColorGetComponents((__bridge CGColorRef)self.colors[locationIndex]);
  60. for (NSInteger componentIndex = 0; componentIndex < numberOfComponents; componentIndex++) {
  61. gradientComponents[numberOfComponents * locationIndex + componentIndex] = colorComponents[componentIndex];
  62. }
  63. }
  64. CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientComponents, gradientLocations, numberOfLocations);
  65. if (self.isRadial) {
  66. CGContextDrawRadialGradient(ctx, gradient, origin, 0, origin, radius, kCGGradientDrawsAfterEndLocation);
  67. } else {
  68. CGContextDrawLinearGradient(ctx, gradient, self.startPoint, self.endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
  69. }
  70. CGGradientRelease(gradient);
  71. }
  72. @end