Is there a way to draw a CGContextDrawRadialGradie

2019-03-20 07:05发布

I need a radial gradient in the shape of an oval or ellipse and it seems like it CGContextDrawRadialGradient can only draw a perfect circle. I've been drawing to a square context then copying/drawing into a rectangular context.

Any better way to do this?

Thanks!

2条回答
我命由我不由天
2楼-- · 2019-03-20 08:02

The only way I've found to do this is as Mark F suggested, but I think the answer needs an example to be easier to understand.

Draw an elliptical gradient in a view in iOS (and using ARC):

- (void)drawRect:(CGRect)rect {

    CGContextRef ctx = UIGraphicsGetCurrentContext();

    // Create gradient
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGFloat locations[] = {0.0, 1.0};

    UIColor *centerColor = [UIColor orangeColor];
    UIColor *edgeColor = [UIColor purpleColor];

    NSArray *colors = [NSArray arrayWithObjects:(__bridge id)centerColor.CGColor, (__bridge id)edgeColor.CGColor, nil];
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

    // Scaling transformation and keeping track of the inverse
    CGAffineTransform scaleT = CGAffineTransformMakeScale(2, 1.0);
    CGAffineTransform invScaleT = CGAffineTransformInvert(scaleT);

    // Extract the Sx and Sy elements from the inverse matrix
    // (See the Quartz documentation for the math behind the matrices)
    CGPoint invS = CGPointMake(invScaleT.a, invScaleT.d);

    // Transform center and radius of gradient with the inverse
    CGPoint center = CGPointMake((self.bounds.size.width / 2) * invS.x, (self.bounds.size.height / 2) * invS.y);
    CGFloat radius = (self.bounds.size.width / 2) * invS.x;

    // Draw the gradient with the scale transform on the context
    CGContextScaleCTM(ctx, scaleT.a, scaleT.d);
    CGContextDrawRadialGradient(ctx, gradient, center, 0, center, radius, kCGGradientDrawsBeforeStartLocation);

    // Reset the context
    CGContextScaleCTM(ctx, invS.x, invS.y);

    // Continue to draw whatever else ...

    // Clean up the memory used by Quartz
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
}

Put in a view with a black background you get:

enter image description here

查看更多
男人必须洒脱
3楼-- · 2019-03-20 08:08

You can change the transform of the context to draw an ellipse (for example, apply CGContextScaleCTM(context, 2.0, 1.0) just before calling CGContextDrawRadialGradient () to draw an elliptical gradient that's twice as wide as it is high). Just remember to apply the inverse transform to your start and end points, though.

查看更多
登录 后发表回答