JavaScript使用带有画布的setInterval连续运行函数

JavaScript-Run a function continuously using setInterval with a canvas

本文关键字:setInterval 连续 运行 函数 JavaScript      更新时间:2023-09-26

我正在努力让红绿灯自动亮起并连续运行。函数不会显示所有灯光,只显示第一个和最后一个。我试过使用setInterval(),但没有成功。这可能与这条线路放错了地方有关。ctx.clearRect(0,0,canvas.width,canvas.height);我是JavaScript的新手,这是我第一次使用画布。我能在这个上得到一些帮助吗

这是我的JSFiddle链接:http://jsfiddle.net/nmrsjp/opv1cpyx/11/

提前感谢

var red = ["Red", "White", "White"]
var redAmber = ["Red", "Yellow", "White"]
var green = ["White", "White", "Green"]
var amber = ["White", "Yellow", "White"]
var x = 50
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var circle = function (x, y, radius) {
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI * 2, false);
    ctx.stroke();
    ctx.fill();
};
var draw = function (colour) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (i = 0; i < 3; i++) {
        ctx.lineWidth = 1;
        ctx.strokeStyle = "Black";
        ctx.fillStyle = colour[i];
        circle(50, x, 40);
        x = x + 120;
    }
    x = 50
}
var myVar = setInterval(function () {draw(red)}, 1000);
var myVar = setInterval(function () {draw(redAmber)}, 3000);
var myVar = setInterval(function () {draw(green)}, 3000);
var myVar = setInterval(function () {draw(amber)}, 3000);
<canvas id="canvas1" width="100" height="350" style="border:1px solid"></canvas>

您每秒将颜色设置为red一次。你每隔三秒钟设置一次其他颜色,它们几乎同时被激发,但也会被再次设置为红色立即覆盖。

我不确定你到底希望它如何表现,但如果你想要一个恒定的间隔,但在不同的时间发射,你也需要延迟间隔的设置。下面是一个4秒间隔全部延迟1秒的例子:

setInterval(function () { draw(red) }, 4000);
setTimeout(function() { setInterval(function () { draw(redAmber) }, 4000); }, 1000);
setTimeout(function() { setInterval(function () { draw(green) }, 4000); }, 2000);
setTimeout(function() { setInterval(function () { draw(amber) }, 4000); }, 3000);

Fiddle

定义一个序列,然后循环通过,只使用一个间隔可能更容易:

var colourSequence = [red, redAmber, green, amber];
var position = -1;
function changeColour() {
    draw(colourSequence[++position % colourSequence.length]);
}
setInterval(changeColour, 1000);

Fiddle

您设置间隔的方式不正确。使用如下:

http://jsfiddle.net/opv1cpyx/18/enter此处的链接描述

var red = ["Red", "White", "White"];
var redAmber = ["Red", "Yellow", "White"];
var green = ["White", "White", "Green"];
var amber = ["White", "Yellow", "White"];
var lights = [red, redAmber, green, amber];
var x = 50
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var circle = function (x, y, radius) {
    ctx.beginPath();
    ctx.arc(x, y, radius, 0, Math.PI * 2, false);
    ctx.stroke();
    ctx.fill();
};
var draw = function (colour) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (i = 0; i < 3; i++) {
    ctx.lineWidth = 1;
    ctx.strokeStyle = "Black";
    ctx.fillStyle = colour[i];
    circle(50, x, 40);
    x = x + 120;
}
x = 50;
}
var li=0;
var myVar = setInterval(function () {
    if(li > 3)
        li = 0;
    draw(lights[li++]);
}, 3000);

试试这个:

Fiddle

var red = ["Red", "White", "White"]
var redAmber = ["Red", "Yellow", "White"]
var green = ["White", "White", "Green"]
var amber = ["White", "Yellow", "White"]
var x = 50
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var circle = function(x, y, radius) {
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI * 2, false);
  ctx.stroke();
  ctx.fill();
};
var draw = function(colour) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for (i = 0; i < 3; i++) {
    ctx.lineWidth = 1;
    ctx.strokeStyle = "Black";
    ctx.fillStyle = colour[i];
    circle(50, x, 40);
    x = x + 120;
  }
  x = 50
}
var index = 0;
var myVar = setInterval(function() {
  switch (index) {
    case 0:
      draw(red);
      break;
    case 1:
      draw(green);
      break;
    case 2:
      draw(amber);
      break;
  }
  index = (index + 1) % 3;
}, 1000);
<canvas id="canvas1" width="100" height="350" style="border:1px solid"></canvas>


