如何在<canvas>中正确设置动画?

时间:2018-07-02 20:52:15

标签: javascript animation html5-canvas

所以我想重新创建这个简单的动画效果,它使用

https://codepen.io/w3devcampus/pen/PpLLKY

HTML:

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Draw a monster in a canvas</title>
</head>
<body>
  <canvas id="myCanvas"  width="200" height="200"></canvas>
</body>
</html>

JavaScript:

function mainLoop() {

  ctx.clearRect(0, 0, w, h);

  drawMyMonster(xMonster, yMonster);

  xMonster += monsterSpeed;

   if (((xMonster + 100)> w) || (xMonster < 0))  {
    monsterSpeed = -monsterSpeed;
  }

}

function drawMyMonster(x, y) {

    ctx.save();

    ctx.translate(x, y);

    ctx.strokeRect(0, 0, 100, 100);
    ctx.fillRect(20, 20, 10, 10);
    ctx.fillRect(65, 20, 10, 10);
    ctx.strokeRect(45, 40, 10, 40);
    ctx.strokeRect(35, 84, 30, 10);
    ctx.fillRect(38, 84, 10, 10);
    ctx.fillRect(52, 84, 10, 10);

   ctx.restore();
}

所以,我确实重新创建了它,但是它不能正常运行。而不是一次显示一帧,而是将所有帧彼此堆叠在画布中。这是我的版本:

https://codepen.io/Undefined_Variable/pen/LraLJQ

HTML:

<html>
  <head>
    <title>CanvasThingy</title>
  </head>
  <body>
    <canvas id="CanvasForMonster">
      No support for you scrub!
    </canvas>
  </body>
</html>

JavaScript:

var myCanvas, context, w, h;

var xMonster = 60;
var yMonster = 30;
var monsterSpeed = 1;

window.onload = function initial(){

  myCanvas = document.body.querySelector('#CanvasForMonster');
  w = myCanvas.style.width;
  h = myCanvas.style.height;
  context = myCanvas.getContext('2d');

ClearCanvas();
}

function ClearCanvas(){
  context.clearRect(0, 0, w, h);

   DrawFMLface(xMonster, yMonster);

    xMonster += monsterSpeed;

  if(((xMonster + 175) > 299) || (xMonster < 0) ){
    monsterSpeed = -monsterSpeed;
 }

   requestAnimationFrame(ClearCanvas);

}

function DrawFMLface(x, y){
  context.save();

  context.translate(x, y);

  context.strokeRect(0, 4, 175, 80);
  context.strokeStyle = 'black';

  context.fillRect(40, 10, 20, 20);
  context.strokeStyle = 'black';

  context.fillRect(110, 10, 20, 20);
  context.strokeStyle = 'black';

  context.strokeRect(85, 40, 1, 15);
  context.strokeStyle = 'black';

  context.strokeRect(42, 70, 90, 0);
  context.strokeStyle = 'black';

  context.restore();
}

请告诉我如何在没有jQuery的情况下正确执行此操作。我仍在学习,请不要在我的代码中使用任何jQuery / Angular / React等!

3 个答案:

答案 0 :(得分:2)

您的问题是先前的面孔没有被清除。清除应该通过以下这一行完成:

ctx.clearRect(0, 0, w, h);

问题是运行时wh的设置不正确,因此没有清除足够的画布。

在这里设置wh

w = myCanvas.style.width;
h = myCanvas.style.height;

仅当宽度和高度是使用CSS设置的(例如,带有HTML属性style="width: 200px; height: 200px;",并且如果您调用parseInt将CSS样式字符串转换为数字。但是实际上canvas element的宽度和高度是直接由widthheight HTML属性设置的。因此,您应该使用HTMLCanvasElementwidthheight属性设置wh

w = canvas.width;
h = canvas.height;

原始的Codepen以这种方式设置它们。

答案 1 :(得分:1)

如果您正在寻找一种可能更简单的方法来实现此目的,则using CSS animations创建这样的简单动画时实际上可以完全避免使用JavaScript:

#CanvasForMonster {
  position: relative;
  width: 200px;
  height: 200px;
  border: 1px solid #000;
}

#Monster {
  position: absolute;
  top: 25%;
  width: 50%;
  height: 50%;
  animation: bounce 2s alternate linear infinite;
}

@keyframes bounce {
  from { left: 0; }
  to { left: 50%; }
}

#Monster div {
  position: absolute;
}

#Monster .stroke {
  border: 1px solid #000;
}

#Monster .fill {
  background-color: #000;
}

#Monster .head {
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

#Monster .eye {
  width: 10%;
  height: 10%;
}

#Monster .eye-left {
  left: 25%;
  top: 25%;
}

#Monster .eye-right {
  left: 65%;
  top: 25%;
}

#Monster .nose {
  left: 50%;
  top: 50%;
  width: 1px;
  height: 10%;
}

#Monster .mouth {
  left: 25%;
  top: 75%;
  width: 50%;
  height: 0;
}
<div id="CanvasForMonster">
  <div id="Monster">
    <div class="stroke head"></div>
    <div class="fill eye eye-left"></div>
    <div class="fill eye eye-right"></div>
    <div class="stroke nose"></div>
    <div class="stroke mouth"></div>
  </div>
</div>

答案 2 :(得分:0)

一切都还好。

问题出在你的全局对象上。

画布的宽度应设置为:

w = myCanvas.width;

高度设置为:

h = myCanvas.height;

您都设置为:

w = myCanvas.style.width;
h = myCanvas.style.height;

这将不起作用。

这里是fork(演示)。

我强烈建议在使用画布时使用JQuery。 使用画布时,应注意,您也要尽可能参考canvas.height和canvas.width,而不要使用一个指向css样式的高度和宽度的全局变量。