我的代码中的画布仅在for循环之后显示。我追求动画效果

时间:2019-06-17 14:53:05

标签: javascript html canvas

我正在学习javascript OOP,因此决定实施Langstons蚂蚁。我在使用html5画布时遇到了麻烦。当我运行此命令时,Ant.js中的调试警报会按预期方式弹出,但只有在完成这些操作后,画布才会出现在我的浏览器(chrome)中。然后看起来它应该处于循环结束的状态。 为什么是这样? 在此先感谢。

这是我的代码;

langstonsAnt.html

details {
  border-bottom: 1px solid #3C3C3B;
  max-width: 80%;
}

details summary {
  outline: none;
  font-weight: 600;
  padding: 10px 0px;
  cursor: pointer;
}

details summary::-webkit-details-marker {
  background: url(https://image.flaticon.com/icons/svg/3/3907.svg) center no-repeat;
  color: transparent;
  width: 30px;
  /* known value*/
  height: 20px;
  float: right;
}

details[open] summary::-webkit-details-marker {
  background: url(https://image.flaticon.com/icons/svg/3/3581.svg) center no-repeat;
  color: transparent;
  width: 30px;
  height: 20px;
  float: right;
}

summary+* {
  padding-right: 30px;
  /* known value */
}

antGame.js

<details>
  <summary>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor. Lorem ipsum dolor sit amet </summary>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation</p>
</details>

Ant.js

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Langstons Ant</title>
<script defer src="antGame.js"></script>
<script src="Ant.js"></script>
<script src="AntWorld.js"></script>
</head>
<body>
<canvas id="antboard" width="700" height="700" style="border: 5px solid black; background-size: 100%;">
    Canvas not supported
</canvas>
</body>

</html>

AntWorld.js

let c = document.getElementById("antboard");
let ctx = c.getContext("2d");
startGame(ctx);

function startGame(ctx)
{
    for (let x=0; x<100; x++)
    {
        for (let y=0; y<100; y++)
        {
            ctx.fillStyle = "red";
            ctx.fillRect(7 * x, 7 * y, 7, 7);
        }
    }
}

// create antWorld board
let world = new AntWorld(100, ctx);

// create the ant
let ant = new Ant(world.board);

// place the ant on the board
world.setAntPos(ant.getAntX(), ant.getAntY());


// THIS IS THE LOOP I AM REFERRING THAT CALLS THE ALERTS.
for (let i=0; i<16; i++)
{
    ant.moveForward();
    world.setAntPos(ant.getAntX(),ant.getAntY());
    //sleep(100);
}

function sleep(milliseconds) {
    let start = new Date().getTime();
    for (let i=0; i<1e7; i++) {
        if ((new Date().getTime() - start) > milliseconds){
            break;
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您所做的(在删除警报并取消注释sleep()之后)是busy sleep。这意味着在您的睡眠例程中,Javascript一直处于忙碌状态。没有时间做其他事情,例如渲染画布,因为它正在循环。

您需要使用系统事件来执行下一个操作。通常,这将是用户或计时器的按键。

因此,让我们使用计时器重新编码以下代码:

for (let i=0; i<16; i++)
{
    ant.moveForward();
    world.setAntPos(ant.getAntX(),ant.getAntY());
    sleep(100);
}

使用计时器将变为:

function moveTheAnt()
{
    ant.moveForward();
    world.setAntPos(ant.getAntX(),ant.getAntY());
    stepCount++;
    if (stepCount > 16) clearInterval(stepTimer);
}

let stepCount = 0;
let stepTimer = setInterval(moveTheAnt, 100);

您可以在此处查看它的运行情况:JSFiddle

有关Javascript计时器的更多信息,请参见:https://www.w3schools.com/js/js_timing.asp

有关一般事件的信息,请参见:https://www.w3schools.com/JS/js_events.asp

这两个链接只是示例,可能会有更好的教程。

答案 1 :(得分:0)

如果您想在浏览器中使用JavaScript制作动画,则应该使用requestAnimationFrame并适当地构建代码。

那是说,如果您只想破解,则可以在循环中使用async / await。首先,我们需要一个会等待一段时间的函数

function sleep(ms = 0) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

然后,我们需要将循环放入async函数中,并使用sleep关键字调用await

async function loop() {
  for (let i=0; i<16; i++)
  {
      ant.moveForward();
      world.setAntPos(ant.getAntX(),ant.getAntY());
      await sleep(100);  // pause 100 milliseconds
  }
}
loop();

这是一个例子

function sleep(ms = 0) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function loop() {
  for (let i=0; i<16; i++)
  {
      console.log(i);
      await sleep(1000);  // pause 1000 milliseconds
  }
}
loop();

有关更多信息,请参见:https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await