JSFiddle - React, Tailwind, and code Playground

HTML

<canvas id="canvas" style="border: 1px solid" width="1000" height="600"></canvas>

JavaScript

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let raf;
var G = 1; //гравитационная постоянная

var balls = [];

for (var i = 0; i < 4; i ++) {
  for (var j = 0; j < 4; j ++) {
    balls.push({
      x: i * 100 + 350,
      y: j * 100 + 100,
      f: 0,
      a: 0,
      radius: 5,
      color: "rgb("+Math.pow(2, i*2)+","+Math.pow(2, j*2)+","+0+")",
      draw() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
        ctx.closePath();
        ctx.fillStyle = this.color;
        ctx.fill();
      },
      recalc(fn, an) {
        xn = this.f * Math.cos(this.a) + fn * Math.cos(an);
        yn = this.f * Math.sin(this.a) + fn * Math.sin(an);
        this.f = Math.sqrt(xn * xn + yn * yn);
        this.a = Math.atan2(yn, xn);
      },
    });
  }
}

function dist(el1, el2) {
  return Math.sqrt(Math.pow(el1.x - el2.x, 2) + Math.pow(el1.y - el2.y, 2));
}

function angle(el1, el2) {
  return Math.PI + Math.atan2(el1.y - el2.y, el1.x - el2.x);
}


function draw() {
  ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);

  for (const ball of balls) {
    for (const ball2 of balls) {
      if (ball != ball2) {
        var d = dist(ball, ball2);
        if (d > 100) {
          var f = G / d;
          var a = angle(ball, ball2);

          ball.recalc(f, a);
        }
      }
    }
  }

  for (const ball of balls) {
    ball.x += ball.f * Math.cos(ball.a);
    ball.y += ball.f * Math.sin(ball.a);
    ball.draw();
  }

  setTimeout(function() {
    raf = window.requestAnimationFrame(draw);

  }, 10);


}

raf = window.requestAnimationFrame(draw);

ball.draw();