使用CALayer路径的CABasicAnimation不会设置动画

时间:2012-07-13 02:40:55

标签: core-animation calayer uibezierpath cgpath cabasicanimation

我正在尝试动画CALayer从正常角落到圆角的过渡。我只想绕过顶角,所以我使用的是UIBezierPath。这是代码:

UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight;

UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)];
UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0f, 0.0f)];

CAShapeLayer* layer = [CAShapeLayer layer];
layer.frame = self.bounds;
layer.path = oldPath.CGPath;

self.layer.mask = layer;

CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"];
[a setDuration:0.4f];
[a setFromValue:(id)layer.path];
[a setToValue:(id)newPath.CGPath];

layer.path = newPath.CGPath;
[layer addAnimation:a forKey:@"path"];

但是当我运行它时,角落是圆的,但是没有动画 - 它会立即发生。我在SO上看到了一些类似的问题,但它们并没有解决我的问题。

iPhone CALayer animation

Animating CALayer's shadowPath property

我确信我只是做了一件导致问题的小错误,但对于我的生活,我无法理解。

解决方案:

- (void)roundCornersAnimated:(BOOL)animated {
    UIRectCorner corners = UIRectCornerTopLeft | UIRectCornerTopRight;

    UIBezierPath* newPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(8.0f, 8.0f)];
    UIBezierPath* oldPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corners cornerRadii:CGSizeMake(0.0001f, 0.0001f)];

    CAShapeLayer* layer = [CAShapeLayer layer];
    layer.frame = self.bounds;

    self.layer.mask = layer;

    if(animated) {
        CABasicAnimation* a = [CABasicAnimation animationWithKeyPath:@"path"];
        [a setDuration:0.4f];
        [a setFromValue:(id)oldPath.CGPath];
        [a setToValue:(id)newPath.CGPath];

        layer.path = newPath.CGPath;
        [layer addAnimation:a forKey:@"path"];
    } else {
        layer.path = newPath.CGPath;
    }
}

我真正需要做的就是为动画设置一个正确的'from'值。

3 个答案:

答案 0 :(得分:11)

在我看来,您正在创建一个没有路径的形状图层,然后尝试动画添加路径。形状图层是特殊情况,不会那样工作。

你必须在动画之前和之后的形状图层中有一条路径,并且路径前后需要具有相同的点数。

您需要创建一个圆角矩形路径,其圆角半径为0(手动,使用一系列边和圆弧),然后为要圆角和安装的角创建一个非零半径的新路径该路径作为动画。

尽管这可能不起作用,因为路径需要在其中具有完全相同的点数,并且我怀疑当半径为零时,弧将简化为点。

我刚刚找到了一个UIBezierPath调用,它将创建一个矩形,您可以在其中选择要舍入的角。调用是bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:

这将创建一个包含任意多个圆角的矩形。但是,我不确定它是否适用于路径动画。您可能需要请求所有角都圆角,并将2个非圆角设置为零半径。这样你就可以获得一个与圆角矩形路径具有相同点数的路径,这样路径动画就可以正常工作。你必须尝试一下。

答案 1 :(得分:5)

尝试放置:

layer.path = newPath.CGPath;

后:

[layer addAnimation:a forKey:@"path"];

答案 2 :(得分:0)

安德鲁·瓦格纳here找到了一个非常优雅的解决方案。

系统将尽可能处理所有路径更改动画,您只需要:

  1. 实施CAShapeLayer子类
  2. 覆盖并实施actionForKey
  3. 按照惯例更新路径,您将获得动画!