Есть ли способ нарисовать CGContextDrawRadialGradient в виде овала вместо идеального круга? - PullRequest
7 голосов
/ 02 августа 2011

Мне нужен радиальный градиент в форме овала или эллипса, и кажется, что CGContextDrawRadialGradient может нарисовать только идеальный круг. Я рисовал в квадратный контекст, затем копировал / рисовал в прямоугольный контекст.

Есть ли лучший способ сделать это?

Спасибо!

Ответы [ 2 ]

5 голосов
/ 01 октября 2012

Единственный способ, который я нашел, это сделать, как предложил Марк Ф., но я думаю, что для ответа требуется пример, который будет легче понять.

Рисование эллиптического градиента на виде в 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 голосов
/ 09 января 2012

Вы можете изменить преобразование контекста, чтобы нарисовать эллипс (например, применить CGContextScaleCTM (context, 2.0, 1.0) непосредственно перед вызовом CGContextDrawRadialGradient (), чтобы нарисовать эллиптический градиент, который в два раза шире его высоты). Просто не забудьте применить обратное преобразование к начальной и конечной точкам.

...