2017-09-12 1 views
1

Je suis en train de faire un simple «Simon Game». Je suis actuellement bloqué en essayant d'ajouter une classe "on" à un div pendant une seconde, puis supprimer cette classe pour le même laps de temps. J'ai donc quatre divs que je suis en train de clignoter en fonction d'une séquence de nombres, par ex. [0, 1, 2, 3]. Cela clignotera div[0] pendant une seconde et s'éteindra pendant une seconde, puis passera à div[1], on et off et ainsi de suite.setInterval() pour ajouter une classe, puis supprimer la classe pour le même laps de temps

Voici ma fonction

/** 
* sequence => array [0, 1, 2, 3] 
* speed => int 1000 (one second) 
*/ 
playSequence: function(sequence, speed){ 
    var self = this; 

    // removes class 'on' 
    view.turnOffPads(); 
    setTimeout(function(){ 
     // adds the 'on' class to a specific div 
     view.lightUpPad(model.startupSequence[model.count]); 
    }, speed/2); 

    setTimeout(function(){ 
     model.count++; // keeps track of the iterations 
     if (model.count < sequence.length) { // if we are still iterating 
      self.playSequence(sequence, speed); // light up the next div 
     } else { 
      model.count = 0; // set back to zero 
     } 
    }, speed); 
}, 

Le problème est que j'utilise deux fonctions setTimeout uns avec les autres et bien qu'il fonctionne, je me demande s'il y a une meilleure façon. Si vous regardez, j'utilise une variable count dans mon objet modèle pour suivre les itérations.

Voici mon application complète javascript jusqu'à présent ...

$(function(){ 

    var model = { 
     on: false, 
     strictMode: false, 
     startupSequence: [0, 1, 2, 3, 3, 3, 2, 1, 0, 3, 2, 1, 0, 2, 1, 3], 
     score: 0, 
     sequence: [], 
     count: 0, 
    } 

    var controller = { 
     init: function(){ 
      view.cacheDOM(); 
      view.bindEvents(); 
     }, 
     getSequence: function(){ 
      // get a random number from one to 4 
      var random = Math.floor(Math.random() * 4); 
      // push it to the sequence array 
      model.sequence.push(random); 
      console.log(model.sequence); 
      // play it 
      this.playSequence(model.sequence); 
     }, 

     /** 
     * sequence => array [0, 1, 2, 3] 
     * speed => int 1000 (one second) 
     */ 
     playSequence: function(sequence, speed){ 
      console.log(sequence.length); 
      var self = this; 

      view.turnOffPads(); 
      setTimeout(function(){ 
       view.lightUpPad(model.startupSequence[model.count]); 
      }, speed/2); 

      setTimeout(function(){ 
       model.count++; 
       if (model.count < sequence.length) { 
        self.playSequence(sequence, speed); 
       } else { 
        model.count = 0; 
       } 
      }, speed); 
      // view.turnOffPads(); 
     }, 
    } 

    var view = { 
     cacheDOM: function(){ 
      this.$round = $('#round'); 
      this.$start = $('#start'); 
      this.$strict = $('#strict'); 
      this.$pad = $('.pad'); 

      this.$padArray = document.getElementsByClassName('pad'); 
     }, 
     bindEvents: function(){ 
      this.$start .change(this.start.bind(this)); 
      this.$strict.change(this.setStrictMode.bind(this)); 
     }, 
     start: function(){ 
      // turn on pads 
      if (model.on) { 
       this.$pad.removeClass('on'); 
       this.$round.text('--'); 
       model.on = false; 
       // reset everything 
      } else { 
       this.$round.text(model.score); 
       model.on = true; 
       controller.playSequence(model.startupSequence, 100) 
       // controller.getSequence(); 
      } 
     }, 
     lightUpPad: function(i){ 
      $(this.$padArray[i]).addClass('on'); 
     }, 
     turnOffPads: function(){ 
      this.$pad.removeClass('on'); 
     }, 
     setStrictMode: function(){ 
      if (model.strictMode) { 
       model.strictMode = false; 
      } else { 
       model.strictMode = true; 
      } 
     } 
    } 

    controller.init(); 
}); 

Y at-il un moyen plus propre d'ajouter une classe, puis supprimer une classe?

Répondre

1

Je pense que vous pouvez transformer une liste des boutons dans une séquence de commandes. Ensuite, vous pouvez utiliser un seul setInterval pour lire les commandes jusqu'à ce qu'il soit à court de commandes. Le setInterval peut utiliser des intervalles de 1 seconde si vous souhaitez que l'activation et la désactivation soient aussi longues, mais vous pouvez également définir un délai un peu plus court pour permettre des durées différentes.

L'exemple ci-dessous n'est pas vraiment basé sur votre code, mais simplement pour illustrer l'idée. Il commence (au bouton du code) avec un tableau de boutons pressés. Ceux-ci sont passés à getSequence. Cela retournera un tableau de commandes, dans ce cas simplement la couleur du bouton à allumer, donc une séquence pourrait être rouge, rouge, rouge, rouge, '', '', '', '' pour 4 'intervalles', puis éteignez-le pour 4 'intervalles'. De cette façon, vous pouvez créer des séquences compliquées, et avec des ajustements mineurs, vous pouvez même allumer plusieurs boutons simultanément.

