1

ポーカー デッキから 3 枚のカードを順番に配る一連のアニメーションを作成しようとしています。3枚のカードの位置をアニメートしたいだけです.最初のアニメーションは最初のカードの位置ですぐに始まり、0.4秒間続き、2番目のアニメーションは0.4秒後に同じ長さで始まり、最後のアニメーションは0.8秒後に始まります。これを行う方法がわかりません!以下のコードは機能しません。を使用する必要があるかもしれCAGroupAnimationませんが、同じプロパティで一連のアニメーションのグループを作成する方法がわかりません!

        CGFloat beginTime = 0.0;

        for (Card *c in cards) {
            CardLayer *cardLayer = [cardToLayerDictionary objectForKey:c];

            CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
            anim.fromValue = [NSValue valueWithCGPoint:stockLayer.position];
            anim.toValue = [NSValue valueWithCGPoint:wasteLayer.position];
            anim.duration = 0.4;
            anim.beginTime = beginTime;
            beginTime += 0.4;
            cardLayer.position = wasteLayer.position;
            [cardLayer addAnimation:anim forKey:@"position"];

            …
         }
4

2 に答える 2

4

アインシュタインが言ったように、時間は相対的です。すべてのレイヤーbeginTime、そのスーパーレイヤーの時空間に相対的です--- アニメーション化されていないため、最終的にはすべて同じになります。

次の 2 つの解決策が考えられるようです。

  1. 絶対タイムベースを取得し、各レイヤーのアニメーションbeginTimeをそれに対して相対的に設定します。

    int i = 0; float delay = 0.4;
    for (Card *c in cards) {
        // ...
        float baseTime = [cardLayer convertTime:CACurrentMediaTime() fromLayer:nil];
        anim.beginTime = baseTime + (delay * i++);
        // ...
    }
    
  2. 各カードのアニメーションをグループにまとめます。なんらかの理由で、これらのグループは互いに分離されていますが、これにより、これらのアニメーションが共通のタイムスケールに置かれます。一部の人にとってはうまくいきましたが、私はそれを信頼するのは少し気が進まないです---遠く離れた不気味なアクションのようです.

いずれにせよ、レイヤーをアニメーションの最後にある場所にとどめたいと思うでしょう。次のようにアニメーションを「くっつける」ことができます。

anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;

しかし、それは後で問題を引き起こす可能性があります---レイヤーのモデルの位置はまだ開始位置にあり、アニメーションの後にそれを調整すると(たとえば、カードをドラッグするために)、奇妙な結果が得られる可能性があります. CATransactionそのため、レイヤーの最終位置を設定する完了ブロックを設定する でカード ディール アニメーションをラップすることが適切な場合があります。


s と完了ブロックについて言えば、CATransactionそれらを使用して暗黙的なアニメーションを順番に実行できます (他の理由で明示的なアニメーションを使用していない場合)。

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    [CATransaction begin];
    [CATransaction setCompletionBlock:^{
        card3Layer.position = wasteLayer.position;
    }];
    card2Layer.position = wasteLayer.position;
    [CATransaction end];
}];
card1Layer.position = wasteLayer.position;
[CATransaction end];
于 2012-04-18T06:52:09.063 に答える
0

次の再帰的な方法は、アニメーションを連鎖させるために私ができる最善の方法です。を使用しCATransactionてプロパティをアニメーション化positionし、次のカードを再帰的に呼び出すブロックを設定します。

-(void)animateDeal:(NSMutableArray*)cardLayers {
    if ([cardLayers count] > 0) {
        CardLayer *cardLayer = [cardLayers objectAtIndex:0];
        [cardLayers removeObjectAtIndex:0];

         // ...set new cardLayer.zPosition with animations disabled...

        [CATransaction begin];
        [CATransaction setCompletionBlock:^{[self animateDeal:cardLayers];}];
        [CATransaction setAnimationDuration:0.25];
        [cardLayer setFaceUp:YES];
        cardLayer.position = wasteLayer.position;
        [CATransaction commit];
    }
}

もちろん、これは時間間隔が重複する連鎖の問題を解決するものではありません。

于 2012-04-20T15:38:22.393 に答える