<canvas id="canvas" width="800" height="800"></canvas>
<div>
<label for="slid">tails</label>
<input id="slid" type="range" min="0" max="50" value="4" onchange="changeTails(this.value)" oninput="changeTails(this.value)" />
<button onclick="restart()">restart</button>
</div>
#canvas {
width: 400px;
height: 400px;
}
body {
font-family: sans-serif;
color: #fff;
background-color: #000;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
div > * {
display: block;
text-align: center;
margin: 0 auto;
}
div > *:not(first-child) {
margin-top: 8px;
}
div {
margin-left: 20px;
}
const force = 2;
const minDistance = 100;
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");
const cols = 30;
const rows = cols * canvas.height / canvas.width;
const squareSize = canvas.width / cols;
const Dot = function(x, y) {
this.x = x;
this.y = y;
this.dx = 0;
this.dy = 0;
};
let dots;
const initDots = () => {
dots = [];
for (let i = 0; i <= cols; i += 2) {
for (let j = 0; j <= rows; j += 2) {
const dot = new Dot(i * squareSize, j * squareSize);
dots.push(dot);
}
}
};
initDots();
function rotate(p1, c, deg) {
const dx = p1.x - c.x;
const dy = p1.y - c.y;
const ang = Math.atan(dy / dx) + deg;
const hyp = Math.sqrt(Math.pow(Math.abs(dx), 2) + Math.pow(Math.abs(dy), 2));
return {
x: c.x + hyp * Math.cos(ang),
y: c.y + hyp * Math.sin(ang)
};
}
requestAnimationFrame(function() {
frame(context, 0, rotate);
});
context.strokeStyle = "#fff";
context.fillStyle = "rgba(0,0,0,0.046)";
let firstCount = 0;
function frame(context, val, func) {
let i;
for (i = 0; i < dots.length; i++) {
for (let j = i + 1; j < dots.length; j++) {
let dist = Math.sqrt(
Math.pow(dots[j].x - dots[i].x, 2) + Math.pow(dots[j].y - dots[i].y, 2)
);
dist = Math.max(minDistance, dist);
const dist3 = force / (dist * dist * dist);
const dx = (dots[j].x - dots[i].x) * dist3;
const dy = (dots[j].y - dots[i].y) * dist3;
dots[i].dx += dx;
dots[i].dy += dy;
dots[j].dx -= dx;
dots[j].dy -= dy;
}
}
context.fillRect(0, 0, canvas.width, canvas.height);
for (i = 0; i < dots.length; i++) {
const dot = dots[i];
dot.x += dot.dx;
dot.y += dot.dy;
context.beginPath();
context.arc(dot.x, dot.y, 0.75, 0, 2 * Math.PI);
context.stroke();
}
window.requestAnimationFrame(function() {
frame(context, val + 0.1, func);
});
}
const changeTails = v => {
context.fillStyle = `rgba(0,0,0,${0.05 - 0.001 * v})`;
};
const restart = () => {
const fs = context.fillStyle;
context.fillStyle = "#000";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = fs;
initDots();
};
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.