<!-- tsParticles container -->
<div id="tsparticles"></div>
<!-- https://github.com/matteobruni/tsparticles -->
/* ---- reset ---- */
body {
margin: 0;
font: normal 75% Arial, Helvetica, sans-serif;
}
canvas {
display: block;
vertical-align: bottom;
}
/* ---- tsparticles container ---- */
#tsparticles {
position: absolute;
width: 100%;
height: 100%;
background-color: #0d47a1;
background-image: url("");
background-repeat: no-repeat;
background-size: cover;
background-position: 50% 50%;
}
let noiseZ;
let size;
let columns;
let rows;
let w;
let h;
let field;
function setup(container) {
size = 10;
noiseZ = 0;
reset(container);
window.addEventListener("resize", reset);
}
function initField() {
field = new Array(columns);
for (let x = 0; x < columns; x++) {
field[x] = new Array(columns);
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 = noise.simplex3(x / 50, y / 50, noiseZ) * Math.PI * 2;
let length = noise.simplex3(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;
noise.seed(Math.random());
columns = Math.floor(w / size) + 1;
rows = Math.floor(h / size) + 1;
initField();
}
tsParticles
.load("tsparticles", {
fpsLimit: 60,
emitters: {
position: {
x: 50,
y: 50
},
size: {
width: 100,
height: 100,
mode: "percent"
},
rate: {
delay: 0.1,
quantity: 20
}
},
particles: {
number: {
value: 0,
density: {
enable: false,
value_area: 800
}
},
color: {
value: ["#5bc0eb", "#fde74c", "#9bc53d", "#e55934", "#fa7921"]
},
shape: {
type: "circle",
stroke: {
width: 0,
color: "#000000"
},
polygon: {
nb_sides: 5
},
image: {
src: "https://cdn.matteobruni.it/images/particles/github.svg",
width: 100,
height: 100
}
},
opacity: {
value: 0.5,
random: false,
anim: {
enable: false,
speed: 1,
opacity_min: 0.1,
sync: false
}
},
size: {
value: 7,
random: {
enable: true,
minimumValue: 4
},
anim: {
enable: false,
speed: 40,
size_min: 0.1,
sync: false
}
},
line_linked: {
enable: false,
distance: 150,
color: "#ffffff",
opacity: 0.4,
width: 1
},
move: {
enable: true,
speed: 4,
direction: "none",
random: false,
straight: false,
out_mode: "destroy",
bounce: false,
noise: {
enable: true,
delay: {
value: 0
}
},
trail: {
enable: true,
fillColor: "#000000",
length: 20
},
attract: {
enable: false,
rotateX: 600,
rotateY: 1200
}
}
},
interactivity: {
detect_on: "canvas",
events: {
onhover: {
enable: false,
mode: "grab"
},
onclick: {
enable: false,
mode: "repulse"
},
resize: true
},
modes: {
grab: {
distance: 200,
line_linked: {
opacity: 1
}
},
bubble: {
distance: 400,
size: 40,
duration: 2,
opacity: 8,
speed: 3
},
repulse: {
distance: 200
},
push: {
particles_nb: 4
},
remove: {
particles_nb: 2
}
}
},
retina_detect: true,
pauseOnBlur: false
})
.then((container) => {
container.setNoise({
init: function () {
setup(container);
},
update: function () {
calculateField();
noiseZ += 0.004;
},
generate: function (p) {
const pos = p.getPosition();
const px = Math.max(Math.floor(pos.x / size), 0);
const py = Math.max(Math.floor(pos.y / size), 0);
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();
});
This Pen doesn't use any external CSS resources.