Подтвердить что ты не робот

Применение градиента к CAShapeLayer

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

Все остальное, что связано с CAShapeLayer (тени, формы, цвет штриха, анимационный путь формы), фантастически.

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

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

Спасибо.

4b9b3361

Ответ 1

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

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

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

См. Установка правильного кадра только что созданного 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];