258 votes

Animation de rotation à 360 degrés UIView Infinite?

Je suis en train de faire tourner un UIImageView 360 degrés, et nous avons examiné plusieurs tutoriels en ligne. J'ai pu obtenir aucun d'eux de travailler, sans l' UIView , soit de l'arrêt ou de sauter à une nouvelle position.

  • Comment puis-je y parvenir?

La dernière chose que j'ai essayé:

[UIView animateWithDuration:1.0
                      delay:0.0
                    options:0
                 animations:^{
                     imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
                 } 
                 completion:^(BOOL finished){
                     NSLog(@"Done!");
                 }];

Mais si j'utilise 2*pi, il ne bouge pas du tout (puisque c'est la même position). Si j'essaie de faire à peu pi (180 degrés), il fonctionne, mais si je l'appelle la méthode de nouveau, il tourne à l'envers.

EDIT:

[UIView animateWithDuration:1.0
                      delay:0.0
                    options:0
                 animations:^{
                     [UIView setAnimationRepeatCount:HUGE_VALF];
                     [UIView setAnimationBeginsFromCurrentState:YES];
                     imageToMove.transform = CGAffineTransformMakeRotation(M_PI);
                 } 
                 completion:^(BOOL finished){
                     NSLog(@"Done!");
                 }];

ne fonctionne pas non plus. Il va à 180 degrés, une pause pour une fraction de seconde, puis repasse à 0 degrés avant qu'il ne commence à nouveau.

335voto

Derek Points 2495

J'ai trouvé une méthode (je l'ai un peu modifiée) qui fonctionnait parfaitement pour moi: iphone UIImageView rotation

 - (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration rotations:(CGFloat)rotations repeat:(float)repeat;
{
    CABasicAnimation* rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
    rotationAnimation.duration = duration;
    rotationAnimation.cumulative = YES;
    rotationAnimation.repeatCount = repeat;

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

112voto

Nate Points 22452

Bravo à Richard J. Ross III pour l'idée, mais j'ai trouvé que son code n'était pas tout à fait ce dont j'avais besoin. La valeur par défaut de options, je crois, est de vous donner des UIViewAnimationOptionCurveEaseInOut, ce qui ne veut pas regarder à droite dans une animation continue. Aussi, j'ai ajouté une case pour que je puisse arrêter mon animation à un même quart de tour si j'avais besoin (ne pas infinie, mais de durée indéterminée durée), et la rampe d'accélération pendant les 90 premiers degrés, et à ralentir pendant les 90 derniers degrés (après un arrêt a été demandé):

// an ivar for your class:
BOOL animating;

- (void) spinWithOptions: (UIViewAnimationOptions) options {
   // this spin completes 360 degrees every 2 seconds
   [UIView animateWithDuration: 0.5f
                         delay: 0.0f
                       options: options
                    animations: ^{
                       self.imageToMove.transform = CGAffineTransformRotate(imageToMove.transform, M_PI / 2);
                    }
                    completion: ^(BOOL finished) {
                       if (finished) {
                          if (animating) {
                             // if flag still set, keep spinning with constant speed
                             [self spinWithOptions: UIViewAnimationOptionCurveLinear];
                          } else if (options != UIViewAnimationOptionCurveEaseOut) {
                             // one last spin, with deceleration
                             [self spinWithOptions: UIViewAnimationOptionCurveEaseOut];
                          }
                       }
                    }];
}

- (void) startSpin {
   if (!animating) {
      animating = YES;
      [self spinWithOptions: UIViewAnimationOptionCurveEaseIn];
   }   
}

- (void) stopSpin {
    // set the flag to stop spinning after one last 90 degree increment
    animating = NO;
}

69voto

ram Points 467

Nate réponse ci-dessus est idéal pour démarrer et arrêter l'animation et donne un meilleur contrôle. J'ai été intrigué pourquoi le vôtre ne fonctionne pas et sa ne. Je voulais partager mes découvertes ici et une version plus simple de code qui devra animer une UIView en continu sans caler.

C'est le code que j'ai utilisé,

- (void)rotateImageView
{
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        [self.imageView setTransform:CGAffineTransformRotate(self.imageView.transform, M_PI_2)];
    }completion:^(BOOL finished){
        if (finished) {
            [self rotateImageView];
        }
    }];
}

J'ai utilisé "CGAffineTransformRotate' au lieu de 'CGAffineTransformMakeRotation" parce que le premier renvoie le résultat est enregistré en tant que l'animation s'exécute. Cela permettra d'éviter le saut ou la réinitialisation de l'affichage de duing l'animation.

Une autre chose est de ne pas utiliser 'UIViewAnimationOptionRepeat' parce qu'à la fin de l'animation avant qu'il ne commence à répéter, il réinitialise le transformer en rendant la vue à revenir à sa position d'origine. Au lieu de répéter, vous répète donc que la transformation n'est jamais remis à zéro à la valeur d'origine parce que le bloc d'animation pratiquement ne se termine jamais.

Et dernière chose, vous avez à transformer l'affichage par incréments de 90 degrés (M_PI / 2) au lieu de 360 ou de 180 degrés (2*M_PI ou M_PI). Parce que la transformation se produit comme une multiplication de matrice de valeurs sinus et cosinus.

t' =  [ cos(angle) sin(angle) -sin(angle) cos(angle) 0 0 ] * t

Donc, dire que si vous utilisez 180 degré de transformation, le cosinus de 180 rendements -1 faire de la transformation de la vue dans la direction opposée à chaque fois (Note-Nate réponse sera également avoir ce problème si vous modifiez le radian valeur de la transformation de M_PI). Un 360 degrés de transformation est de simplement demander l'avis de rester où il était, par conséquent, vous ne voyez pas tout de rotation.

21voto

levigroker Points 309

Si tout ce que vous voulez faire est de faire pivoter l'image à l'infini, cela fonctionne plutôt bien et est très simple:

 NSTimeInterval duration = 10.0f;
CGFloat angle = M_PI / 2.0f;
CGAffineTransform rotateTransform = CGAffineTransformRotate(imageView.transform, angle);

[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionRepeat| UIViewAnimationOptionCurveLinear animations:^{
    imageView.transform = rotateTransform;
} completion:nil];
 

D'après mon expérience, cela fonctionne parfaitement, mais assurez-vous que votre image peut pivoter autour de son centre sans décalage, ou que l'animation d'image "sautera" une fois qu'elle sera contournée par PI.

Pour changer le sens du spin, changez le signe de angle ( angle *= -1 ).

9voto

Richard J. Ross III Points 33152

Utilisez un quart de tour et augmentez le tour de façon incrémentielle.

 void (^block)() = ^{
    imageToMove.transform = CGAffineTransformRotate(imageToMove.transform, M_PI / 2);
}

void (^completion)(BOOL) = ^(BOOL finished){
    [UIView animateWithDuration:1.0
                          delay:0.0
                        options:0
                     animations:block
                     completion:completion];
}

completion(YES);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X