不会出现小球聚在光标旁边成一个圆圈的情况。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
</style>
</head>
<body style="overflow: hidden;">
<div style="width: 100%;height: 100%;overflow: hidden;">
<canvas id="bg" style="width: 100vw;height: 100vh;"
onmousemove="getMousePos()">
</canvas>
</div>
</body>
</html>
<script>
const X = 'x';
const Y = 'y';
const V_X = 'vx';
const MASS = 'm';
const MASS_MAX = 'max'
const V_Y = 'vy';
const CIRCLE = 360;
const COUNT = 300;
const COLOR_P = '#0088ff';
const COLOR_L = '#0088ff22';
const LOST = 0.6;
const DRAG = 0.01;
const MASS_LOSS = 1e-3;
const SPEED_L = 2;
const MAX_DISTANCE = 60;
const MIN_DISTANCE = 15;
const MASS_S = 30;
const MASS_L = 40;
function initFireFly() {
var ret = {
}
ret[X] = Math.random() * document.body.clientWidth;
ret[Y] = Math.random() * document.body.clientHeight;
ret[V_X] = (Math.random() - .5) * 5;
ret[V_Y] = (Math.random() - .5) * 5;
ret[MASS] = (Math.random() * .9 + .1);
ret[MASS] = (ret[MASS] > .75 ? (ret[MASS] * MASS_L) : (ret[MASS] / MASS_S));
ret[MASS_MAX] = ret[MASS]
return ret;
};
var mousePoint = {
};
var list = [];
var canvas = document.getElementById('bg');
for (var i = 0; i < COUNT; i++) {
list.push(initFireFly());
}
function getMousePos(event) {
var e = event || window.event;
var ret = {
}
ret[X] = e.offsetX;
ret[Y] = e.offsetY;
mousePoint = ret;
}
function run() {
var mouse = mousePoint;
var m = {
}
m[X] = mouse[X];
m[Y] = mouse[Y];
m[V_X] = 0;
m[V_Y] = 0;
m[MASS] = MASS_L * 2;
m[MASS_MAX] = m[MASS];
list.push(m);
for (var i = 0; i < COUNT; i++) {
list[i][X] += list[i][V_X];
list[i][Y] += list[i][V_Y];
if (list[i][X] > screen.width) {
list[i][X] -= (list[i][X] - screen.width) * 2;
list[i][V_X] *= -(1 - LOST);
} else if (list[i][X] < 0) {
list[i][X] += list[i][X] * -2;
list[i][V_X] *= -(1 - LOST);
}
if (list[i][Y] > screen.height) {
list[i][Y] -= (list[i][Y] - screen.height) * 2;
list[i][V_Y] *= -(1 - LOST);
} else if (list[i][Y] < 0) {
list[i][Y] += list[i][Y] * -2;
list[i][V_Y] *= -(1 - LOST);
}
var cont = canvas.getContext('2d');
cont.beginPath();
cont.moveTo(list[i][X], list[i][Y]);
cont.lineWidth = 1;
cont.strokeStyle = COLOR_P;
cont.lineTo(list[i][X] + 1, list[i][Y] + 1);
cont.stroke();
let neighbours = 0;
for (var i1 = 0; i1 < COUNT + 1; i1++) {
if (i1 != i) {
var r = Math.sqrt(Math.pow((list[i][X] - list[i1][X]), 2) + Math.pow((list[i][Y] - list[i1][Y]), 2));
if (r < MAX_DISTANCE) {
if (r >= MIN_DISTANCE) {
var d = r != 0 ? (list[i1][MASS] / Math.pow(r, 2)) : 0;
var dx = list[i1][X] - list[i][X];
var dy = list[i1][Y] - list[i][Y];
if (list[i][MASS] > 0) {
list[i][V_Y] += (d / r) * dy;
list[i][V_X] += (d / r) * dx;
}
}
cont.beginPath();
cont.moveTo(list[i][X], list[i][Y]);
cont.strokeStyle = COLOR_L;
cont.lineTo(list[i1][X], list[i1][Y]);
cont.stroke();
neighbours++;
}
}
}
list[i][MASS] = Math.max(Math.min(list[i][MASS_MAX], list[i][MASS] - neighbours * MASS_LOSS), 0);
if (list[i][V_Y] * list[i][V_Y] + list[i][V_X] ** list[i][V_X] > SPEED_L * SPEED_L) {
list[i][V_Y] *= 1 - DRAG;
list[i][V_X] *= 1 - DRAG;
}
cont.stroke();
}
list.splice(COUNT, 1);
}
setInterval(function () {
canvas.setAttribute('width', screen.width);
canvas.setAttribute('height', screen.height);
canvas.style.width = screen.width + 'px';
canvas.style.height = screen.height + 'px';
run();
}, 40)
</script>