2

CAGradientLayer (グラデーションとフレーム) をアニメーション化しようとしていますが、フレームを 0 までアニメーション化すると、ビューの左上隅まで縮小し、水平方向にアニメーション化したいと考えています。現在、水平方向と垂直方向の両方で 0 にアニメーション化しています。

現在のアニメーションは次のようになります。

CAGradientLayer のアニメーション化

私が望むのは、それが何もなくなったときに、水平方向のみに縮小し、ずっと同じ高さを維持することです。

現在使用しているコードは次のとおりです。

- (void)drawRect:(CGRect)rect
{
// Drawing code
if (!gradientLayer) {
    gradientLayer = [CAGradientLayer layer];
    [gradientLayer setFrame:[self createRectForFrame:rect]];
    [gradientLayer setColors:@[(id)fromColor.CGColor, (id)toColor.CGColor]];
    [gradientLayer setStartPoint:CGPointMake(fillPct/100, 0.5)];
    [gradientLayer setEndPoint:CGPointMake(1.0, 0.5)];
    [self.layer addSublayer:gradientLayer];
}
else {
    [gradientLayer removeAllAnimations];

    [CATransaction begin];

    [CATransaction setAnimationDuration:ANIMATION_DURATION];
    CGRect newFrame = [self createRectForFrame:rect];
    CABasicAnimation *frameAnimation = [CABasicAnimation animationWithKeyPath:@"frame"];
    [frameAnimation setDuration:ANIMATION_DURATION];
    [frameAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [frameAnimation setFromValue:[NSValue valueWithCGRect:gradientLayer.bounds]];
    [frameAnimation setToValue:[NSValue valueWithCGRect:newFrame]];
    [frameAnimation setFillMode:kCAFillModeForwards];
    [frameAnimation setRemovedOnCompletion:NO];
    [gradientLayer setFrame:newFrame];
    [gradientLayer addAnimation:frameAnimation forKey:@"frame"];

    CGPoint startPoint = CGPointMake(MIN(fillPct/100, 0.99), 0.5);
    CABasicAnimation *startPointAnimation = [CABasicAnimation animationWithKeyPath:@"startPoint"];
    [startPointAnimation setDuration:ANIMATION_DURATION];
    [startPointAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    [startPointAnimation setFromValue:[NSValue valueWithCGPoint:gradientLayer.startPoint]];
    [startPointAnimation setToValue:[NSValue valueWithCGPoint:startPoint]];
    [startPointAnimation setFillMode:kCAFillModeForwards];
    [startPointAnimation setRemovedOnCompletion:NO];
    [gradientLayer setStartPoint:startPoint];
    [gradientLayer addAnimation:startPointAnimation forKey:@"startPoint"];

    [CATransaction setCompletionBlock:^{
        [self updateInnerLabelTextColor];
    }];

    [CATransaction commit];
}
[self bringInnerLabelToFront];
}

- (CGRect)createRectForFrame:(CGRect)frame {
if (fillPct == 0)
    return CGRectZero;
else if (fillPct >= 100)
    return frame;
else
    return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width * (fillPct / 100), frame.size.height);
}

fillPct は、バーを埋める値で、0 から 100 の間です。

4

1 に答える 1

2

問題は次の行です。

CGPoint startPoint = CGPointMake(MIN(fillPct/100, 0.99), 0.5);

次のように変更した場合:

CGPoint startPoint = CGPointMake(0.0, 0.5);

コーナーで収縮することなく、思い通りに機能します。

または、現在のコードを保持したい場合は、この値を変更することもできます:

CGPoint startPoint = CGPointMake(MIN(fillPct/100, 0.0), 0.5);

テストしたところです。水平方向にアニメーションします。お役に立てれば。

更新 1:

あなたがコメントで言及した問題は実際には経験しませんでした。でも、もう一度見てみることにしました。これを何度も呼び出す方法とに恣意的な値を提供しなかったのでrect、私は自分の値を思いつき、再度テストしました。

私はこの値で を設定しましたgradientLayer:

[gradientLayer setFrame:(CGRect){{150.0f, 240.0f}, 150.0f, 20.0f}];

最初のCABasicAnimationでは、テスト目的で、これを変更しました。

[frameAnimation setToValue:[NSValue valueWithCGRect:(CGRect){{150.0f, 240.0f}, 0.0f, 20.0f}]];

ご覧のとおり、幅が 0.0f であることを除いて、レイヤーの rect とまったく同じです。幅が 0 になると想像してみてください。

上記は機能しますか?はい。

上記はあなたが望むように機能しますか?いいえ。

その理由は、フレームが均一に収縮するためです。ここで必要なものではありません。

したがって、作成時にこれを追加しますgradientLayer

gradientLayer.anchorPoint = (CGPoint){0.0f, 0.5f};

繰り返しますが、私はそれをテストしましたが、この記事を書いている時点で私の前で実行されています。ちなみに見てて楽しいです。

これがまた役立つことを願っています。

于 2014-04-25T02:12:54.150 に答える