这是一个替代实现,每个灯的时间相等。
var red = document.getElementById('circleRed');
var orange = document.getElementById('circleOrange');
var green = document.getElementById('circleGreens');
/* Set an array with the desired order to turn on lights */
var lights = [red, green, orange];
function open(light) {
light.classList.add('opened');
}
function close(light) {
light.classList.remove('opened');
}
function change() {
close(lights[i]);
i = (i + 1) % lights.length;
open(lights[i]);
}
/* Start */
var i = 0;
open(lights[i]);
setInterval(change, 1000);
.circle {
width: 50px;
height: 50px;
border-radius: 25px;
margin: 5px;
opacity: 0.2;
transition: opacity 200ms;
}
.circle.opened {
opacity: 1;
}
#circleRed {
background-color: red;
}
#circleOrange {
background-color: orange;
}
#circleGreens {
background-color: green;
}
.back {
width: 60px;
padding: 5px;
background-color: black;
}
<div class="back">
<div id="circleRed" class="circle"></div>
<div id="circleOrange" class="circle"></div>
<div id="circleGreens" class="circle"></div>
</div>
说明:
不是将每个圆圈的背景颜色从黑色更改为自己的颜色以点亮圆圈,反之亦然以关闭,在我的示例中,所有圆圈都将其各自的颜色(红色、绿色或橙色)淡化为(几乎)使用opacity: 0.2 透明(最初我使用0,但我认为使用0.2 看起来更好)参见:opacity。
所以,所有具有.circle 类的元素都有:
.circle {
/* Other properties */
opacity: 0.2;
}
然后,我使用一个名为 opened 的类将不透明度设置为 1,使圆圈可见。
.circle.opened {
opacity: 1;
}
由于.circle.opened 具有比.circle 更高的specificity,因此不透明度:1 优先于具有两个类(circle 和opened)的元素。
要从灯项中添加或删除类opened,我使用两个简单的函数open 和close 来操作元素的classList。 这很重要。一般来说,更推荐在类中定义元素的属性(样式),并使用JS添加或删除该类来改变元素,直接用JS修改元素的样式。
所以,它更干净,更推荐这样做:
/* CSS */
.red { background-color: red }
/* Javascript */
var element = document.getElementById('#element_ID');
element.classList.add('red');
比:
/* Javascript */
var element = document.getElementById('#element_ID');
element.style.backgroundColor = 'red';
即使第二种方式看起来更容易。
为了改变灯光,我按所需顺序制作了一个包含元素的数组:
var lights = [red, green, orange];
如您所见,灯光Array 的每个元素都是圆圈之一,我们已经使用document.getElementById() 存储在变量中(如果您不熟悉数组,请花一些时间阅读并理解它们它们是什么以及它们是如何工作的。它们是任何编程语言中最基本的数据结构之一,因此掌握它们很重要。)
首先,我向0 (var i = 0) 启动一个全局变量,然后点亮第一盏灯:
open(lights[i]);
由于i 等于0,lights[i],所以lights[0] 是red(在JS 中,与大多数语言一样,数组从0 开始计数元素)。这样open(lights[i])就等于open(red)。
然后我执行setInterval(change, 1000),所以每秒都会调用函数change()。而这个change 函数有什么作用?
基本上:
// Turn off the current light
close(lights[i]);
// Increment i, so that lights[i] points to the next element...
i = (i + 1) % lights.length;
// Turn on this next element
open(lights[i]);
这里最稀有的可能是增量。为什么我要i = (i + 1) % lights.length 而不是i++。
如果我在连续调用change 后执行i++,i 将是:0、1、2、3、4、5、6... 所以,当我尝试访问 lights[i] 时,我'会报错,因为lights数组的第3、4、5...位置没有元素。
我需要我的序列是:0, 1, 2, 0, 1, 2, 0, 1, 2...
如何获得这个想要的序列而不是 0、1、2、3、4、5、6...?
也许更容易理解的方式是:
i++;
if (i > 2) {
i = 0;
}
但我使用Remainder 运算符(%)来达到相同的效果。
我希望这会有所帮助!
还有一个可以轻松配置每个灯的持续时间:
var lights = {
red: {
node: document.getElementById('circleRed'),
duration: 4000,
},
green: {
node: document.getElementById('circleGreens'),
duration: 2000,
},
orange: {
node: document.getElementById('circleOrange'),
duration: 800,
}
};
var order = ['red', 'green', 'orange'];
function open(light) {
light.node.classList.add('opened');
}
function close(light) {
light.node.classList.remove('opened');
}
function change() {
close(lights[order[i]]);
i = (i + 1) % order.length;
open(lights[order[i]]);
setTimeout(change, lights[order[i]].duration);
}
/* Start */
var i = 0;
open(lights[order[i]]);
setTimeout(change, lights[order[i]].duration);
.circle {
width: 50px;
height: 50px;
border-radius: 25px;
margin: 5px;
opacity: 0;
transition: opacity 200ms;
}
.circle.opened {
opacity: 1;
}
#circleRed {
background-color: red;
}
#circleOrange {
background-color: orange;
}
#circleGreens {
background-color: green;
}
.back {
width: 60px;
padding: 5px;
background-color: black;
}
<div class="back">
<div id="circleRed" class="circle"></div>
<div id="circleOrange" class="circle"></div>
<div id="circleGreens" class="circle"></div>
</div>