有没有一种方法可以将CGContextDrawRadialGradient绘制成椭圆形而不是完美的圆形?

9

我需要一个椭圆形或椭圆形状的径向渐变,但似乎CGContextDrawRadialGradient只能绘制一个完美的圆。我一直在将其绘制到正方形上下文中,然后将其复制/绘制到矩形上下文中。

有更好的方法吗?

谢谢!

2个回答

6

我发现实现这个目标的唯一途径是按照Mark F的建议进行操作,但我认为答案需要一个示例以便更容易理解。

在iOS中(且使用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);
}

用黑色背景呈现,您将得到以下效果:

enter image description here


4

您可以更改上下文的变换以绘制椭圆(例如,在调用CGContextDrawRadialGradient()之前应用CGContextScaleCTM(context,2.0,1.0)以绘制比高度宽两倍的椭圆形渐变)。不过,请记得将反向变换应用于起始点和结束点。


这帮助我找到了正确的方向。谢谢!我在下面用代码示例进行了扩展。 - Erik Tjernlund

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接