javascript 如何用动画制作交通灯?

ma8fv8wu  于 2023-05-05  发布在  Java
关注(0)|答案(2)|浏览(126)
//traffic lights:red,yellow,green
    fill(trafficFirstLightColor)
    ellipse(315, 40, 20, 20)
    fill(trafficSecondLightColor)
    ellipse(315, 40 + 25 * 1, 20, 20)
    fill(trafficThirdLightColor)
    ellipse(315, 40 + 25 * 2, 20, 20)

    //if three lights with black, first light on
    x+=10
    if (trafficFirstLightColor === "black" && trafficSecondLightColor === "black" && trafficThirdLightColor === "black" && x == 3000) {
        setTimeout(() => {
            trafficFirstLightColor = 'red';
        }, x)
    } else if (trafficFirstLightColor === "red" && x == 6000) {
        trafficFirstLightColor = "black"
        setTimeout(() => {
            trafficSecondLightColor = 'yellow';
        }, x-3000)
    } else if (trafficSecondLightColor === "yellow" && x == 9000) {
        trafficSecondLightColor = "black"
        setTimeout(() => {
            trafficThirdLightColor = 'green';
        }, x-6000)
    }

我试图为交通灯每3秒生成颜色;然而,它失败了……
我最初有三个黑色的交通灯,并给他们特定的变量,我给另一个变量x作为if-else语句中的变量,当所有的交通灯都是黑色的,第一个交通灯变成红色。然后,当第一个交通灯变为红色时,第二个交通灯变为黄色3秒。最后,当第二个交通灯变成黄色时,第三个交通灯变成绿色。顺便说一句,计划很棒,但代码很糟糕。

lzfw57am

lzfw57am1#

假设这是一个使用setupdraw的p5.js配置,draw函数的执行速度高达30/60 FPS,因此您不必手动调用setTimeout来触发更改。相反,您可以将当前的millis()与以前的millis()进行比较,以了解自上次调用draw()以来所经过的时间。
下面是一个尝试使用p5.js而不使用setTimeout执行交通灯动画的示例:

let trafficFirstLightColor = 'black';
let trafficSecondLightColor = 'black';
let trafficThirdLightColor = 'black';
let start;

function setup() {
  createCanvas(400, 400);
  trafficFirstLightColor = 'black';
  trafficSecondLightColor = 'black';
  trafficThirdLightColor = 'black';
  start = millis();
}

function draw() {
  fill(trafficFirstLightColor);
  ellipse(315, 40, 20, 20);
  fill(trafficSecondLightColor);
  ellipse(315, 40 + 25 * 1, 20, 20);
  fill(trafficThirdLightColor);
  ellipse(315, 40 + 25 * 2, 20, 20);
  
  const now = millis();
  const cycle = now - start;
  
  if (cycle < 3000) {
    if (trafficFirstLightColor === 'black' &&
    trafficSecondLightColor === 'black' &&
    trafficThirdLightColor === 'black') {
      trafficFirstLightColor = 'red';
      return;
    }
  } else if (cycle < 6000) {
    if (trafficFirstLightColor === 'red') {
      trafficFirstLightColor = 'black';
      trafficSecondLightColor = 'yellow';
      return;
    }
  } else if (cycle < 9000) {
    if (trafficSecondLightColor === 'yellow') {
      trafficSecondLightColor = 'black';
      trafficThirdLightColor = 'green';
      return;
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>
nmpmafwu

nmpmafwu2#

当你处理多个值时,使用一个数据结构,而不是thing1thing2thing3 ...。在这种情况下,我们可以创建一个数组,其中包含3个包含颜色和持续时间属性的对象,然后循环数组或使用索引在渲染灯光时遍历灯光。

const lights = [
  {
    color: "green",
    duration: 10_000,
  },
  {
    color: "yellow",
    duration: 3_000,
  },
  {
    color: "red",
    duration: 10_000,
  },
];

function setup() {
  createCanvas(50, 50);
  noStroke();
  noLoop();
  renderLights();
}

const renderLights = () => {
  clear();
  const {duration, color} = lights[0];
  fill(color);
  ellipse(width / 2, height / 2, width, height);
  setTimeout(renderLights, duration);
  lights.push(lights.shift());
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

代码不仅泛化得很好(您可以随意添加和删除灯光),而且通过分离配置和实现逻辑,可以更容易地调整持续时间,而不会在代码中出现混乱。
如果您的画布在draw中的每一帧上都被清除,则可以将灯光循环与绘图分开:

const lights = [
  {
    color: "green",
    duration: 10_000,
  },
  {
    color: "yellow",
    duration: 3_000,
  },
  {
    color: "red",
    duration: 10_000,
  },
];

function setup() {
  createCanvas(50, 50);
  noStroke();
  runLightCycle();
}

function draw() {
  background(0);
  renderCurrentLight();
}

const renderCurrentLight = () => {
  fill(lights[0].color);
  ellipse(width / 2, height / 2, width, height);
};

const runLightCycle = () => {
  setTimeout(() => {
    lights.push(lights.shift());
    runLightCycle();
  }, lights[0].duration);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

请记住,setTimeout是一个粗略的估计,而不是一个精确的持续时间,所以这将随着时间的推移而漂移。
如果你想避免漂移,你可以跟踪最后一次灯光变化的时间,然后反复检查自最后一次灯光变化以来所经过的毫秒数。当它超过当前灯光持续时间时,将上次更改时间增加持续时间并重复。
如果要一次渲染所有灯光而不是更改单个灯光的颜色,可以添加循环:

const lights = [
  {
    color: "green",
    duration: 10_000,
  },
  {
    color: "yellow",
    duration: 3_000,
  },
  {
    color: "red",
    duration: 10_000,
  },
];
let currentLight = 0;
const lightSize = 50;

function setup() {
  createCanvas(lightSize, lightSize * lights.length);
  noStroke();
  noLoop();
  renderLights();
}

const renderLights = () => {
  clear();
  lights.forEach((e, i) => {
    fill(i === currentLight ? e.color : "black");
    ellipse(
      lightSize / 2,
      lightSize / 2 + i * lightSize,
      lightSize,
      lightSize
    );
  });
  setTimeout(renderLights, lights[currentLight].duration);
  currentLight = ++currentLight % lights.length;
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js"></script>

相关问题