6

には 2 つの回転アニメーションがありますCAAnimationGroup。1 つはゼロから開始し、もう 1 つはその状態から繰り返して自動反転します。

- (void)addWobbleAnimationToView:(UIView *)view amount:(float)amount speed:(float)speed
{
    NSMutableArray *anims = [NSMutableArray array];

    // initial wobble
    CABasicAnimation *startWobble = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    startWobble.toValue = [NSNumber numberWithFloat:-amount];
    startWobble.duration = speed/2.0;
    startWobble.beginTime = 0;
    startWobble.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [anims addObject:startWobble];

    // rest of wobble
    CABasicAnimation *wobbleAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    wobbleAnim.fromValue = [NSNumber numberWithFloat:-amount];
    wobbleAnim.toValue = [NSNumber numberWithFloat:amount];
    wobbleAnim.duration = speed;
    wobbleAnim.beginTime = speed/2.0;
    wobbleAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    wobbleAnim.autoreverses = YES;
    wobbleAnim.repeatCount = INFINITY;
    [anims addObject:wobbleAnim];

    CAAnimationGroup *wobbleGroup = [CAAnimationGroup animation];
    wobbleGroup.duration = DBL_MAX; // this stops it from working
    wobbleGroup.animations = anims;

    [view.layer addAnimation:wobbleGroup forKey:@"wobble"];
}

CFTimeInterval は double として定義されているため、アニメーション グループの期間を に設定しようとしましたDBL_MAXが、アニメーション グループの実行が停止します。ただし、10000 などの大きな数値に設定すると、問題なく動作します。CAAnimationGroup可能な限り無限に近く実行されるように、a の期間に使用できる最大数は何ですか?

更新:のように非常に大きな値をDBL_MAX / 4.0入力すると、1 秒間フリーズしてからアニメーションを開始するようです。値DBL_MAX / 20.0を入力すると、最初のフリーズははるかに小さくなります。期間の値が非常に大きいため、フリーズしているようです。期間に非常に大きな値を使用する以外に、これを行うより良い方法はありますか?

4

2 に答える 2

1

私は今、まったく同じ問題に直面しています...誰かが私が間違っていることを証明してくれることを願っていますが、この状況を処理するための唯一の合理的な方法は、最初のアニメーションを に移動し、次CATransactionを使用して自動反転アニメーションでチェーンすることです。

[CATransaction setCompletionBlock:block];

理想的ではありませんが、仕事は完了します。

バックグラウンドから戻ったときにアニメーションが一時停止するという質問については、これは CoreAnimation フレームワークの古典的な制限であり、多くの解決策が提案されています。timeOffset私がそれを解決する方法は、プロパティをランダム化することにより、アニメーションのランダムなポイントでアニメーションをリセットすることです。アプリがバックグラウンドにあったため、ユーザーはアニメーションの状態がどうあるべきかを正確に知ることができません。これが役立つコードです(//RANDOMIZE!!コメントを探してください):

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(startAnimating)
                                             name:UIApplicationWillEnterForegroundNotification
                                           object:[UIApplication sharedApplication]];

...

for (CALayer* layer in _layers) 
{
    // RANDOMIZE!!!
    int index = arc4random()%[levels count];
    int level = ...;
    CGFloat xOffset = ...;

    layer.position = CGPointMake(xOffset, self.bounds.size.height/5.0f + yOffset * level);

    CGFloat speed = (1.5f + (arc4random() % 40)/10.f);
    CGFloat duration = (int)((self.bounds.size.width - xOffset)/speed);

    NSString* keyPath = @"position.x";
    CABasicAnimation* anim = [CABasicAnimation animationWithKeyPath:keyPath];

    anim.fromValue      = @(xOffset);
    anim.toValue        = @(self.bounds.size.width);
    anim.duration       = duration;
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    // RANDOMIZE!!
    anim.timeOffset     = arc4random() % (int) duration;
    anim.repeatCount    = INFINITY;

    [layer removeAnimationForKey:keyPath];
    [layer addAnimation:anim forKey:keyPath];
    [_animatingLayers addObject:layer];
}
于 2013-08-02T20:22:25.873 に答える