CAGradientLayer动画“颜色”而不是“位置”

时间:2013-12-02 21:04:01

标签: ios objective-c core-animation

我正在尝试使用CABasicAnimation为CAGradientLayer的位置数组设置动画。文档说这是可行的。我正在使用以下代码:

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

现在,我认为这可能是一个奇怪的图层/子图层,所以我添加了以下代码来设置颜色动画

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

颜色动画很好,并且在调用第一个位置动画的委托时。

NSString *keyPath = ((CAPropertyAnimation *)anim).keyPath;
if ([keyPath isEqualToString:@"locations"]) {
    _gradientLayer.locations = ((CABasicAnimation *)anim).toValue;
}

其中正确设置了位置的最终状态,但没有动画

2 个答案:

答案 0 :(得分:4)

我下载了您的示例项目并进行了查看。

它有两个问题:

  1. locations数组中的对象数量必须与colours数组中的对象数相同。在您的示例中,您有三种颜色和两个位置,因此核心动画无法计算要执行的正确动画。所以我更新了以下几行:

    NSArray * startingLocations = @[[NSNumber numberWithFloat:0.0f], [NSNumber numberWithFloat:0.4f],[NSNumber numberWithFloat:1.0f]];
    

    fadeAnim.toValue = @[[NSNumber numberWithFloat:0.0f],[NSNumber numberWithFloat:0.8f], [NSNumber numberWithFloat:1.0f]];
    

    这是您的地点没有动画的主要原因

  2. 动画中也有一些不必要的复杂性。它的解释非常好here,但在这种情况下你不需要填充模式或委托。您将位置设置为最终值(这会更新模型图层,但会创建隐式动画)。然后,使用相同的键(在您的情况下,位置)创建显式动画,并将from值设置为start数组。这会覆盖隐式动画。

  3. 我修改后的动画代码版本是:

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

答案 1 :(得分:-1)

“locations”属性的类型是CGPoint的NSArray,因此您需要替换此行:

fadeAnim.toValue = @[[NSNumber numberWithFloat:0.8f], [NSNumber numberWithFloat:1.0f]];

通过以下方式:

fadeAnim.toValue = @[
  [NSValue valueWithCGPoint:CGPointMake(0.2, 1)], 
  [NSValue valueWithCGPoint:CGPointMake(0.8, 1)]
];

将这些值(0.2,1)和(0.8,1)替换为您想要设置动画的实际渐变停止位置。