2011-01-19 29 views
29

Czy ktokolwiek ma jakiekolwiek doświadczenie w stosowaniu gradientu do CAShapeLayer? CAShapeLayer to fantastyczna klasa warstwowa, ale wydaje się, że obsługuje tylko kolory wypełnienia stałego, podczas gdy ja chciałbym, aby wypełnienie było gradientem (w rzeczywistości jest to animowany gradient).Stosowanie gradientu do CAShapeLayer

Cała reszta z CAShapeLayer (cienie, kształty, kolor obrysu, animowalna ścieżka kształtu) jest fantastyczna.

Próbowałem wstawić CAGradientLayer wewnątrz CAShapeLayer, lub faktycznie ustawiając CAShapeLayer jako maskę GradientLayer i dodając obie do warstwy kontenera, ale te nie mają właściwego rezultatu.

Czy należy podklasę CAShapeLayer, czy jest lepszy sposób na przyszłość?

Dzięki.

+0

wierzę [to pytanie] (http://stackoverflow.com/questions/1303855/how-to-draw-a-gradient-line-fading-in-out-with-core-graphics-iphone) zawiera odpowiedź [odpowiedź Matt Long] (http://stackoverflow.com/questions/1303855/how-to-draw-a-gradient-line-fading-in-out-w-core-core-graphics-iphone/1303943# 1303943). – Palimondo

Odpowiedz

53

Można użyć ścieżki swojego kształtu, aby utworzyć warstwę maskującą i zastosować że na warstwie gradientu, tak:

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]; 

Jeśli chcesz także użyć cieni, trzeba by umieszczenia "duplikowanie" warstwy kształtu pod warstwą gradientu, przetwarzanie tego samego odniesienia do ścieżki.

+2

To jest niesamowita odpowiedź. Dla tych, którzy nie są tego świadomi (jak ja), chciałbym dodać, że można dodać maskę, gradient, cień i dowolne inne warstwy, które mogą być potrzebne do warstwy kontenera ('CALayer container = [warstwa CALayer] '), a następnie zarządzaj tylko tą warstwą kontenera, jeśli chcesz animować jej położenie. –

+0

Świetna odpowiedź! Dziękuję Ci! – user5685969

2

To jest świetne rozwiązanie, ale możesz napotkać nieoczekiwane problemy, jeśli tworzysz kategorię na CAShapeLayer, gdzie nie masz od razu widoku.

Zobacz Setting correct frame of a newly created CAShapeLayer

dolnej linii, uzyskać granice ścieżki następnie ustawić ramkę maski gradientu Korzystanie granice ścieżek i tłumaczyć jak to konieczne. Dobrą rzeczą jest to, że używając granic ścieżki, a nie jakiejkolwiek innej ramki, gradient będzie pasował tylko w granicach ścieżki (zakładając, że tego właśnie chcesz).

// 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];