Как правильно анимировать в <canvas>? - PullRequest
0 голосов
/ 02 июля 2018

Итак, я хочу воссоздать этот простой анимационный эффект, который использует :

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 голосов
/ 03 июля 2018

Все, что у тебя в порядке.

Проблема в ваших глобалах.

Ширина холста должна быть установлена ​​на:

w = myCanvas.width;

Высота установлена ​​на:

h = myCanvas.height;

Вы оба задали как:

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

Что не будет работать.

Вот форк (демо).

Я бы настоятельно рекомендовал использовать JQuery при работе с canvas. При использовании canvas следует отметить, что вы хотите использовать как можно больше ссылок на canvas.height и canvas.width, а не на глобальный объект, указывающий на высоту и ширину стиля css.

0 голосов
/ 03 июля 2018

На тот случай, если вы искали более простой способ сделать это, вы можете полностью избежать JavaScript, создавая простую анимацию, подобную этой, с помощью с использованием CSS-анимаций :

#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>
0 голосов
/ 03 июля 2018

Ваша проблема в том, что предыдущие лица не очищаются. Предполагается, что очистка выполняется по следующей строке:

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

Проблема в том, что w и h установлены неправильно при запуске, поэтому очищается недостаточно холста.

Здесь вы можете установить w и h:

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

Это будет работать только в том случае, если ширина и высота были установлены с помощью CSS, например с атрибутом HTML style="width: 200px; height: 200px;", и если вы вызвали parseInt, чтобы преобразовать строки стиля CSS в числа. Но на самом деле ширина и высота элемента canvas были напрямую установлены с помощью атрибутов width и height HTML. Таким образом, вы должны установить w и h с HTMLCanvasElement s width и height свойствами:

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

Оригинальный Codepen устанавливает их таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...