5

私のアプリはCALayer、ビューを描画するために使用します。より正確には、の最上位レイヤーのdrawLayer:inContext:サブレイヤーでメソッドを使用しUIViewます。これは、連続する描画の「暗黙の」アニメーションをdrawLayer:inContext:時間の経過とともに互いにフェードアウトさせる良い方法です。フェード アニメーションはかなり速く (おそらく 0.25 秒) 発生しますが、その持続時間を変更するには、単に という別のデリゲート メソッドを実装しactionForLayer:forKey:ます。この完全に機能する実装例では、デフォルトの持続時間が 2.0 秒に引き伸ばされます。

- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
    animation.duration = 2.0;
    return animation;

    // or return nil for the default duration.
}

当面の問題に移ります。

フェードが完了する時間よりも速く呼び出す[sublayer setNeedsDisplay]と、新しいフェードごとに突然のジャンプが見られます。見た目から、進行中のフェードがキャンセルされ、その最終状態が新しいフェードの開始点として使用されます。これはそれほど驚くべきことではないかもしれませんが、視覚的な結果はかなり望ましくありません。

黒から白への 10 秒間のフェードと、開始の 5 秒後にトリガーされる別の黒へのフェードのシナリオを考えてみましょう。アニメーションは黒から白にフェードし始めますが、「中間のグレー」になると、再び黒にフェードする前に完全な白にジャンプします。

これを防ぐ方法はありますか?レイヤーをグレーから黒に戻すことはできますか? UIViewAnimationOptionBeginFromCurrentState(UIView アニメーションで使用される)言うことに相当する CALayer の描画はありますか?

乾杯。

4

3 に答える 3

2

レイヤーのアニメーションは、アニメーション化するときにレイヤーがどのように見えるかを視覚的に表現したものにすぎません。CAでは、ある状態から別の状態にアニメーション化すると、レイヤーの状態全体がすぐに変化します。プレゼンテーション層が作成されてアニメーションが表示され、アニメーションが完了すると、実際の層が最後に残されます。

したがって、ある状態から別の状態に移行する必要があり、現在のアニメーションがまだ完了していない場合は、アニメーションの現在の状態をキャプチャして、これを次のアニメーションの開始点として使用する必要があると思います。

問題は、レイヤーの現在のアニメーションを変更できないことにあります。

次の投稿では、アニメーションの現在の状態をキャプチャし、それをレイヤーの現在の状態として設定し、それをアニメーションの開始値として使用します。投稿では、この手法をアニメーションの速度/継続時間に適用していますが、シナリオにも適用できます。

https://stackoverflow.com/a/9544674/1218605

于 2012-04-28T17:06:15.987 に答える
1

私もこれには少し困惑しています。

fillMode の指定を忘れていませんかkCAFillModeForwards。詳細については、リファレンス ドキュメントを参照してください

たとえば、デュレーションを変更していませんが、これをスナップせずに動作させました。

@implementation FadingLayer

- (void)fadeOut {    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    animation.fillMode = kCAFillModeForwards;
    animation.fromValue = (id)[UIColor redColor].CGColor;
    animation.toValue = (id)[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
    animation.removedOnCompletion = FALSE;
    animation.delegate = self;    
    [self addAnimation:animation
                    forKey:@"test"];
}

- (void)fadeIn {
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"backgroundColor"];
    animation.fillMode = kCAFillModeForwards;
    animation.fromValue = (id)[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
    animation.toValue = (id)[UIColor redColor].CGColor;
    animation.removedOnCompletion = FALSE;
    animation.delegate = self;    
    [self addAnimation:animation
                    forKey:@"test"];
}

@end

ただし、おそらくカスタム プロパティをアニメーション化する必要があります。

お役に立てれば :/

于 2012-04-27T14:43:43.507 に答える
0

レイヤー ツリーのズーム アニメーションで同じことを達成したかったのです。ユーザーがそれに応じてレイヤーツリーをズームできるズームイン/ズームアウトキーに相当します。ただし、ユーザーがズーム キーに相当するキーをすばやく連続して押すと、前のアニメーションがまだ完了していないため、アニメーションの開始前の値に一時的にスナップバックします。

アニメーション コードの最後でソールを実行すると、[CATransaction commit]保留中のトランザクションが次のアニメーションの開始前にレイヤー モデルに強制的にコミットされ、問題が解決されました。

ドキュメントには次のように記載されています。

+ コミット

現在のトランザクション中に行われたすべての変更をコミットします。

宣言

+ (無効) コミット

特別な考慮事項

現在のトランザクションが存在しない場合、例外が発生します。

ただし、これを[CATransaction commit]連続して多くのメッセージでテストしても、実際には例外は発生しません。これと同じ手法を使用して、次のフォームの警告を抑制しました。

CoreAnimation: 警告、CATransaction がコミットされていないスレッドが削除されました。

レイヤ アニメーションが終了する前に実行スレッドが終了する NSOperation で。ドキュメントを更新せずに、現在のトランザクションが存在しない場合、Apple が最近の OS リリースでこの動作をノーオペレーションに変更した可能性があります。

于 2015-09-17T00:03:00.580 に答える