How to automate a JavaScript/html traffic light sequence using setinterval?

前端 未结 2 377
北海茫月
北海茫月 2021-01-07 15:30

I am new to JavaScript and i am tying to automate this traffic light sequence. I have used if and if else statements to preform the task but I am unable to automate it so it

相关标签:
2条回答
  • 2021-01-07 16:08

    I don't usually write ready-to-go code, but there are so many things wrong with yours that I was... compelled to.

    Functions: use 'em! Don't copy-paste the same code over and over, that's a sign you're doing it wrong!

    setInterval takes a reference to a function. I don't know what your "previous attempts" were since you never bothered telling us, but I'll hazard a guess that you wrote setInterval(changelight(), 1000) and wondered why it only ever did the first one.

    You can re-use a canvas context! Just get it once and draw on it forever!

    Avoid "magic numbers" like these colours[0] in your original code. Give things meaningful names, such as colours.red, colours.off so you can easily find and change them if you want!

    Use a counter to step through your cycles, don't rely on equality to some arbitrary value. Use % operator to effectively create a repeating cycle of the given length.

    Find patterns and exploit them. A UK traffic light goes in four steps: (red), (red+yellow), (green), (red). US is similar but without the (red+yellow) step... I guess they like testing people's reflexes or something.

    Put it all together, this is what you get:

    var c = document.createElement('canvas'),
        ctx = c.getContext('2d');
    
    c.width = 150;
    c.height = 300;
    document.body.appendChild(c);
    
    var cycle = 0,
        colours = {
          red: "#cc0000",
          yellow: "#cccc00",
          green: "#00cc00",
          off: "#333333"
        };
    
    function drawLight(id,colour) {
      // avoid repetition, use a function!
      ctx.fillStyle = colours[colour];
      ctx.beginPath();
      ctx.arc(95, 50 + 100*id, 40, 0, Math.PI*2);
      ctx.fill();
      ctx.stroke();
    }
    
    function changelight(){
      ctx.stokeStyle = "black";
      ctx.lineWidth = 3;
      
      // top light: red if cycle = 0 or 1, off otherwise
      drawLight(0, cycle <= 1 ? 'red' : 'off');
      
      // middle light: yellow if cycle = 3 (and 1 for UK lights, we have red+yellow before green), off otherwise
      drawLight(1, cycle == 1 || cycle == 3 ? 'yellow' : 'off');
      
      // bottom light: green if cycle = 2
      drawLight(2, cycle == 2 ? 'green' : 'off');
      
      // increment cycle
      cycle = (cycle + 1) % 4;
    }
    
    // start the magic
    setInterval(changelight,1000);

    0 讨论(0)
  • 2021-01-07 16:12

    I would clean things up a bit... you can move all the drawing to one place. Then use a start and stop function. Actually, you can easily combine the start and stop but I will leave that to you. Here you go:

    function light(c) {
      this.current = 0;
      this.colors = ["green", "yellow", "red"];
      this.ctx = c.getContext("2d");
    }
    
    light.prototype.draw = function() {
      this.ctx.beginPath();
      this.ctx.arc(95, 50, 40, 0, 12 * Math.PI);
      this.ctx.fillStyle = this.colors[this.current];
      this.ctx.fill();
    }
    
    light.prototype.start = function() {
      if(this.interval)
        return;
      this.draw();
      this.interval = setInterval(function() {
        this.current = (this.current + 1) % this.colors.length;
        console.log("drawing: ", this.colors[this.current]);
        this.draw();
      }.bind(this), 3000);
    }
    
    light.prototype.stop = function() {
      if (!this.interval)
        return;
      clearInterval(this.interval);
      delete this.interval;
    }
    
    var myLight = new light(document.getElementById("myCanvas"));
    <canvas id="myCanvas"></canvas>
    <button onclick="myLight.start()">start</button>
    <button onclick="myLight.stop()">stop</button>

    0 讨论(0)
提交回复
热议问题