JSFiddle - React, Tailwind, and code Playground

HTML

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Canvas Application</title>
  <style>
    /* Ensuring the canvas fills the entire window */
    body, html {
      margin: 0;
      padding: 0;
      overflow: hidden;
    }

    canvas {
      display: block;
      background-color: #f0f0f0;
    }
  </style>
</head>
<body>
  <canvas id="render_canvas"></canvas>

  <script src="index.js"></script>
</body>
</html>

JavaScript

const canvas = document.getElementById('render_canvas');
const ctx = canvas.getContext('2d');
function resizeCanvas() {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);


class Simulation {

  constructor() {
    this.bodies = [];
  }
  
  step(dt) {
    // slove forces
    for(const body of this.bodies) {
      // v = u  + f/m * t;
      body.linear_velocity[0] += body.force[0] / body.mass * dt;
      body.linear_velocity[1] += body.force[1] / body.mass * dt;
      
      // zero out force
      body.force = [0,0];
    }
    
    // integrate position
    for(const body of this.bodies) {
      // s = s + v * t;
      body.pos[0] += body.linear_velocity[0] * dt;
    }
  }
  
  newBody(pos, radius, density) {
    const body = createBody(pos, radius, density);
    this.bodies.push(body);
  }
}

// create a new physics body
function createBody(pos, radius, density) {
  const volume = (4/3) * Math.PI * radius * radius;
  const mass = density * volume;
  return {
    pos: pos,
    mass: mass,
    radius: radius,
    force: [0,0],
    linear_velocity: [0, 0]
  };
}

function applyForce(body, accleration) {
  // f = ma;
  body.force[0] = body.mass * accleration[0];
  body.force[1] = body.mass * accleration[1];
}

const simulation = new Simulation();
simulation.newBody([20, 100], 20, 10);
simulation.newBody([40, 100], 20, 10);


// Animation loop
let last_time = 0;
function animate(time) {
  requestAnimationFrame(animate);
	
  // calculate frame time
	const diff = time - last_time;
  last_time = time;
  if(diff > 100) { // handle suspend
    return;
  }
  
	const dt = diff / 1000;
  simulation.step(dt);
  
  // apply foce to body 0
  applyForce(simulation.bodies[0], [20, 0]);
  
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  for(const body of simulation.bodies) {
    ctx.beginPath();
      ctx.arc(body.pos[0], body.pos[1], body.radius, 0, 2 * Math.PI);
    ctx.stroke();
 ...