tag: CGColorSpaceRef CGContextDrawLinearGradient CGContextDrawRadialGradient

The demo here

Commonly used framework collection PYKit

Pod import POD ‘PYGradientView’

The sample

  1. Add a View
self.gradientView = [PYGradientView new];
    CGRect gradientViewFrame = self.view.bounds;
    self.gradientView.frame = gradientViewFrame;
    [self.view addSubview:self.gradientView];
Copy the code
  1. There are two types of Config
    1. Linear gradientPYGradientViewLineConfig PYGradientViewObject call methoddrawLineGradientSet linear Config and draw the gradient immediately
[self.gradientView drawLineGradient:^(PYGradientViewLineConfig *lineConfig) {
            lineConfig
            .setUpScaleEndCenter(CGPointMake(0, 0))
            .setUpScaleStartCenter(CGPointMake(1, 1))
            .setUpColorArray(@[
                               UIColor.redColor,
                               UIColor.cyanColor
                               ])
            .setUpLocationArray(@[
                                  @0,@1
                                  ]);
    
        }];
Copy the code
  • Diffusion gradientPYGradientViewDrawRadialConfig PYGradientViewObject call methoddrawRadialGradientSet linear Config and draw the gradient immediately
[self.gradientView drawRadialGradient:^(PYGradientViewDrawRadialConfig *radialConfig) { radialConfig SetUpScaleEndCenter (CGPointMake (0.5, 0.5)). SetUpScaleStartCenter (CGPointMake (0.5, 0.5)). SetUpColorArray (@ [UIColor redColor, SetUpStartRadius (0).setupendRADIUS (1000).setuplocationArray (@[@0.1,@1]);}];Copy the code

The specific implementation

Rewrite the drawRect method

  1. Linear gradient main method
# pragma mark linear gradient - (void) drawLineGradientWithContext: (CGContextRef) context {/ / 2. Create a color space CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB (); / / 3. Create a gradient object NSInteger count = self. DrawLineConfig. ColorArray. Count; CGFloat *components = [self parseColorArray:self.drawLineConfig.colorArray]; CGFloat *locations = [self parseLocationWithArray:self.drawLineConfig.locationArray andLenth:count]; CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorSpaceRef,components,locations,count); PYGradientViewLineConfig *config = self.drawLineConfig; CGPoint startCenter = [self getCenterWithCenter:config.startCenter andScaleCenter:config.startScaleCenter]; CGPoint endCenter = [self getCenterWithCenter:config.endCenter andScaleCenter:config.endScaleCenter]; / * * * * startCenter gradientRef said color space for absolute beginning * endCenter said absolute end position * / CGContextDrawLinearGradient (context, gradientRef, startCenter, endCenter, config.options); [self freeArray:components]; [self freeArray:locations]; CFRelease(colorSpaceRef); CFRelease(gradientRef); }Copy the code
  1. Diffusion gradient
# pragma mark radial gradient - (void) drawRadialGradientWithContext context: (CGContextRef) {/ / CGColorSpaceRef using RGB color space colorSpace=CGColorSpaceCreateDeviceRGB(); Note that since RGB color space is specified, four array elements represent one color (red, green, blue, alpha). Locations: Locations of colors (range 0 to 1). The number of colors in the array is no less than the number of colors stored in the components. Count: Number of gradients. Is equal to the number of locations * / / / / analysis color ARGB NSInteger count = self. DrawRadialConfig. ColorArray. Count; CGFloat *compoents = [self parseColorArray:self.drawRadialConfig.colorArray]; CGFloat *locations= [self parseLocationWithArray:self.drawRadialConfig.locationArray andLenth:count]; CGGradientRef gradient= CGGradientCreateWithColorComponents(colorSpace, compoents, locations, count); StartCenter: startRadius: startRadius (usually 0, otherwise there is no padding in this radius) endCenter: end position (usually the same as the start point, Otherwise there will be a deviation) endRadius: at the end of the radius (that is, the gradient of the diffusion length) options: drawing modes, kCGGradientDrawsBeforeStartLocation drawing before starting position, but to the end position after drawing, no longer Don't draw before kCGGradientDrawsAfterEndLocation starting position, But to the end point after continue filling * / PYGradientViewDrawRadialConfig * config = self. DrawRadialConfig; CGPoint startCenter = [self getCenterWithCenter:config.startCenter andScaleCenter:config.startScaleCenter]; CGPoint endCenter = [self getCenterWithCenter:config.endCenter andScaleCenter:config.endScaleCenter]; CGContextDrawRadialGradient(context, gradient, startCenter, config.startRadius, endCenter, config.endRadius, config.options); CGColorSpaceRelease(colorSpace); // Release CGGradientRelease(gradient); // Free the memory space of the color array [self freeArray: compoents]; [self freeArray:locations]; }Copy the code
  1. NSArrayArray is converted to CGFloatOther methods
- (CGPoint) getCenterWithCenter:(CGPoint)center andScaleCenter: (CGPoint)scaleCenter { if(! CGPointEqualToPoint(center, PYGradientViewConfigPointDefault)) { return center; } if (! CGPointEqualToPoint(scaleCenter, PYGradientViewConfigPointDefault)) { CGFloat x = self.frame.size.width * scaleCenter.x; CGFloat y = self.frame.size.height * scaleCenter.y; return CGPointMake(x, y); } NSLog(@".\ n 🌶 %@: Center failed ",[self class]); return CGPointMake(0, 0); } - (CGFloat *)parseColorArray: (NSArray <UIColor *>*)colorArray { NSInteger count = colorArray.count; CGFloat *compoents = [self createArrayWithLenth:4 * count]; for (int idx = 0; idx < count; idx ++) { UIColor *color = colorArray[idx]; CGFloat r,g,b,a = 0; [color getRed:&r green:&g blue:&b alpha:&a]; NSInteger currentIMinValue = idx * 4; CGFloat RGBA[4] = {r,g,b,a}; for (NSInteger i = currentIMinValue; i < 4 * (idx + 1); I ++) {// get ARGB compoents[I] = RGBA[i-currentiminValue]; } } return compoents; } - (CGFloat *) parseLocationWithArray: (NSArray <NSNumber *>*)array andLenth: (NSInteger)lenth{ NSInteger count = lenth; CGFloat *locations = [self createArrayWithLenth:count]; for (int i = 0; i < count; i++) { CGFloat value = 1; if (array.count <= i) { value = array.lastObject.floatValue; }else{ value = array[i].floatValue; }; locations[i] = value; } return locations; } /** Create c array @param Len length @return return C array */ - (CGFloat *)createArrayWithLenth: (NSInteger)len { return malloc(sizeof(CGFloat) * len); } - (void) freeArray: (CGFloat *)array { free(array); } - (CGFloat *)arrayAddLenth: (NSInteger)len andArray: (CGFloat *)array{ len = sizeof(array)/sizeof(*array) + len; CGFloat *array_old = array; array = (CGFloat *)realloc(array,sizeof(CGFloat)*len); /* if(array_old! = array_old! = array_old! = array) free(array_old); return array; }Copy the code