<p>collisions: 0</p>
<button onclick="m2 = 1;draw();">1 kg</button>
<button onclick="m2 = 100;draw();">100 kg</button>
<button onclick="m2 = 10000;draw();">10.000 kg</button>
<button onclick="m2 = 1000000;draw();">1.000.000 kg</button><br>
<canvas id="canvas" width="700" height="350"></canvas>
<span class="reload" onclick="draw()">Reload?</span>
<p class="p2">Imagine a frictionless ground where square b (blue) slides into square a (white) without energy loss. The amount of collisions of the white square will equal the digits of pi. The estimation will become more and more accurate if the mass of square b increases.</p>
html {
  background-color: #000111;
}

body {
  margin: 50px;
  padding: 0px;
  font-family: 'Roboto', sans-serif;
}

canvas {
  box-shadow: 0px 0 200px -50px #fff;
  border-radius: 1em;
  border-bottom-left-radius: 0;
  width: 40%;
  min-width: 300px;
}

p {
  font-size: calc(3vh + 0.5em);
  margin: 0;
  margin-bottom: 0.5em;
  color: white;
  display: inline-block;
  vertical-align: middle
}

.p2 {
  position: relative;
  top: 50%;
  margin-left: 2em;
  vertical-align: top;
  width: 40%;
}

button {
  background: white;
  border: none;
  border-radius: 1em;
  padding: 2em;
  padding-top: 0.75em;
  padding-bottom: 0.75em;
  margin-left: 2em;
  position: relative;
  bottom: 0.5em;
  display: inline-block;
  cursor: pointer;
  outline: none;
}

@media screen and (max-width: 900px) {
  canvas {
    width: 100%;
  }
  p {
    display: block;
  }
  .p2 {
    margin-left: 0;
    width: 100%;
    margin-top: 0.2em;
  }
  button {
    margin: 0.5em;
  }
}

.reload {
	position: absolute;
	color: black;
	padding: 1em;
	border-radius: 0.5em;
	background: #49fb35;
	cursor: pointer;
	pointer-events: none;
	opacity: 0;
	transition: opacity 200ms ease;
	transition-delay: 0s;
}

.reload.visible {
	pointer-events: all;
	opacity: 1;
	transition: opacity 500ms ease;
	transition-delay: 1s;
}
var canvas = document.getElementById("canvas"),
  context = canvas.getContext("2d"),
  x, y, m1 = 1,
  m2 = 1,
  x2, y2, vx, vx2, p = document.querySelector('p'),
  html = p.innerHTML.split(' '),
  collid = false,
  collisions = 0,
  w = 80,
	w2 = 80,
	span = document.querySelector('span');

context.fillStyle = "#000111"; //"#0001";
context.fillRect(0, 0, canvas.width, canvas.height);

function spanOffset() {
	var cRect = canvas.getBoundingClientRect();
	span.style.left=canvas.offsetWidth/2+cRect.left-span.offsetWidth/2+"px";
 	span.style.top=canvas.offsetHeight/2+cRect.top-span.offsetHeight/2+"px";
}

spanOffset();

window.addEventListener("resize", function(){
	spanOffset();
}, true);

var renderCv = function(width, height, render) {
  var buffer = document.createElement('canvas');
  buffer.width = width;
  buffer.height = height;
  render(buffer.getContext('2d'));
  return buffer;
};

var square1 = renderCv(w2, w2, function(ctx) {
  ctx.fillStyle = "#fff";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "#000111";
  ctx.font = "17pt sans-serif";
  ctx.textBaseline = 'middle';
  ctx.textAlign = 'center';
  ctx.fillText("1 kg", w2 / 2, w2 / 2);
});

var square2;

function draw() {
	context.fillStyle = "#000111"; //"#0001";
  context.fillRect(0, canvas.height-w, canvas.width, canvas.height);
  w = w2-20 + (10 * m2.toString().split('').length*2);
  x = 100;
  y = canvas.height - w2;
  x2 = 350;
  y2 = canvas.height - w;
  vx = 0;
  vx2 = 0.01;
  p.style.color="#fff";
  p.innerHTML = html[0] + ' ' + 0;
	span.classList.remove('visible');
  collid = false;
  collisions = 0;
  square2 = renderCv(w, w, function(ctx) {
    ctx.fillStyle = "#a6dbf0";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "#000111";
    ctx.font = "17pt sans-serif";
    ctx.textBaseline = 'middle';
    ctx.textAlign = 'center';
    ctx.fillText(m2.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".") + " kg", w / 2, w / 2);
  });
}


function collide(squareA, squareB) {
  return !(x + squareA.width < x2 ||
    x2 + squareB.width < x);
}

function countUp() {
  collisions++;
  html = p.innerHTML.split(' ');
  var num = collisions.toString();
  var num1 = num.split('')[0];
  var numx = num.substring(1, num.length);
  //console.log(numx)
  num = num1;
  if (numx) {
    num = num1 + '.' + numx;
  }
  p.innerHTML = html[0] + ' ' + num;
}

function renderFrame() {
  x -= vx;

  if (x < 0 || x > x2) {
    vx = -vx;
    x = 0;
    countUp();
  }
  /*if (x2 < square1.width) {
    x2 = square1.width;
    x2 -= vx2;
  } else {
    x2 -= vx2;
  }*/
	
	x2 -= vx2;

  //if( x2 < 0) vx2 = - vx2, countUp();
  /*if (~(vx.toFixed(0)+1) == 0 && Math.abs(vx2.toFixed(0)) == 1 && collid == true) {
    setTimeout(function() {
      draw();
    },3000);
  }*/
  var n = m2;
  if (n == 1) {
    n = 100;
  }
  if (Number(p.innerHTML.split(' ')[1].replace('.', '')) == (Math.PI * m2 / Math.sqrt(m2, 2)).toString().split('.')[0]) {
    p.style.color="#49fb35";
		span.classList.add('visible');
		/*setTimeout(function() {
      draw();
    }, 3000);*/
  }

  if (collide(square1, square2)) {
    var t = vx;
    vx = ((m1 - m2) * t + 2 * m2 * vx2) / (m1 + m2);
    vx2 = t - vx2 + vx;
    countUp();
    collid = true;
  }

  //context.clearRect(0, canvas.height-w, canvas.width, canvas.height);
	context.clearRect(0, 0, canvas.width, canvas.height);
  context.drawImage(square1, x, y);
  context.drawImage(square2, x2, y2);
  requestAnimationFrame(renderFrame);
}
draw();
for (var i = 0; i < 100; i++) {
  renderFrame();
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.