L'intervalle de l'exemple est défini sur 1/10 de seconde. Chaque couleur joue pendant 10 étapes (= 1 seconde), et chaque pause joue pendant 5 étapes (= 0,5 seconde). Dans la console, vous voyez le tableau de base des boutons/couleurs à jouer, suivi de la séquence plus élaborée qui est jouée.

// The play function plays a sequence of commands 
 
function play(sequence) { 
 
    var index = 0; 
 
    var lastid = ''; 
 
    var timer = setInterval(function(){ 
 
    // End the timer when at the end of the array 
 
    if (++index >= sequence.length) { 
 
     clearInterval(timer); 
 
     return; 
 
    } 
 
    var newid = sequence[index]; 
 
     
 
    if (lastid != newid) { 
 
     // Something has changed. Check and act. 
 
    
 
     if (lastid != '') { 
 
     // The last id was set, so lets switch that off first. 
 
     document.getElementById(lastid).classList.remove('on'); 
 
     console.log('--- ' + lastid + ' off'); 
 
     } 
 
     
 
     if (newid != '') { 
 
     // New id is set, switch it on 
 
     document.getElementById(newid).classList.add('on'); 
 
     console.log('+++ ' + newid + ' on'); 
 
     } 
 
     lastid = newid; 
 
    } 
 
    }, 100); 
 
} 
 

 
// generateSequence takes a list of buttons and converts them to a 
 
// sequence of color/off commands. 
 
function generateSequence(buttons) { 
 
    var result = []; 
 
    for (var b = 0; b < buttons.length; b++) { 
 
    // 'On' for 10 counts 
 
    for (var i = 0; i < 10; i++) { 
 
     result.push(buttons[b]); 
 
    } 
 
    if (b+1 < buttons.length) { 
 
     // 'Off' for 5 counts 
 
     for (var i = 0; i < 5; i++) { 
 
     result.push(''); 
 
     } 
 
    } 
 
    } 
 
    // One 'off' at the end 
 
    result.push(''); 
 
    
 
    return result; 
 
} 
 

 
var buttons = ['red', 'green', 'red', 'yellow', 'yellow', 'blue']; 
 
console.log(buttons); 
 
var sequence = generateSequence(buttons); 
 
console.log(sequence); 
 
play(sequence);
div.button { 
 
    width: 100px; 
 
    height: 100px; 
 
    opacity: .5; 
 
    display: inline-block; 
 
} 
 
div.button.on { 
 
    opacity: 1; 
 
} 
 
#red { 
 
    background-color: red; 
 
} 
 
#green { 
 
    background-color: green; 
 
} 
 
#yellow { 
 
    background-color: yellow; 
 
} 
 
#blue { 
 
    background-color: blue; 
 
}
<div id="red" class="button"></div> 
 
<div id="green" class="button"></div> 
 
<div id="yellow" class="button"></div> 
 
<div id="blue" class="button"></div>

1

TLDR;)

Tout ce que vous devez faire est d'utiliser setInterval() ou setTimeout() et dans l'utilisation de la fonction de rappel element.classList.toggle() pour ajouter ou supprimer une classe de l'élément. Si vous voulez que le clignotement s'arrête, utilisez clearTimeout() ou clearInterval().

Voici un exemple:

var d = document.getElementById("test"); 
 
var b = document.querySelector("button"); 
 

 
b.addEventListener("click", function(){ 
 
    // Cancel the timer 
 
    clearTimeout(timer); 
 
}); 
 

 
// Assign the timer's ID to a variable so that 
 
// you can stop it later 
 
var timer = setInterval(function(){ 
 
    // Toggle the use of the lightUp class 
 
    test.classList.toggle("lightUp"); 
 
},1000);
#test { 
 
    width:100px; 
 
    height:100px; 
 
    background-color:blue; /* <-- blue will be the default color */ 
 
} 
 

 
#test.lightUp { 
 
    background-color:yellow; 
 
}
<div id="test"></div> 
 
<button>Stop Blinking</button>

1

Utilisation setInterval au lieu de setTimeout j'ai créé quatre divison et clignote chaque division pendant 1 sec.

var i = 0, 
 
    j = 4; 
 

 
function blink(i) { 
 
    new Promise(function(resolve, reject) { 
 
    x = setTimeout(function() { 
 
    document.querySelectorAll(".post-text")[i].classList.add("myClass"); 
 
    resolve("added"); 
 
    }, 1000) 
 
    }).then(function(a) { 
 
    new Promise(function(res, rej) { 
 
    setTimeout(function() { 
 
     clearInterval(x); 
 
     document.querySelectorAll(".post-text")[i].classList.remove("myClass"); 
 
     res("deleted"); 
 
    }, 1000) 
 
    }).then(function(a) { 
 
    i++; 
 
    if (i < j) { 
 
     blink(i); 
 
    } else { 
 
     i = 0; 
 
     blink(i); 
 
    } 
 
    }); 
 

 
    }); 
 
} 
 
blink(i);
.myClass { 
 
    background-color:yellow; 
 
}
<div class="post-text">A</div> 
 
<div class="post-text">B</div> 
 
<div class="post-text">C</div> 
 
<div class="post-text">D</div>