2017-08-26 1 views
3

J'utilise ce code pour faire pivoter une vue:Smoothly accélérer une animation de rotation de fonctionnement

func rotateAnimation(theView: UIView, duration: CFTimeInterval = 20.0, repeatCount: Float = 200, toValue: CGFloat = CGFloat(.pi * 2.0)) { 
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation") 
    rotateAnimation.fromValue = 0.0 
    rotateAnimation.toValue = toValue 
    rotateAnimation.duration = duration 
    rotateAnimation.repeatCount = repeatCount 
    theView.layer.add(rotateAnimation, forKey: nil) 
} 

Je voudrais savoir comment accélérer cette animation en cours d'exécution. Si par exemple un UIView tourne avec le code ci-dessus, comment puis-je faire en sorte que cette vitesse soit deux fois plus rapide avec une bonne transition?

Donc: appels rotateAnimation: rotation à vitesse normale ->appels? Fonction? -> UIView va doucement tourner plus vite à la vitesse désirée -> UIView continuera à tourner à la vitesse désirée.

Merci pour toute aide.

+0

ne changeant l'aide de la durée? – 3stud1ant3

+0

@ 3stud1ant3 Non, cela change la vitesse mais après quelques secondes, l'animation revient à sa vitesse d'origine. – NoKey

+0

Sur la même note que la modification de la durée, avez-vous essayé une boucle while avec la ligne de condition spécifiant la position finale de l'animation? – ProgrammingEnthusiast

Répondre

2

S'il vous plaît Essayez ci-dessous le code

 let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in 
      self.viewToMove.layer.timeOffset = self.viewToMove.layer.convertTime(CACurrentMediaTime(), from: nil) 
      self.viewToMove.layer.beginTime = CACurrentMediaTime() 
      self.viewToMove.layer.speed += 0.5 

     } 
     timer.fire() 

Il augmentera la vitesse d'animation très facilement

+0

Oui merci ça marche avec quelques lignes de code :) –

0

Essayez ceci pour la deuxième animation

Vous pouvez définir la durée plus petite pour augmenter la vitesse

func rotateAnimation(theView: UIView, duration: CFTimeInterval = 0.4, repeatCount: Float = 200, toValue: CGFloat = CGFloat(.pi * 2.0)) { 
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation") 
    rotateAnimation.fromValue = 0.0 
    rotateAnimation.toValue = toValue 
    rotateAnimation.duration = duration 
    rotateAnimation.repeatCount = repeatCount 

Et mettre shouldRasterize = true pour une meilleure performance

theView.layer.rasterizationScale = UIScreen.main.scale 
    theView.layer.shouldRasterize = true 

Utilisez la même clé pour les deux animations

theView.layer.add(rotateAnimation, forKey: "animation") 
} 
0

Définissez repeatcount sur 1 et rajoutez l'animation après chaque animation arrêtée. Je ne suis pas sûr si cela cause problème de performance dans votre scénario depuis que je l'ai testé avec une vue carrée très basique.

En ajoutant un paramètre CAMediaTimingFunction, vous êtes en mesure de contrôler si vous souhaitez utiliser kCAMediaTimingFunctionLinear - pour les boucles d'animation normales, ou d'utiliser un personnalisé, comme kCAMediaTimingFunctionEaseIn - pour l'image clé d'animation pour montrer une transition en douceur .

// your function to start the acceleration 
@IBAction func buttonTapped(_ sender: UIButton) { 
    accel = true 
    speed = 2.0 
    timeOffset = self.rect.layer.convertTime(CACurrentMediaTime(), from: nil) 
    timeOffset = timeOffset - lastStart 
    // memorize the timeoffset, new speed (2x) and a boolean flag 
    self.rect.layer.removeAllAnimations() 
} 

// delegate - memorize the CFTimeInterval 
func animationDidStart(_ anim: CAAnimation) { 
    lastStart = self.rect.layer.convertTime(CACurrentMediaTime(), from: nil) 
} 

// delegate - start a new loop of animation each time it's stopped 
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { 
    if accel { 
     accel = false 
     let opt = CAMediaTimingFunction(controlPoints: 0.5, 0.2, 0.9, 0.7) 
     rotateAnimation(theView: rect, speed: speed, fromValue: CGFloat(.pi * 2.0 * Float(timeOffset)/10.0), toValue: CGFloat(.pi * 2.0 * Float(timeOffset)/10.0 + .pi * 2.0), option: opt) 
    } else { 
     rotateAnimation(theView: rect, speed: speed, fromValue: CGFloat(.pi * 2.0 * Float(timeOffset)/10.0), toValue: CGFloat(.pi * 2.0 * Float(timeOffset)/10.0 + .pi * 2.0)) 
     // note that timeOffset is initialize to be 0. 
    } 
} 

Vous voulez un CAMediaTimingFunction personnalisé ici, commencez par une pente de 0,5 et augmenter progressivement à 1,0, je ne l'ai pas optimiser la courbe de Bézier ici, vous pouvez faire votre propre courbe souhaitée.

Enfin un peu tweak à votre fonction d'animation:

func rotateAnimation(theView: UIView, speed: Float, duration: CFTimeInterval = 10.0, fromValue: CGFloat = CGFloat(0.0), toValue: CGFloat = CGFloat(.pi * 2.0), option: CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)) { 
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation") 
    rotateAnimation.fromValue = fromValue 
    rotateAnimation.toValue = toValue 
    rotateAnimation.duration = duration 
    rotateAnimation.speed = speed 
    rotateAnimation.repeatCount = 1 
    rotateAnimation.delegate = self 
    rotateAnimation.timingFunction = option 
    theView.layer.add(rotateAnimation, forKey: nil) 
}