"> "> ">
<!-- tsParticles library -->
<script src="<https://cdn.jsdelivr.net/npm/tsparticles@2.12.0/tsparticles.bundle.min.js>"></script>
<!-- Simplex Noise library -->
<script src="<https://cdn.jsdelivr.net/npm/simplex-noise@2.4.0/simplex-noise.min.js>"></script>
let noiseGenerator = new SimplexNoise();
let noiseZ;
let size;
let columns;
let rows;
let w;
let h;
let field;
function setup(container) {
size = 20;
noiseZ = 0;
reset(container);
window.addEventListener("resize", () => reset(container));
}
function initField() {
field = new Array(columns);
for (let x = 0; x < columns; x++) {
field[x] = new Array(rows);
for (let y = 0; y < rows; y++) {
field[x][y] = [0, 0];
}
}
}
function calculateField() {
for (let x = 0; x < columns; x++) {
for (let y = 0; y < rows; y++) {
let angle = noiseGenerator.noise3D(x / 50, y / 50, noiseZ) * Math.PI * 2;
let length = noiseGenerator.noise3D(x / 100 + 40000, y / 100 + 40000, noiseZ);
field[x][y][0] = angle;
field[x][y][1] = length;
}
}
}
function reset(container) {
w = container.canvas.size.width;
h = container.canvas.size.height;
columns = Math.floor(w / size) + 1;
rows = Math.floor(h / size) + 1;
initField();
}
function drawField(ctx) {
ctx.clearRect(0, 0, w, h);
for (let x = 0; x < columns; x++) {
for (let y = 0; y < rows; y++) {
let angle = field[x][y][0];
let length = field[x][y][1];
ctx.save();
ctx.translate(x * size, y * size);
ctx.rotate(angle);
ctx.strokeStyle = "white";
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, size * length);
ctx.stroke();
ctx.restore();
}
}
}
tsParticles
.load("tsparticles", {
background: {
color: {
value: "#000"
}
},
fpsLimit: 120,
particles: {
number: {
value: 200,
density: {
enable: true,
value_area: 800
}
},
color: {
value: ["#5bc0eb", "#fde74c", "#9bc53d", "#e55934", "#fa7921"]
},
shape: {
type: "square",
stroke: {
width: 0,
color: "#000000"
}
},
opacity: {
value: 1
},
size: {
value: 5
},
line_linked: {
enable: false,
distance: 150,
color: "#ffffff",
opacity: 0.4,
width: 1
},
move: {
enable: true,
speed: 1,
direction: "none",
random: false,
straight: false,
outMode: "out",
bounce: false,
warp: true,
noise: {
enable: true,
delay: {
value: 0
}
},
trail: {
enable: false,
color: {
value: "#000"
},
length: 30
}
}
},
interactivity: {
detect_on: "canvas",
events: {
resize: true
}
},
detectRetina: true,
pauseOnBlur: true
})
.then((container) => {
container.setNoise({
init: function () {
setup(container);
},
update: function () {
calculateField();
noiseZ += 0.004;
drawField(container.canvas.element.getContext("2d"));
},
generate: function (p) {
const pos = p.getPosition();
const px = Math.min(Math.max(Math.floor(pos.x / size), 0), columns - 1);
const py = Math.min(Math.max(Math.floor(pos.y / size), 0), rows - 1);
if (!field || !field[px] || !field[px][py]) {
return { angle: 0, length: 0 };
}
return {
angle: field[px][py][0],
length: field[px][py][1]
};
}
});
container.refresh();
});