CALayer и CGGradientRef сглаживание? - PullRequest
4 голосов
/ 19 апреля 2009

У меня странная проблема с рисованием CALayer для iPhone. У меня есть корневой слой, который добавляет кучу подслоев, представляющих «пузыри». Конечный результат должен выглядеть примерно так:

http://www.expensivedna.com/IMG_0018.PNG http://www.expensivedna.com/IMG_0018.PNG

Проблема в том, что я не могу получить слой с псевдонимом (обратите внимание на неровности пузырьков). Мой код перезаписывает drawInContext для пузырькового CALayer следующим образом:

- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.5,  // Start color
                          1.0, 1.0, 1.0, 0.0 }; // End color
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef glossGradient = 
CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

CGPoint topCenter = CGPointMake(25, 20);
CGPoint midCenter = CGPointMake(25, 25);
CGContextDrawRadialGradient(theContext, glossGradient, midCenter, 20, topCenter, 10, kCGGradientDrawsAfterEndLocation); 

}

Теперь действительно странным является то, что если я немного изменю код рисования, чтобы нарисовать только нормальные красные круги следующим образом:

- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

CGContextSetFillColorWithColor(theContext, [UIColor redColor].CGColor);
CGContextFillEllipseInRect(theContext, CGRectMake(0, 0, 40,40));
}

Все, кажется, сумасшедшим. ОК:

http://www.expensivedna.com/IMG_0017.PNG http://www.expensivedna.com/IMG_0017.PNG

Я не могу понять это, казалось бы, странное поведение. Я пропускаю некоторую разницу между градиентами сглаживания и нормальными кругами?

Спасибо, ребята.

Ответы [ 3 ]

4 голосов
/ 10 мая 2009

Спасибо, ребята. Вот и получается, что ответ - это комбинация двух ваших ответов (coob и Alex). По сути, кажется, что функция CGDrawRadialGradient имеет псевдонимы только на начальном круге, а не на конечном. Так как я хочу использовать псевдонимы «ребра» на обоих, я сначала устанавливаю функцию рисования изнутри, которая заботится о первом «ребре», но производит следующее:

Шаг 1

Затем я обрезаю изображение в соответствии с предложением coob, и это дает хороший псевдоним вокруг последнего края пузыря:

Шаг 2

Выглядит достаточно хорошо для меня!

- (void)drawInContext:(CGContextRef)theContext{
CGContextSetAllowsAntialiasing(theContext, true);
CGContextSetShouldAntialias(theContext, true);

size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 1.0, 1.0, 0.0,  // Start color
              1.0, 1.0, 1.0, 0.5 }; // End color
CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef glossGradient = 
CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);

CGContextAddEllipseInRect(theContext, CGRectMake(5, 5, 40, 40));
CGContextClip(theContext);

CGPoint topCenter = CGPointMake(25, 20);
CGPoint midCenter = CGPointMake(25, 25);
CGContextDrawRadialGradient(theContext, glossGradient, topCenter, 10, midCenter, 20, kCGGradientDrawsAfterEndLocation);

}

2 голосов
/ 08 мая 2009

Джефф - сделайте topCenter немного дальше и используйте CGContextClipToMask с круглой маской.

Редактировать: На самом деле гораздо лучший способ сделать это - использовать путь отсечения векторов с помощью CGContextClip.

Редактировать 2: Пример кода:

CGContextAddEllipseInRect(theContext, CGRectMake(20, 20, 10, 10));
CGContextClip(theContext);

Добавьте это, прежде чем рисовать свой градиент, и нарисуйте его немного дальше.

0 голосов
/ 22 апреля 2009

может быть, попробовать сбросить kCGGradientDrawsAfterEndLocation? Это может быть что-то странное с альфа

...