Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing a conical or arcing gradient using Core Animation layers

I need to draw a circular line and fill this line with a gradient using Core Animation. This is not a major problem since I'm using a CAGradientLayer and masking it with a CAShapeLayer. The problem is that the gradient should be like the one seen in this thread.

There are a lot of solutions already there but let me explain why they don't work for me:

-I can't use an image because I need to animate the locations property array of the CAGradientLayer

-I'm not using Core Graphics to draw everything because, as I said, nearly everything in this circle I'm trying to draw should be animatable.

-The class available here is a possible solution but not optimal, since it requires a new view for every circle I need to draw, which is not optimal for me (in case there is no other solution I'll maybe use this one)

-I can't use the solution in this question because it works only with a simple, two-color gradient

Here is the code I'm using to draw the circle:

int radius = 100;
CAShapeLayer *circle = [CAShapeLayer layer];
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(50, 60, 2.0*radius,    2.0*radius)cornerRadius:radius].CGPath;

circle.lineWidth = 10;
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor blackColor].CGColor;



CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = CGRectMake(50, 60, 300, 300);
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, 300, 300);
NSMutableArray *colors = [NSMutableArray array];
NSMutableArray *locations = [NSMutableArray array];
[colors addObject:(id)[[UIColor colorWithRed:134.0/255.0 green: 234.0/255.0   blue:63.0/255.0 alpha:1.0] CGColor]];
[colors addObject:(id)[[UIColor colorWithRed:215.0/255.0 green: 82.0/255.0 blue:76.0/255.0 alpha:1.0] CGColor]];
[colors addObject:(id)[[UIColor colorWithRed:28.0/255.0 green:28.0/255.0 blue:28.0/255.0 alpha:1.0] CGColor]];
[locations addObject:(id)[NSNumber numberWithFloat:0.2]];
[locations addObject:(id)[NSNumber numberWithFloat:0.5]];
[locations addObject:(id)[NSNumber numberWithFloat:0.8]];
gradientLayer.colors = colors;
gradientLayer.locations = locations;
[gradientLayer setMask:circle];

[sender.layer addSublayer:gradientLayer];
like image 227
Philip Müller Avatar asked Jan 03 '14 13:01

Philip Müller


1 Answers

I would suggest using a custom Core Image filter to solve the problem.

For each pixel you can calculate the angle from the center of the filtered image. Convert this angle into a value between 0.0 and 1.0. Using these values, you can map a color value to the calculated pixel.

If you write this "Core Image Kernel Language", it should process very fast. You can animate the input values using core animation to animate the resulting gradient.

like image 164
Flovdis Avatar answered Oct 09 '22 04:10

Flovdis