我有一个编写的应用程序,可以在按下按钮时在屏幕上添加一组交通信号灯。交通灯会在10秒钟后自动从红色变为黄色,然后在两秒钟后变为绿色,然后在10秒钟后恢复为黄色,最后变为红色。我想将其中几个红绿灯添加到屏幕上并使其同时运行,但是当我添加第二个红绿灯时,第一个红绿灯的序列会冻结在其达到的任何状态。关于如何使它继续运行的任何想法-因此有多个光在同一时间循环通过该序列?
转换是由javascript通过状态机控制的。
任何人都对如何使其顺利运行有任何想法?
谢谢!
Rob
英国伦敦
var i = 1;
var TrafficLight = function(i) {
var count = 0;
var light_container = document.getElementById('light-container-' + i);
var currentState = new Red(this, light_container);
this.change = function(state) {
currentState = state;
currentState.go();
}
this.start = function() {
currentState.go();
}
}
var Red = function(light, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('#inner-circle-red').style.backgroundColor = '#d8412c';
console.log(light_container);
setTimeout(function() {
light.change(new Yellow(light, 'red', light_container))
}, 10000);
}
}
var Yellow = function(light, origin, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('#inner-circle-yellow').style.backgroundColor = '#fad201';
setTimeout(function() {
if (origin == 'red') {
light.change(new Green(light, light_container));
light_container.querySelector('#inner-circle-red').style.backgroundColor = '#111111';
light_container.querySelector('#inner-circle-yellow').style.backgroundColor = '#111111';
} else if (origin == 'green') {
light.change(new Red(light, light_container));
light_container.querySelector('#inner-circle-yellow').style.backgroundColor = '#111111';
}
}, 2000);
}
}
var Green = function(light, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('#inner-circle-green').style.backgroundColor = '#33A532';
setTimeout(function() {
light.change(new Yellow(light, 'green', light_container))
light_container.querySelector('#inner-circle-green').style.backgroundColor = '#111111';
}, 10000);
}
};
function run() {
document.getElementById("container").innerHTML += '<div id="light-container-' + i + '"><div class="outer-circle-red"><div id="inner-circle-red"></div></div><div class="outer-circle-yellow"><div id="inner-circle-yellow"></div></div><div class="outer-circle-green"><div id="inner-circle-green"></div></div></div>';
var light = new TrafficLight(i);
light.start();
i++;
}
.outer-circle-red,
.outer-circle-yellow,
.outer-circle-green {
background-color: #696969;
border: 2px solid black;
width: 50px;
height: 40px;
border-radius: 15px;
display: table;
}
#light-container-1,
#light-container-2,
#light-container-3 {
margin-top: 20px;
float: left;
margin-left: 70px;
}
#inner-circle-red,
#inner-circle-yellow,
#inner-circle-green {
width: 20px;
height: 20px;
border-radius: 25px;
border: 2px solid #111111;
margin: 0 auto;
margin-top: 7.5px;
background-color: #111111;
}
#button {
width: 200px;
height: 20px;
padding: 10px;
background-color: blue;
color: #ffffff;
cursor: pointer;
}
<div id="button" onclick="run()">+ Add a new traffic light</div>
<div id="container">
</div>
答案 0 :(得分:1)
我想这是因为您没有使用唯一的#ID。这是您代码中的示例;
light_container.querySelector('#inner-circle-red').style.backgroundColor
如果页面上有多个#inner-circle-red
,您将看到类似的错误。也许尝试对选择器进行更具体的说明-这样;
#light-container-1 .inner-circle-red
#light-container-2 .inner-circle-red
我还添加了几个变量和一个循环来帮助管理多个灯光;
for(let i = 1; i <= lights; i++){
var light = new TrafficLight(i);
light.start();
}
有关所有更改,请参见下面的代码段;
var lights = 0;
var TrafficLight = function(i) {
var count = 0;
var light_container = document.getElementById('light-container-' + i);
var currentState = new Red(this, light_container);
this.change = function(state) {
currentState = state;
currentState.go();
}
this.start = function() {
currentState.go();
}
}
var Red = function(light, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('.inner-circle-red').style.backgroundColor = '#d8412c';
console.log(light_container);
setTimeout(function() {
light.change(new Yellow(light, 'red', light_container))
}, 10000);
}
}
var Yellow = function(light, origin, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#fad201';
setTimeout(function() {
if (origin == 'red') {
light.change(new Green(light, light_container));
light_container.querySelector('.inner-circle-red').style.backgroundColor = '#111111';
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#111111';
} else if (origin == 'green') {
light.change(new Red(light, light_container));
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#111111';
}
}, 2000);
}
}
var Green = function(light, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('.inner-circle-green').style.backgroundColor = '#33A532';
setTimeout(function() {
light.change(new Yellow(light, 'green', light_container))
light_container.querySelector('.inner-circle-green').style.backgroundColor = '#111111';
}, 10000);
}
};
function run() {
lights++;
document.getElementById("container").innerHTML += '<div id="light-container-' + lights + '"><div class="outer-circle-red"><div class="inner-circle-red"></div></div><div class="outer-circle-yellow"><div class="inner-circle-yellow"></div></div><div class="outer-circle-green"><div class="inner-circle-green"></div></div></div>';
for(let i = 1; i <= lights; i++){
var light = new TrafficLight(i);
light.start();
}
}
.outer-circle-red,
.outer-circle-yellow,
.outer-circle-green {
background-color: #696969;
border: 2px solid black;
width: 50px;
height: 40px;
border-radius: 15px;
display: table;
}
#light-container-1,
#light-container-2,
#light-container-3 {
margin-top: 20px;
float: left;
margin-left: 70px;
}
.inner-circle-red,
.inner-circle-yellow,
.inner-circle-green {
width: 20px;
height: 20px;
border-radius: 25px;
border: 2px solid #111111;
margin: 0 auto;
margin-top: 7.5px;
background-color: #111111;
}
#button {
width: 200px;
height: 20px;
padding: 10px;
background-color: blue;
color: #ffffff;
cursor: pointer;
}
<div id="button" onclick="run()">+ Add a new traffic light</div>
<div id="container">
</div>
答案 1 :(得分:1)
一个问题是,正如刘易斯已经说过的,您有多个具有相同id
的元素。 JavaScript只能处理其中之一。
另一个问题是您使用#container
删除了innerHTML
的内容。然后,您存储在TrafficLight
,Red
,Yellow
和Green
类中的引用将被销毁。该商店可以正常运行,但是看不到它。改用DOM操作。
var light_container = document.createElement('div');
light_container.id = "light-container-" + i;
light_container.innerHTML = '<div class="outer-circle-red"><div class="inner-circle-red"></div></div><div class="outer-circle-yellow"><div class="inner-circle-yellow"></div></div><div class="outer-circle-green"><div class="inner-circle-green"></div></div>';
document.getElementById("container").appendChild(light_container);
var i = 1;
var TrafficLight = function(i) {
var count = 0;
var light_container = document.getElementById('light-container-' + i);
var currentState = new Red(this, light_container);
this.change = function(state) {
currentState = state;
currentState.go();
}
this.start = function() {
currentState.go();
}
}
var Red = function(light, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('.inner-circle-red').style.backgroundColor = '#d8412c';
setTimeout(function() {
light.change(new Yellow(light, 'red', light_container))
}, 10000);
}
}
var Yellow = function(light, origin, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#fad201';
setTimeout(function() {
if (origin == 'red') {
light.change(new Green(light, light_container));
light_container.querySelector('.inner-circle-red').style.backgroundColor = '#111111';
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#111111';
} else if (origin == 'green') {
light.change(new Red(light, light_container));
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#111111';
}
}, 2000);
}
}
var Green = function(light, light_container) {
this.light = light;
this.go = function() {
light_container.querySelector('.inner-circle-green').style.backgroundColor = '#33A532';
setTimeout(function() {
light.change(new Yellow(light, 'green', light_container))
light_container.querySelector('.inner-circle-green').style.backgroundColor = '#111111';
}, 10000);
}
};
function run() {
var light_container = document.createElement('div');
light_container.id = "light-container-" + i;
light_container.innerHTML = '<div class="outer-circle-red"><div class="inner-circle-red"></div></div><div class="outer-circle-yellow"><div class="inner-circle-yellow"></div></div><div class="outer-circle-green"><div class="inner-circle-green"></div></div>';
document.getElementById("container").appendChild(light_container);
var light = new TrafficLight(i);
light.start();
i++;
}
.outer-circle-red,
.outer-circle-yellow,
.outer-circle-green {
background-color: #696969;
border: 2px solid black;
width: 50px;
height: 40px;
border-radius: 15px;
display: table;
}
[id^=light-container] {
margin-top: 20px;
float: left;
margin-left: 70px;
}
.inner-circle-red,
.inner-circle-yellow,
.inner-circle-green {
width: 20px;
height: 20px;
border-radius: 25px;
border: 2px solid #111111;
margin: 0 auto;
margin-top: 7.5px;
background-color: #111111;
}
#button {
width: 200px;
height: 20px;
padding: 10px;
background-color: blue;
color: #ffffff;
cursor: pointer;
}
<div id="button" onclick="run()">+ Add a new traffic light</div>
<div id="container">
</div>
答案 2 :(得分:-1)
感谢您的回答。作为一项附加功能,我添加了一个控件,该控件使用户可以分别启动每个交通信号灯。我试图弄清楚如何使用户能够永久停止每个交通信号灯,而不停止其他所有信号灯。
到目前为止,这是我更新的代码-请注意在var Red内部添加了'this.stop()'函数。我希望代码在此停止旋转,而不是继续变为黄色和绿色。
谢谢
Rob
<!DOCTYPE html>
<html>
<head>
<title>Traffic Lights</title>
<style type="text/css">
#button {
width: 200px;
height: 20px;
padding: 10px;
background-color: blue;
color: #ffffff;
cursor: pointer;
}
.button {
width: 15px;
height: 20px;
padding: 10px;
background-color: red;
color: #ffffff;
cursor: pointer;
margin: 20px auto;
text-align: center;
text-transform: uppercase;
font-weight: bold;
}
.outer-circle-red, .outer-circle-yellow, .outer-circle-green {
background-color: #696969;
margin: 0 auto;
border: 2px solid black;
width: 50px;
height: 40px;
border-radius: 15px;
display: table;
}
.light-container {
margin: 20px 30px 0 30px;
margin-top: 20px;
float: left;
}
.inner-circle-red, .inner-circle-yellow, .inner-circle-green {
width: 20px;
height: 20px;
border-radius: 25px;
border: 2px solid #111111;
margin: 0 auto;
margin-top: 7.5px;
background-color: #111111;
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
margin-top: 20px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
</style>
</head>
<body>
<div id="button" onclick="initiate()">+ Add a new traffic light</div>
<div id="container">
</div>
<script type="text/javascript">
var i = 1;
var TrafficLight = function (i) {
var count = 0;
var light_container = document.getElementById('light-container-' + i);
var currentState = new Red(this, light_container);
this.change = function (state) {
currentState = state;
currentState.go();
}
this.start = function () {
currentState.go();
}
this.stop = function () {
currentState.stop();
}
}
var Red = function (light, light_container) {
this.light = light;
this.go = function () {
light_container.querySelector('.inner-circle-red').style.backgroundColor = '#d8412c';
console.log(light_container);
setTimeout(function(){
light.change(new Yellow(light, 'red', light_container))
}, 12000);
}
this.stop = function () {
light_container.querySelector('.inner-circle-red').style.backgroundColor = '#111111';
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#111111';
light_container.querySelector('.inner-circle-green').style.backgroundColor = '#111111';
// Switch all the lights off.
return;
}
}
var Yellow = function (light, origin, light_container) {
this.light = light;
this.go = function () {
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#fad201';
setTimeout(function(){
if(origin == 'red'){
light.change(new Green(light, light_container));
light_container.querySelector('.inner-circle-red').style.backgroundColor = '#111111';
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#111111';
} else if(origin == 'green'){
light.change(new Red(light, light_container));
light_container.querySelector('.inner-circle-yellow').style.backgroundColor = '#111111';
}
}, 2000);
}
}
var Green = function (light, light_container) {
this.light = light;
console.log('here');
this.go = function () {
light_container.querySelector('.inner-circle-green').style.backgroundColor = '#33A532';
setTimeout(function(){
light.change(new Yellow(light, 'green', light_container))
light_container.querySelector('.inner-circle-green').style.backgroundColor = '#111111';
}, 14000);
}
};
function initiate(){
var light_container = document.createElement('div');
light_container.id = "light-container-" + i;
light_container.className = "light-container";
light_container.innerHTML = '<div class="outer-circle-red"><div class="inner-circle-red"></div></div><div class="outer-circle-yellow"><div class="inner-circle-yellow"></div></div><div class="outer-circle-green"><div class="inner-circle-green"></div></div><label class="switch"><input type="checkbox" class="off" onclick="toggleRun(this, ' + i + ');"><span class="slider round"></span></label>';
document.getElementById("container").appendChild(light_container);
i++;
}
function toggleRun(item, i){
if(item.className == "off"){
item.className="on";
run(i);
} else {
item.className="off";
stop(i);
}
}
function run(i){
var light = new TrafficLight(i);
light.start();
}
function stop(i){
var light = new TrafficLight(i);
light.stop();
}
function exit( status ){
var i;
if (typeof status === 'string') {
alert(status);
}
window.addEventListener('error', function (e) {e.preventDefault();e.stopPropagation();}, false);
var handlers = [
'copy', 'cut', 'paste',
'beforeunload', 'blur', 'change', 'click', 'contextmenu', 'dblclick', 'focus', 'keydown', 'keypress', 'keyup', 'mousedown', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'resize', 'scroll',
'DOMNodeInserted', 'DOMNodeRemoved', 'DOMNodeRemovedFromDocument', 'DOMNodeInsertedIntoDocument', 'DOMAttrModified', 'DOMCharacterDataModified', 'DOMElementNameChanged', 'DOMAttributeNameChanged', 'DOMActivate', 'DOMFocusIn', 'DOMFocusOut', 'online', 'offline', 'textInput',
'abort', 'close', 'dragdrop', 'load', 'paint', 'reset', 'select', 'submit', 'unload'
];
function stopPropagation (e) {
e.stopPropagation();
// e.preventDefault(); // Stop for the form controls, etc., too?
}
for (i=0; i < handlers.length; i++) {
window.addEventListener(handlers[i], function (e) {stopPropagation(e);}, true);
}
if (window.stop) {
window.stop();
}
throw '';
}
</script>
</body>
</html>```