2017-04-19 4 views
0

Je ViewController avec Rating d'étoiles qui ressemble à ceci (sauf qu'il ya 10 étoiles)animation fluide avec minuterie et boucle dans iOS app

enter image description here

Lorsque l'utilisateur ouvre ViewController pour un objet qui ont pas d'étoiles Je veux attirer l'attention de l'utilisateur sur ces étoiles de façon très simple: animer la mise en évidence des étoiles (on pourrait voir un tel comportement sur certaines publicités dans le monde réel lorsque chaque lettre est mise en évidence les unes après les autres).

  1. Une étoile a souligné
  2. Deux étoiles ont mis en évidence
  3. Trois étoiles ont mis en évidence
  4. ......
  5. Désactiver tous

C'est donc la manière dont Je le fais

func delayWithSeconds(_ seconds: Double, completion: @escaping() ->()) { 
    DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { 
     completion() 
    } 
} 

func ratingStarsAnimation() { 
    for i in 1...11 { 
     var timer : Double = 0.6 + Double(i)*0.12 
     delayWithSeconds(timer) { 
      ratingStars.rating = (i < 10) ? Double(i) : 0 
     } 
    } 
} 

Que se passe-t-il ici? J'ai une fonction appelée delayWithSeconds qui retarde l'action et j'utilise cette fonction pour retarder chaque surbrillance d'étoile. Et 0.6 est le délai initial avant le début de l'animation. Une fois toutes les étoiles mises en évidence, la dernière étape consiste à désactiver la mise en évidence de toutes les étoiles. Ce code fonctionne mais je ne peux pas dire qu'il est lisse.

Mes questions sont les suivantes:

  1. Comment puis-je changer + 0,6 Double (i) * 0,12 pour obtenir une animation fluide sentir?
  2. Je pense que ma solution avec des retards n'est pas bonne - comment puis-je résoudre les étoiles lisses en mettant mieux en évidence la tâche?
+0

Pouvez-vous montrer que l'animation que vous avez accompli jusqu'à présent et celui que vous voulez. –

+0

Comment puis-je le montrer? – moonvader

+0

Partager la vidéo par dropBox. –

Répondre

1

Jetez un coup d'oeil à la classe CADisplaylink. C'est une minuterie spécialisée qui est liée au taux de rafraîchissement de l'écran, sur iOS c'est 60fps. C'est l'épine dorsale de nombreuses bibliothèques d'animation tierces.

Exemple d'utilisation:

var displayLink: CADisplayLink? 
let start: Double = 0 
let end: Double = 10 
let duration: CFTimeInterval = 5 // seconds 
var startTime: CFTimeInterval = 0 

let ratingStars = RatingView() 

func create() { 
    displayLink = CADisplayLink(target: self, selector: #selector(tick)) 
    displayLink?.add(to: .main, forMode: .defaultRunLoopMode) 
} 

func tick() { 
    guard let link = displayLink else { 
     cleanup() 
     return 
    } 

    if startTime == 0 { // first tick 
     startTime = link.timestamp 
     return 
    } 

    let maxTime = startTime + duration 
    let currentTime = link.timestamp 

    guard currentTime < maxTime else { 
     finish() 
     return 
    } 

    // Add math here to ease the animation 

    let progress = (currentTime - startTime)/duration 
    let progressInterval = (end - start) * Double(progress) 

    // get value =~ 0...10 
    let normalizedProgress = start + progressInterval 


    ratingStars.rating = normalizedProgress 
} 

func finish() { 
    ratingStars.rating = 0 
    cleanup() 
} 

func cleanup() { 
    displayLink?.remove(from: .main, forMode: .defaultRunLoopMode) 
    displayLink = nil 
    startTime = 0 
} 

En début cela permettra à l'animation d'être plus lisse. Vous aurez encore besoin d'ajouter de la trigonométrie si vous voulez ajouter de l'accélération mais cela ne devrait pas être trop difficile.