Попытка заставить два светофора работать в последовательности - PullRequest
0 голосов
/ 13 июня 2019

У меня есть приложение, которое я написал, который добавляет светофор на экране после нажатия кнопки. Через 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>

Ответы [ 3 ]

1 голос
/ 13 июня 2019

Одна проблема, поскольку Льюис уже заявил, что у вас есть несколько элементов с одинаковым 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>
1 голос
/ 13 июня 2019

Я думаю, это потому, что вы не используете уникальные #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>
0 голосов
/ 14 июня 2019

Спасибо за ваш ответ. В качестве дополнительной функции я добавил элемент управления, который позволяет пользователю запускать каждый светофор отдельно. Я пытаюсь выяснить, как разрешить пользователю постоянно останавливать каждый светофор без остановки всех остальных.

Вот мой обновленный код - обратите внимание на добавление функции this.stop () внутри var Red. Я бы хотел, чтобы код остановил вращение, а не продолжал желтеть и зеленеть.

Спасибо

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>```


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...