Canvas animation

Ongoing experimentation around canvas animation.




Look at the code
<style>
canvas{
width: 100%;
max-width: 370px;
}
</style>
<div>
<button id="startAnimationButton">Start animation</button>
<button id="stopAnimationButton">Stop animation</button>
</div>
<canvas id="canvas" width="370" height="310"></canvas>

<script>

let canvas, ctx, startButton, stopButton, w, h, requestId;
let animationIncrement = 1/100, animationDirection = -1, scaleValue = 1, translateValueW = 0, translateValueH = 0;

const load = () => {
  //event listeners
  startButton = document.querySelector("#startAnimationButton");
  startButton.addEventListener('click', start, false);
  stopButton = document.querySelector("#stopAnimationButton");
  stopButton.addEventListener('click', stop, false);
  //canvas settingd
  canvas = document.querySelector("#canvas");
  ctx = canvas.getContext("2d");
  w = canvas.width;
  h = canvas.height;

  requestId = requestAnimationFrame(animateLadybird);
}
window.onload = load;

const animateLadybird = (timestamp) => {

  //clear canvas
  //ctx.fillRect(0, 0, w, h);
  ctx.clearRect(0, 0, w, h);

  //draw stuff
  drawLogo(scaleValue, translateValueW, translateValueH);

  //animate the bug
  if(scaleValue < 0 || scaleValue > 1){
    animationDirection = -animationDirection;
  }
  scaleValue += animationDirection*animationIncrement;
  translateValueW += (-animationDirection)*w*animationIncrement/2;
  translateValueH += (-animationDirection)*h*animationIncrement/2;
  console.log(translateValueW);


  //recursive call
  //if(requestId) cancelAnimationFrame(requestId);
  requestId = requestAnimationFrame(animateLadybird);

}

//callbacks
const start = (event) => {
  if(requestId) cancelAnimationFrame(requestId);
  requestId = requestAnimationFrame(animateLadybird);
}
const stop = (event) => {
  if(requestId) cancelAnimationFrame(requestId);
}


const drawLogo = (s=1,x=0,y=0) => {//drawing the logo
  //console.log("drawing logo");
  //save first and restore at the end
  ctx.save();

  //scale animation
  ctx.translate(x,y);
  ctx.scale(s,s);

  // #body
  ctx.save();
	ctx.beginPath();
	ctx.fillStyle = 'rgb(221, 148, 32)';
	ctx.moveTo(184.427000, 35.014000);
	ctx.bezierCurveTo(242.917269, 35.014000, 290.333000, 94.109279, 290.333000, 167.007000);
	ctx.bezierCurveTo(290.333000, 239.904721, 242.917269, 299.000000, 184.427000, 299.000000);
	ctx.bezierCurveTo(125.936731, 299.000000, 78.521000, 239.904721, 78.521000, 167.007000);
	ctx.bezierCurveTo(78.521000, 94.109279, 125.936731, 35.014000, 184.427000, 35.014000);
	ctx.fill();
  ctx.restore();

  // #separator_body
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(255, 255, 255)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.miterLimit = 10;
	ctx.moveTo(110.969000, 84.500000);
	ctx.bezierCurveTo(110.969000, 102.462000, 145.031000, 121.000000, 185.893000, 121.000000);
	ctx.lineTo(185.161000, 121.000000);
	ctx.bezierCurveTo(226.019000, 121.000000, 257.970000, 103.211000, 257.970000, 85.250000);
	ctx.stroke();
  ctx.restore();

  // #separator_head
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(255, 255, 255)';
	ctx.lineWidth = 16.000000;
  ctx.lineCap = 'round';
	ctx.miterLimit = 10;
	ctx.moveTo(184.000000, 292.000000);
	ctx.lineTo(184.000000, 130.000000);
	ctx.stroke();
  ctx.restore();

  // #legs

  // #leg_1
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(39.250000, 89.820000);
	ctx.lineTo(80.500000, 107.191000);
	ctx.lineTo(88.750000, 132.463000);
	ctx.stroke();
  ctx.restore();

  // #leg_2
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(331.004000, 89.820000);
	ctx.lineTo(289.754000, 107.191000);
	ctx.lineTo(281.504000, 132.463000);
	ctx.stroke();
  ctx.restore();

  // #leg_3
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(61.042000, 298.726000);
	ctx.lineTo(61.238000, 253.951000);
	ctx.lineTo(93.956000, 236.299000);
	ctx.stroke();
  ctx.restore();

  // #leg_4
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(308.945000, 298.726000);
	ctx.lineTo(308.750000, 253.951000);
	ctx.lineTo(276.032000, 236.299000);
	ctx.stroke();
  ctx.restore();

  // #leg_5
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(359.834000, 193.660000);
	ctx.lineTo(325.649000, 164.742000);
	ctx.lineTo(290.982000, 178.170000);
	ctx.stroke();
  ctx.restore();

  // #leg_6
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(9.982000, 193.660000);
	ctx.lineTo(44.167000, 164.742000);
	ctx.lineTo(78.834000, 178.170000);
	ctx.stroke();
  ctx.restore();

  // #aerials

  // #aerialleft
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(169.250000, 38.014000);
	ctx.lineTo(132.250000, 20.080000);
	ctx.lineTo(98.000000, 10.335000);
	ctx.stroke();
  ctx.restore();

  // #aerial_right
  ctx.save();
	ctx.beginPath();
	ctx.strokeStyle = 'rgb(221, 148, 32)';
	ctx.lineWidth = 16.000000;
	ctx.lineCap = 'round';
	ctx.lineJoin = 'bevel';
	ctx.miterLimit = 10;
	ctx.moveTo(202.000000, 38.014000);
	ctx.lineTo(239.000000, 20.080000);
	ctx.lineTo(273.250000, 10.335000);
	ctx.stroke();
  ctx.restore();

  //restore the context after drawing on the canvas
  ctx.restore();
}

</script>