我正在尝试制作一个简单的西蒙游戏'。我目前无法尝试添加课程' on'到一个div一秒钟,然后删除该类相同的时间。
所以我有四个div,我根据一系列数字打开和关闭,例如[0, 1, 2, 3]
。这会使div[0]
闪烁一秒钟然后关闭一秒钟然后移至div[1]
,开启和关闭等等。
这是我的功能
/**
* 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);
},
这个问题是我正在使用两个setTimeout函数,虽然它有效,但我想知道是否有更好的方法。如果你看我在模型对象中使用count变量来跟踪迭代。
到目前为止,这是我的完整javascript应用程序......
$(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();
});
是否有更简洁的方法来添加类,然后删除一个类?
答案 0 :(得分:1)
TLDR;)
您需要做的就是使用setInterval()
或setTimeout()
并在回调函数中使用 element.classList.toggle()
来添加或删除元素中的类。
如果您希望停止闪烁,请使用clearTimeout()
或clearInterval()
。
以下是一个例子:
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);
&#13;
#test {
width:100px;
height:100px;
background-color:blue; /* <-- blue will be the default color */
}
#test.lightUp {
background-color:yellow;
}
&#13;
<div id="test"></div>
<button>Stop Blinking</button>
&#13;
答案 1 :(得分:1)
我认为您可以将按钮列表转换为一系列命令。然后,您可以使用单个setInterval
来播放命令,直到命令用完为止。 setInterval
可以使用1秒间隔,如果您想要打开和关闭同样长,但您也可以将其设置为更快一点,以便轻松地允许不同的持续时间。
以下示例并非基于您的代码,只是为了说明这个想法。它按下一组按钮开始(在代码的按钮处)。这些传递给getSequence
。这将返回一组命令,在这种情况下只是要打开的按钮的颜色,因此序列可以是红色,红色,红色,红色,&#39;&#39;&#39;&#39;&#39;&#39 ;,&#39;&#39;&#39;&#39;为4&#39;间隔点亮红灯,然后关闭4&#39;间隔&#39;。通过这种方式,您可以创建复杂的序列,只需稍作调整,您甚至可以同时点亮多个按钮。
示例中的间隔设置为1/10秒。每种颜色播放10个步骤(= 1秒),每个暂停播放5个步骤(= .5秒)。在控制台中,您可以看到要播放的按钮/颜色的基础数组,然后是更精细的序列。
// 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);
&#13;
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;
}
&#13;
<div id="red" class="button"></div>
<div id="green" class="button"></div>
<div id="yellow" class="button"></div>
<div id="blue" class="button"></div>
&#13;
答案 2 :(得分:1)
使用setInterval而不是setTimeout我创建了四个divison并使每个分区闪烁1秒。
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);
&#13;
.myClass {
background-color:yellow;
}
&#13;
<div class="post-text">A</div>
<div class="post-text">B</div>
<div class="post-text">C</div>
<div class="post-text">D</div>
&#13;