试试这个

  $(document).ready(function () {
    var red = ["Red", "White", "White"]
    var redAmber = ["Red", "Yellow", "White"]
    var green = ["White", "White", "Green"]
    var amber = ["White", "Yellow", "White"]
    var x = 50
    var canvas = document.getElementById("canvas1");
    var ctx = canvas.getContext("2d");
    var circle = function (x, y, radius) {
        ctx.beginPath();
        ctx.arc(x, y, radius, 0, Math.PI * 2, false);
        ctx.stroke();
        ctx.fill();
    };
    var draw = function (colour) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        for (i = 0; i < 3; i++) {
            ctx.lineWidth = 1;
            ctx.strokeStyle = "Black";
            ctx.fillStyle = colour[i];
            circle(50, x, 40);
            x = x + 120;
        }
        x = 50
    }
    setTimeout(function () { setInterval(function () { draw(red) }, 4000); }, 1000);
    setTimeout(function () { setInterval(function () { draw(redAmber) }, 4000); }, 2000);
    setTimeout(function () { setInterval(function () { draw(green) }, 4000); }, 3000);
    setTimeout(function () { setInterval(function () { draw(amber) }, 4000); }, 4000);
});

有很多答案。这里有一个替代方案。

不要使用setInterval。使用setTimeout。我想你希望灯光在每个新灯光之后都更改一个预设时间。应避免setInterval,除非你找不到其他方法

最好的方法是创建一个光状态的对象。每一个州都通向下一个州。结构有灯亮的时间和下一个状态应该是什么。

lights = {
   red:{
      timeOn:1000, // how long it is on for
      display:["red","white","white"], // the colours
      next:"amber", // what comes next.
   },
   amber:{
      timeOn:2000,
      display:["red","#F90","white"],
      next:"green",
   },
   green:{
      timeOn:3000,
      display:["white","white","green"],
      next:"amberGreen",
   },
   amberGreen:{
      timeOn:1000,
      display:["red","#F90","white"],
      next:"red",
   },
}

添加绘图功能,

var circle = function (x, y,col) {
    ctx.beginPath();
    ctx.fillStyle = col;
    ctx.arc(x, y, 40, 0, Math.PI * 2);
    ctx.stroke();
    ctx.fill();
};
function draw(){
    ctx.strokeRect(0, 0, 100, 240 + 4 * 20);
    var posY = 50;
    var lightInd = 0;
    circle(50, posY, nextLightState.display[lightInd ++]);
    circle(50, posY += 100, nextLightState.display[lightInd ++]);
    circle(50, posY += 100, nextLightState.display[lightInd ++]);
    // get the current time
    var currentTime = new Date().valueOf();
    // calc when the next light should be on
    nextTime += nextLightState.timeOn;
    // set the time out to that time. Sometimes the system can get hung up
    // doing other stuff. You just have to make sure you have not gone over 
    // time and give setTimeout a negative value. If it does get delayed it 
    // will automatically switch states quickly and catch up to where it should 
    // be
    setTimeout(draw, Math.max(0,nextTime-currentTime));
    // set the next light state provided in the light state description
    nextLightState = lights[nextLightState.next];    
}

您希望它非常精确,否则就不会使用setInterval。由于setTimeout可能会漂移,您只需要添加一点时间保持,以确保您的时间保持正确。

设置画布上下文状态。

ctx.lineWidth = 2;
ctx.strokeStyle = "black";

现在只需要当前时间和下一个灯光状态。然后调用draw函数,它就会消失。

var nextTime = new date().valueOf(); // get the current time in ms
var nextLightState = lights.red;     // set the next light state
draw(); // start it going.

下面是一个工作示例。

var canvas = document.getElementById("canV");
var ctx = canvas.getContext("2d");
// describe all the requiered states
var lights = {
   red:{
      timeOn:1000,  // how long it is on for
      display:["red","white","white"], // the light colours
      next:"amber",  // what the next state is
   },
   amber:{
      timeOn:3000,
      display:["white","#F90","white"],
      next:"green",
   },
   green:{
      timeOn:3000,
      display:["white","white","#0F0"],
      next:"amberGreen",
   },
   amberGreen:{
      timeOn:1000,
      display:["red","#F90","white"],
      next:"red", // points to the first state
   },
}
// draws a light
var circle = function (x, y,col) {
    ctx.beginPath();
    ctx.fillStyle = col;
    ctx.arc(x, y, 40, 0, Math.PI * 2);
    ctx.fill();
    ctx.stroke();
};
ctx.lineWidth = 3;
ctx.strokeStyle = "black";
function draw(){
    ctx.strokeRect(0, 0, 100, 240 + 4 * 20); // draw the box;
    // set up the vars to draw lights
    var posY = 50;
    var lightInd = 0;
    // no need for a loop as there are always 3 lights
    circle(50, posY, nextLightState.display[lightInd ++]);
    circle(50, posY += 100, nextLightState.display[lightInd ++]);
    circle(50, posY += 100, nextLightState.display[lightInd ++]);
  
    // get the current time
    var currentTime = new Date().valueOf();
  
    // workout when the next light state is due
    nextTime += nextLightState.timeOn;
  
    // set the timeout for the due time
    setTimeout(draw,nextTime-currentTime)
    
    // set the next light state from that requiered by the current state
    nextLightState = lights[nextLightState.next];    
}
    
var nextTime = new Date().valueOf(); // get the current time in ms
var nextLightState = lights.red;     // set the next light state
draw(); // start it going.
#canV {
  width:100px;
  height:320px;
}
<canvas id="canV" width=100 height=320></canvas>