【问题标题】:CABasicAnimation with CALayer path doesn't animate带有 CALayer 路径的 CABasicAnimation 不设置动画
【发布时间】:2012-07-12 21:19:02
【问题描述】:

我正在尝试动画化 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”值。

【问题讨论】:

  • 解决方案作为答案而不是问题的一部分会很好,但这无论如何都是有帮助的,所以 +1 :)

标签: core-animation calayer uibezierpath cgpath cabasicanimation


【解决方案1】:

从 Andrew Wagner here 那里找到了一个非常优雅的解决方案。

基本上系统会处理所有路径更改动画,您只需要:

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

【讨论】:

    【解决方案2】:

    试着放:

    layer.path = newPath.CGPath;
    

    之后:

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

    【讨论】:

      【解决方案3】:

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

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

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

      但即使这样也可能行不通,因为路径中需要有完全相同数量的点,而且我怀疑当半径为零时弧会简化为点。

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

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

      【讨论】:

      • 谢谢。你是对的。为动画设置正确的“来自”值就可以了。
      猜你喜欢
      • 2023-03-25
      • 2012-08-25
      • 1970-01-01
      • 2019-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-18
      相关资源
      最近更新 更多