Reputation: 445
I am attempting to animate a CAGradientLayer's locations array using a CABasicAnimation. The docs say this is doable. I'm using the following code:
CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"locations"];
fadeAnim.fromValue = _gradientLayer.locations;
fadeAnim.toValue = @[[NSNumber numberWithFloat:0.8f], [NSNumber numberWithFloat:1.0f]];
fadeAnim.duration = 3.0;
fadeAnim.delegate = self;
[fadeAnim setFillMode:kCAFillModeForwards];
[fadeAnim setDuration:3.0f];
[fadeAnim setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[_gradientLayer addAnimation:fadeAnim forKey:@"animation"];
Now, I thought this might be a weird layer/sublayer case, so I added the following code to animate the colors
CABasicAnimation* fadeAnim1 = [CABasicAnimation animationWithKeyPath:@"colors"];
fadeAnim1.toValue = @[(id)[UIColor greenColor].CGColor,(id)[transparentColor CGColor],(id)[UIColor blueColor].CGColor];
fadeAnim1.duration = 5.0;
[_gradientLayer addAnimation:fadeAnim1 forKey:@"colorAnimation"];
The colors animate fine, and when the delegate for the first locations animation is called.
NSString *keyPath = ((CAPropertyAnimation *)anim).keyPath;
if ([keyPath isEqualToString:@"locations"]) {
_gradientLayer.locations = ((CABasicAnimation *)anim).toValue;
}
Which correctly sets the final state of locations, but without the animation
Upvotes: 3
Views: 3006
Reputation: 119272
I downloaded your sample project and took a look.
There were two problems with it:
You must have the same number of objects in your locations
array as you do in your colours
array. In your example you have three colours and two locations, so core animation can't calculate the correct animation to perform. So I updated the following lines:
NSArray * startingLocations = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:0.4f],[NSNumber numberWithFloat:1.0f]];
and
fadeAnim.toValue = @[[NSNumber numberWithFloat:0.0f],[NSNumber numberWithFloat:0.8f], [NSNumber numberWithFloat:1.0f]];
This is the principal reason your locations are not animating
You also have some unnecessary complexity in the animation. It's explained very well here, but you don't need fill modes or a delegate in this case. You set your locations to the final value (this updates the model layer, but creates an implicit animation). You then create an explicit animation with the same key (in your case, locations) and set the from value to your start array. This overrides the implicit animation.
My revised version of the animation code is this:
//Create gradient layer
_gradientLayer = [CAGradientLayer layer];
_gradientLayer.frame = maskedImageView.bounds;
_gradientLayer.colors = colors;
//set locations for the colors
NSArray * startingLocations = @[@0.0, @0.4,@1.0];
NSArray *endinglocations = @[@0.0,@0.8,@1.0];
// Update the model layer to the final point
_gradientLayer.locations = endinglocations;
_gradientLayer.startPoint = CGPointMake(0.0f, 0.3f);
_gradientLayer.endPoint = CGPointMake(1.0f, 0.5f);
//add the text image as a mask on the gradient layer
_gradientLayer.mask = maskedImageView.layer;
//add the gradient layer to the holder view
[_slideImageView.layer addSublayer:_gradientLayer];
//Create animation for the "locations" aspect of the gradient layer
CABasicAnimation* fadeAnim = [CABasicAnimation animationWithKeyPath:@"locations"];
//Set the starting locations to the previously applied array
fadeAnim.fromValue = startingLocations;
// 3 seconds of run time
[fadeAnim setDuration:3.0f];
//linear and straight timing since we want it smooth
[fadeAnim setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
//do the magic and apply the animation
[_gradientLayer addAnimation:fadeAnim forKey:@"locations"];
Upvotes: 5
Reputation: 156
The type of the "locations" property is NSArray of CGPoint, so you'd need to replace this line:
fadeAnim.toValue = @[[NSNumber numberWithFloat:0.8f], [NSNumber numberWithFloat:1.0f]];
by something like this:
fadeAnim.toValue = @[
[NSValue valueWithCGPoint:CGPointMake(0.2, 1)],
[NSValue valueWithCGPoint:CGPointMake(0.8, 1)]
];
replacing those values (0.2, 1) and (0.8, 1) with the actual gradient stop locations you want to animate to.
Upvotes: -1