20

通常のコーナーから丸みを帯びたコーナーへの 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 アニメーション

CALayer の shadowPath プロパティをアニメーション化する

私は問題を引き起こしている小さなことを間違っているだけだと確信していますが、私の人生ではそれを理解することはできません.

解決:

- (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」値を設定することだけでした。

4

3 に答える 3

11

パスのないシェイプレイヤーを作成し、それにパスを追加するアニメーションを作成しようとしているように見えます。シェイプレイヤーは特殊なケースであり、そのようには機能しません。

アニメーションの前後にシェイプレイヤーにパスが必要であり、パスには前後に同じ数のポイントが含まれている必要があります。

角の半径が0の角の丸い長方形のパスを作成し(手動で、一連の辺と角の円弧を使用)、丸くしたい角の半径がゼロ以外の新しいパスを作成して、そのパスを次のようにインストールする必要があります。あなたのアニメーション。

ただし、パスにはまったく同じ数のポイントが含まれている必要があるため、それでも機能しない可能性があります。半径がゼロの場合、円弧はポイントに単純化されると思います。

丸める角を選択できる長方形を作成するUIBezierPath呼び出しを見つけました。呼び出しはbezierPathWithRoundedRect:byRoundingCorners:cornerRadii:です。

これにより、必要な数の角の丸い長方形が作成されます。ただし、パスアニメーションで機能するかどうかはわかりません。丸みのない2つの角を半径ゼロに設定して、すべての角を丸くするように要求する必要がある場合があります。そうすれば、丸みを帯びた長方形のパスと同じ数のポイントを含むパスを取得できるため、パスアニメーションが正しく機能します。あなたはそれを試してみる必要があります。

于 2012-07-13T13:16:30.637 に答える
5

入れてみてください:

layer.path = newPath.CGPath;

後:

[layer addAnimation:a forKey:@"path"];
于 2014-04-10T09:29:59.940 に答える
0

Andrew Wagner hereからの本当にエレガントなソリューションを見つけました。

基本的に、システムはすべてのパス変更アニメーションを処理します。必要なのは次のことだけです。

  1. CAShapeLayer サブクラスを実装する
  2. オーバーライドして実装するactionForKey
  3. いつものようにパスを更新すると、アニメーションが表示されます!
于 2018-04-13T07:47:37.617 に答える