2011-01-19 3 views
29

Есть ли у кого-нибудь опыт применения градиента к CAShapeLayer? CAShapeLayer - это класс фантастического слоя, но он, похоже, поддерживает только сплошную заливку, тогда как я хочу, чтобы у него была градиентная заливка (на самом деле это анимативный градиент).Применение градиента к CAShapeLayer

Все, что связано с CAShapeLayer (тени, формы, цвет обводки, анимационный путь) - это фантастика.

Я попытался разместить CAGradientLayer внутри CAShapeLayer или установить CAShapeLayer как маску GradientLayer и добавить оба уровня контейнера, но они не имеют правильного результата.

Должен ли я подкласс CAShapeLayer, или есть лучший способ продвижения вперед?

Спасибо.

+0

Я считаю, что [этот вопрос] (http://stackoverflow.com/questions/1303855/how-to-draw-a-gradient-line-fading-in-out-with-core-graphics-iphone) содержит [ответ Matt Long] (http://stackoverflow.com/questions/1303855/how-to-draw-a-gradient-line-fading-in-out-with-core-graphics-iphone/1303943# 1303943). – Palimondo

ответ

53

Вы можете использовать путь вашей формы, чтобы создать маскирующий слой и применить его на слой с градиентом, как это:

UIView *v = [[UIView alloc] initWithFrame:self.window.frame]; 

CAShapeLayer *gradientMask = [CAShapeLayer layer]; 
gradientMask.fillColor = [[UIColor clearColor] CGColor]; 
gradientMask.strokeColor = [[UIColor blackColor] CGColor]; 
gradientMask.lineWidth = 4; 
gradientMask.frame = CGRectMake(0, 0, v.bounds.size.width, v.bounds.size.height); 

CGMutablePathRef t = CGPathCreateMutable();  
CGPathMoveToPoint(t, NULL, 0, 0); 
CGPathAddLineToPoint(t, NULL, v.bounds.size.width, v.bounds.size.height); 

gradientMask.path = t; 


CAGradientLayer *gradientLayer = [CAGradientLayer layer]; 
gradientLayer.startPoint = CGPointMake(0.5,1.0); 
gradientLayer.endPoint = CGPointMake(0.5,0.0); 
gradientLayer.frame = CGRectMake(0, 0, v.bounds.size.width, v.bounds.size.height); 
NSMutableArray *colors = [NSMutableArray array]; 
for (int i = 0; i < 10; i++) { 
    [colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]]; 
} 
gradientLayer.colors = colors; 

[gradientLayer setMask:gradientMask]; 
[v.layer addSublayer:gradientLayer]; 

Если вы хотите использовать тени, вы должны поместить «дублировать» слой формы под слоем градиента, перерабатывая одну и ту же ссылку на путь.

+2

Это замечательный ответ. Для тех, кто не знал об этом (как и я), я хотел бы добавить, что вы можете добавить маску, градиент, тень и любые другие слои, которые могут понадобиться для слоя Контейнера ('CALayer container = [CALayer layer] '), а затем нужно только управлять этим уровнем контейнера, если вам нужно анимировать его позицию. –

+0

Отличный ответ! Спасибо! – user5685969

2

Это отличное решение, но вы можете столкнуться с непредвиденными проблемами, если вы создаете категорию на CAShapeLayer, где у вас сразу нет представления.

См Setting correct frame of a newly created CAShapeLayer

Нижней линии, получить границы пути установите рамку градиентной маски, используя границу пути и перевести по мере необходимости. Хорошо, что при использовании границ пути, а не любого другого фрейма, градиент будет только соответствовать границам пути (предполагая, что это то, что вы хотите).

// Category on CAShapeLayer 

CGRect pathBounds = CGPathGetBoundingBox(self.path); 

CAShapeLayer *gradientMask = [CAShapeLayer layer]; 
gradientMask.fillColor = [[UIColor blackColor] CGColor]; 
gradientMask.frame = CGRectMake(0, 0, pathBounds.size.width, pathBounds.size.height); 
gradientMask.path = self.path; 

CAGradientLayer *gradientLayer = [CAGradientLayer layer]; 
gradientLayer.startPoint = CGPointMake(0.5,1.0); 
gradientLayer.endPoint = CGPointMake(0.5,0.0); 
gradientLayer.frame = CGRectMake(0, 0, pathBounds.size.width, pathBounds.size.height); 

NSMutableArray *colors = [NSMutableArray array]; 
for (int i = 0; i < 10; i++) { 
    [colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]]; 
} 
gradientLayer.colors = colors; 

[gradientLayer setMask:gradientMask]; 
[self addSublayer:gradientLayer]; 
Смежные вопросы