JSFiddle - React, Tailwind, and code Playground

HTML

<canvas width="250" height="250"></canvas>

CSS

*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background: #331232;
  min-height: 100vh;
  display: grid;
  place-items: center;
}

canvas {
  background: black;
  border: 2px solid #abcdef;
  border-radius: 100%;
}

JavaScript

const canvas = document.querySelector("canvas");
    
    function map(value, start1, end1, start2, end2) {
        return start2 + ((end2 - start2) * (value - start1)) / (end1 - start1);
    }

    function loading_icon(canvas) {
        const color = -Date.now() / 5;
        const dt = Date.now() / 100;
        const circles = 25;
        const distance = 60;
        const angleInc = (Math.PI * 2) / circles;
        const minRad = 1;
        const maxRad = 7;
        const context = canvas.getContext("2d");
        let angle;

        angle = 0;

        context.clearRect(0, 0, canvas.width, canvas.height);
        for (let i = 0; i < circles; i++, angle += angleInc) {
            const radius =
                minRad +
                Math.abs(
                    maxRad *
                        Math.sin(
                            map(dt % circles, 0, circles, 0, Math.PI * 2) +
                                (i * Math.PI * 3) / circles
                        )
                );
            context.beginPath();
            context.fillStyle = `hsl(${(i * 10 + color) % 360}, 100%, 65%)`;
            context.arc(
                distance * Math.cos(angle) + canvas.width / 2,
                distance * Math.sin(angle) + canvas.height / 2,
                radius,
                0,
                Math.PI * 2
            );
            context.fill();
        }

        requestAnimationFrame(() => loading_icon(canvas));
    }
    
    loading_icon(canvas);