Javascript 试图让两个交通灯按顺序工作

Javascript 试图让两个交通灯按顺序工作,javascript,html,state-machine,Javascript,Html,State Machine,我有一个应用程序,我已经写了,增加了一组交通灯在屏幕上按下一个按钮。交通灯在10秒后自动循环从红色变为黄色,然后在2秒后变为绿色,然后在10秒后变回黄色,最后变回红色。我想在屏幕上添加几个交通灯,并让它们同时运行,但当我添加第二个交通灯时,第一个交通灯的序列将冻结在其达到的任何状态。关于如何让它继续运行,从而在同一时间有多个光循环通过序列,有什么想法吗 转换由javascript通过状态机控制 有人对如何使这项工作顺利进行有什么想法吗 谢谢 抢劫 英国伦敦 var i=1; var交通灯=功能

我有一个应用程序,我已经写了,增加了一组交通灯在屏幕上按下一个按钮。交通灯在10秒后自动循环从红色变为黄色,然后在2秒后变为绿色,然后在10秒后变回黄色,最后变回红色。我想在屏幕上添加几个交通灯,并让它们同时运行,但当我添加第二个交通灯时,第一个交通灯的序列将冻结在其达到的任何状态。关于如何让它继续运行,从而在同一时间有多个光循环通过序列,有什么想法吗

转换由javascript通过状态机控制

有人对如何使这项工作顺利进行有什么想法吗

谢谢

抢劫

英国伦敦

var i=1;
var交通灯=功能(i){
var计数=0;
var light_container=document.getElementById('light-container-'+i);
var currentState=新红色(此灯为容器);
this.change=函数(状态){
当前状态=状态;
currentState.go();
}
this.start=函数(){
currentState.go();
}
}
var Red=功能(灯、灯和容器){
这个。光=光;
this.go=函数(){
light#container.querySelector(“#内圈红色”).style.backgroundColor=“#d8412c”;
控制台日志(轻型容器);
setTimeout(函数(){
灯。更换(新黄色(灯“红色”、灯(集装箱))
}, 10000);
}
}
变量黄=功能(灯光、原点、灯光容器){
这个。光=光;
this.go=函数(){
light#container.querySelector(“#内圈黄色”).style.backgroundColor=“#fad201”;
setTimeout(函数(){
如果(原点==“红色”){
灯。改变(新的绿色(灯,灯)容器);
light#container.querySelector(“#内圈红色”).style.backgroundColor=“#111111”;
light#container.querySelector(“#内圈黄色”).style.backgroundColor=“#111111”;
}else if(原点==“绿色”){
灯。改变(新的红色(灯,灯)容器);
light#container.querySelector(“#内圈黄色”).style.backgroundColor=“#111111”;
}
}, 2000);
}
}
绿色变量=功能(灯、灯和容器){
这个。光=光;
this.go=函数(){
light#container.querySelector(“#内圈绿色”).style.backgroundColor=“#33A532”;
setTimeout(函数(){
灯。更换(新黄色(灯、‘绿色’、灯和容器))
light#container.querySelector(“#内圆绿色”).style.backgroundColor=“#111111”;
}, 10000);
}
};
函数运行(){
document.getElementById(“容器”).innerHTML+='';
var灯=新交通灯(i);
light.start();
i++;
}
。外圆红色,
.外圆黄色,
.外圆绿色{
背景色:#6969;
边框:2件纯黑;
宽度:50px;
高度:40px;
边界半径:15px;
显示:表格;
}
#轻容器-1,
#轻容器-2,
#轻型集装箱-3{
边缘顶部:20px;
浮动:左;
左边距:70像素;
}
#内圆红色,
#内圈黄色,
#内圆绿色{
宽度:20px;
高度:20px;
边界半径:25px;
边框:2px实心#111111;
保证金:0自动;
利润上限:7.5px;
背景色:#111111;
}
#钮扣{
宽度:200px;
高度:20px;
填充:10px;
背景颜色:蓝色;
颜色:#ffffff;
光标:指针;
}
+添加新的交通灯

我想这是因为您没有使用唯一的ID。下面是代码中的一个示例

light\u container.querySelector(“#内圈红色”).style.backgroundColor

如果页面上有多个
#内圆红色
,您将看到如下错误。也许你可以试着对你的选择器更具体一些——像这样

#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();
   }
+添加新的交通灯

一个问题是,正如Lewis已经指出的,您有多个元素具有相同的
id
。JavaScript只能处理其中之一

另一个问题是使用
innerHTML
删除
#container
的内容。存储在
交通灯
红色
黄色
绿色
类中的引用随后被销毁。这家商店运转正常,但看不出来是这样的。改用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 Red中添加了'this.stop()'函数。我希望代码停止那里的旋转,而不是继续黄色和绿色

谢谢

抢劫


交通灯
#钮扣{
宽度:200px;
高度:20px;
填充:10px;
背景颜色:蓝色;
颜色:#ffffff;
光标:指针;
}
.按钮{
宽度:15px;
高度:20px;
填充:10px;
背景色:红色;
颜色:#ffffff;
光标:指针;
保证金:20px自动;
文本对齐:居中;
文本转换:大写;
字体大小:粗体;
}
.外圈红色、.外圈黄色、.外圈绿色{
背景色:#6969;
保证金:0自动;
边框:2件纯黑;
宽度:50px;
高度:40px;
边界半径:15px;
显示:表格;
}
.轻型集装箱{
利润率:20px 30px 0 30px;
利润上限:20px
<!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>```