Guía de JavaScript Vanilla
Tabla de Contenidos
- Comenzando
- Partículas Básicas
- Efecto de Confeti
- Efecto de Fuegos Artificiales
- Efecto de Cintas
- Efecto de Nieve
- Efecto de Red / Conexiones
- Efecto de Estrellas
- Configuración Personalizada
- Múltiples Contenedores
- Controles Dinámicos
Comenzando
CDN (inicio rápido)
Agrega un <div> como marcador de posición y etiquetas de script en tu HTML. Necesitas al menos el motor + un bundle, y debes llamar al cargador antes de tsParticles.load().
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>tsParticles – Getting Started</title>
<style>
#tsparticles {
position: fixed;
inset: 0;
z-index: 0;
}
</style>
</head>
<body>
<div id="tsparticles"></div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: {
/* ... */
},
});
})();
</script>
</body>
</html>npm
npm install @tsparticles/engine @tsparticles/slimLuego impórtalo y úsalo:
import { tsParticles } from "@tsparticles/engine";
import { loadSlim } from "@tsparticles/slim";
(async () => {
await loadSlim(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: {
/* ... */
},
});
})();Nota:
@tsparticles/enginepor sí solo no dibuja nada. Debes instalar un bundle (@tsparticles/slimrecomendado) o plugins individuales para obtener formas visibles.
Partículas Básicas
Una configuración mínima que renderiza 100 partículas con forma circular, colores aleatorios y movimiento suave. En v4, los colores de las partículas se configuran mediante paint en lugar de la antigua propiedad color.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Basic Particles</title>
<style>
#tsparticles {
position: fixed;
inset: 0;
z-index: 0;
}
body {
margin: 0;
}
</style>
</head>
<body>
<div id="tsparticles"></div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: {
fpsLimit: 120,
particles: {
number: { value: 100 },
paint: [
{
fill: { color: { value: "#ff0000" }, enable: true },
},
{
fill: { color: { value: "#00ff00" }, enable: true },
},
{
fill: { color: { value: "#0000ff" }, enable: true },
},
{
fill: { color: { value: "#ffff00" }, enable: true },
},
{
fill: { color: { value: "#ff00ff" }, enable: true },
},
],
shape: { type: "circle" },
opacity: {
value: { min: 0.3, max: 0.8 },
},
size: {
value: { min: 2, max: 6 },
},
move: {
enable: true,
speed: 2,
direction: "none",
random: true,
straight: false,
outModes: { default: "bounce" },
},
},
background: { color: "#1a1a2e" },
},
});
})();
</script>
</body>
</html>Efecto de Confeti
Usa el bundle dedicado @tsparticles/confetti para una explosión festiva con una sola llamada a una función.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Confetti</title>
<style>
body {
margin: 0;
background: #000;
}
</style>
</head>
<body>
<canvas id="confetti"></canvas>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/confetti@4/tsparticles.confetti.bundle.min.js"></script>
<script>
confetti({
particleCount: 100,
spread: 70,
origin: { x: 0.5, y: 0.5 },
});
</script>
</body>
</html>Efecto de Fuegos Artificiales
Un espectáculo de fuegos artificiales usando el bundle dedicado @tsparticles/fireworks con efectos de sonido.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Fireworks</title>
<style>
body {
margin: 0;
background: #000;
}
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/fireworks@4/tsparticles.fireworks.bundle.min.js"></script>
<script>
fireworks({
colors: ["#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff", "#00ffff"],
sounds: true,
});
</script>
</body>
</html>Efecto de Cintas
Usa el bundle dedicado @tsparticles/ribbons para animaciones de cintas fluidas que reaccionan a la posición del ratón.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Ribbons</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #000;
}
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/ribbons@4/tsparticles.ribbons.bundle.min.js"></script>
<script>
ribbons({
ribbonOptions: {
count: 30,
angle: 45,
oscillationSpeed: 3,
oscillationDistance: 40,
particleDist: 8,
},
});
</script>
</body>
</html>Efecto de Nieve
Suaves copos de nieve cayendo usando el catálogo de presets @tsparticles/configs.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Snow Effect</title>
<style>
#tsparticles {
position: fixed;
inset: 0;
z-index: 0;
}
body {
margin: 0;
background: #1a1a2e;
}
</style>
</head>
<body>
<div id="tsparticles"></div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/configs@4/tsparticles.configs.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: {
preset: "snow",
},
});
})();
</script>
</body>
</html>Alternativamente, usando el paquete de preset independiente:
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/basic@4/tsparticles.basic.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/preset-snow@4/tsparticles.preset.snow.min.js"></script>
<script>
(async () => {
await loadBasic(tsParticles);
await loadSnowPreset(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: { preset: "snow" },
});
})();
</script>Efecto de Red / Conexiones
Un visual clásico de nodos conectados con interactividad del ratón. El bundle @tsparticles/slim incluye la interacción de conexiones y el modo de agarre con el ratón.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Network / Links</title>
<style>
#tsparticles {
position: fixed;
inset: 0;
z-index: 0;
}
body {
margin: 0;
}
</style>
</head>
<body>
<div id="tsparticles"></div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: {
fpsLimit: 60,
particles: {
number: { value: 80, density: { enable: true } },
paint: {
color: "#00d4ff",
},
shape: { type: "circle" },
opacity: { value: 0.6 },
size: { value: { min: 1, max: 4 } },
links: {
enable: true,
distance: 150,
color: "#00d4ff",
opacity: 0.4,
width: 1,
},
move: {
enable: true,
speed: 1.5,
direction: "none",
random: true,
outModes: { default: "bounce" },
},
},
interactivity: {
events: {
onHover: { enable: true, mode: "grab" },
onClick: { enable: true, mode: "push" },
},
modes: {
grab: { distance: 180, links: { opacity: 0.8 } },
push: { quantity: 4 },
},
},
background: { color: "#0d1117" },
},
});
})();
</script>
</body>
</html>Efecto de Estrellas
Un cielo nocturno estrellado usando el catálogo de presets @tsparticles/configs.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Stars Effect</title>
<style>
#tsparticles {
position: fixed;
inset: 0;
z-index: 0;
}
body {
margin: 0;
background: #000;
}
</style>
</head>
<body>
<div id="tsparticles"></div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/configs@4/tsparticles.configs.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: {
preset: "star",
},
});
})();
</script>
</body>
</html>Alternativamente, usando el paquete de preset independiente:
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/preset-stars@4/tsparticles.preset.stars.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
await loadStarsPreset(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: { preset: "stars" },
});
})();
</script>Configuración Personalizada
Construye una configuración desde cero con un fondo degradado, efectos interactivos al pasar el ratón y múltiples tipos de formas usando el bundle slim.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Custom Config</title>
<style>
#tsparticles {
position: fixed;
inset: 0;
z-index: 0;
}
body {
margin: 0;
font-family: sans-serif;
}
h1 {
position: relative;
z-index: 1;
color: #fff;
text-align: center;
padding-top: 2rem;
}
</style>
</head>
<body>
<h1>Configuración Personalizada</h1>
<div id="tsparticles"></div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
await tsParticles.load({
id: "tsparticles",
options: {
fullScreen: { enable: true, zIndex: 0 },
fpsLimit: 60,
particles: {
number: { value: 60, density: { enable: true, width: 800, height: 800 } },
paint: [
{
fill: { color: { value: "#ff6b6b" }, enable: true },
},
{
fill: { color: { value: "#feca57" }, enable: true },
},
{
fill: { color: { value: "#48dbfb" }, enable: true },
},
{
fill: { color: { value: "#ff9ff3" }, enable: true },
},
{
fill: { color: { value: "#54a0ff" }, enable: true },
},
],
shape: {
type: ["circle", "triangle", "polygon"],
options: {
polygon: { sides: 6 },
},
},
opacity: { value: { min: 0.4, max: 0.8 } },
size: { value: { min: 3, max: 8 } },
links: {
enable: true,
distance: 200,
color: "#ffffff",
opacity: 0.15,
width: 1,
},
move: {
enable: true,
speed: 2,
direction: "none",
random: true,
straight: false,
outModes: { default: "out" },
attract: { enable: false },
},
},
interactivity: {
events: {
onHover: { enable: true, mode: "attract" },
onClick: { enable: true, mode: "repulse" },
},
modes: {
attract: { distance: 200, duration: 0.4, factor: 1 },
repulse: { distance: 200, duration: 0.4 },
},
},
background: {
color: "#0f0f23",
opacity: 1,
},
themes: [
{
name: "light",
default: { value: false },
options: {
background: { color: "#f0f0f5" },
particles: {
paint: [
{
fill: { color: { value: "#e74c3c" }, enable: true },
},
{
fill: { color: { value: "#2ecc71" }, enable: true },
},
{
fill: { color: { value: "#3498db" }, enable: true },
},
{
fill: { color: { value: "#f1c40f" }, enable: true },
},
],
links: { color: "#333333", opacity: 0.2 },
opacity: { value: { min: 0.5, max: 0.9 } },
},
},
},
],
},
});
})();
</script>
</body>
</html>Múltiples Contenedores
Ejecuta múltiples instancias de partículas independientes en la misma página, cada una con su propia configuración.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Multiple Containers</title>
<style>
.particle-box {
width: 45%;
height: 300px;
float: left;
margin: 1%;
border-radius: 12px;
overflow: hidden;
position: relative;
}
body {
margin: 0;
background: #1a1a2e;
display: flex;
flex-wrap: wrap;
height: 100vh;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div class="particle-box" id="box1"></div>
<div class="particle-box" id="box2"></div>
<div class="particle-box" id="box3"></div>
<div class="particle-box" id="box4"></div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
// Contenedor 1 – círculos con movimiento lento
await tsParticles.load({
id: "box1",
options: {
particles: {
number: { value: 40 },
paint: {
color: "#ff6b6b",
},
shape: { type: "circle" },
opacity: { value: 0.7 },
size: { value: { min: 2, max: 5 } },
move: { enable: true, speed: 1, outModes: { default: "bounce" } },
},
background: { color: "#2d2d44" },
},
});
// Contenedor 2 – triángulos con conexiones
await tsParticles.load({
id: "box2",
options: {
particles: {
number: { value: 30 },
paint: {
color: "#48dbfb",
},
shape: { type: "triangle" },
opacity: { value: 0.6 },
size: { value: { min: 3, max: 7 } },
links: { enable: true, distance: 120, color: "#48dbfb", opacity: 0.3 },
move: { enable: true, speed: 0.8, outModes: { default: "bounce" } },
},
background: { color: "#1a1a2e" },
},
});
// Contenedor 3 – explosión tipo confeti
await tsParticles.load({
id: "box3",
options: {
particles: {
number: { value: 50 },
paint: [
{
fill: { color: { value: "#feca57" }, enable: true },
},
{
fill: { color: { value: "#ff9ff3" }, enable: true },
},
{
fill: { color: { value: "#54a0ff" }, enable: true },
},
{
fill: { color: { value: "#5f27cd" }, enable: true },
},
],
shape: { type: ["circle", "square"] },
opacity: { value: 0.8 },
size: { value: { min: 2, max: 6 } },
move: {
enable: true,
speed: 3,
direction: "top",
outModes: { default: "destroy" },
},
},
background: { color: "#222f3e" },
},
});
// Contenedor 4 – estrellas flotantes lentas
await tsParticles.load({
id: "box4",
options: {
particles: {
number: { value: 20 },
paint: {
color: "#ffffff",
},
shape: { type: "star" },
opacity: { value: { min: 0.2, max: 0.8 } },
size: { value: { min: 1, max: 4 } },
move: { enable: true, speed: 0.4, direction: "none", outModes: { default: "bounce" } },
},
background: { color: "#0d1117" },
},
});
})();
</script>
</body>
</html>Controles Dinámicos
Inicia, detén, pausa y cambia temas programáticamente en tiempo de ejecución.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Dynamic Controls</title>
<style>
#tsparticles {
position: fixed;
inset: 0;
z-index: 0;
}
.controls {
position: fixed;
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
z-index: 10;
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
justify-content: center;
}
.controls button {
padding: 0.5rem 1rem;
border: none;
border-radius: 6px;
background: #222;
color: #fff;
cursor: pointer;
font-size: 0.9rem;
transition: background 0.2s;
}
.controls button:hover {
background: #444;
}
body {
margin: 0;
}
</style>
</head>
<body>
<div id="tsparticles"></div>
<div class="controls">
<button id="play-btn">▶ Reproducir</button>
<button id="pause-btn">⏸ Pausa</button>
<button id="stop-btn">⏹ Detener</button>
<button id="theme-dark-btn">🌙 Tema Oscuro</button>
<button id="theme-light-btn">☀️ Tema Claro</button>
<button id="restart-btn">🔄 Reiniciar</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/engine@4/tsparticles.engine.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@tsparticles/slim@4/tsparticles.slim.bundle.min.js"></script>
<script>
(async () => {
await loadSlim(tsParticles);
const container = await tsParticles.load({
id: "tsparticles",
options: {
fpsLimit: 60,
particles: {
number: { value: 80 },
paint: {
color: "#00d4ff",
},
shape: { type: "circle" },
opacity: { value: 0.6 },
size: { value: { min: 2, max: 5 } },
links: { enable: true, distance: 150, color: "#00d4ff", opacity: 0.3 },
move: { enable: true, speed: 1.5, outModes: { default: "bounce" } },
},
background: { color: "#0d1117" },
themes: [
{
name: "light",
default: { value: false },
options: {
background: { color: "#f5f5f5" },
particles: {
paint: {
color: "#e74c3c",
},
links: { color: "#333333" },
},
},
},
],
},
});
document.getElementById("play-btn").addEventListener("click", () => container.play());
document.getElementById("pause-btn").addEventListener("click", () => container.pause());
document.getElementById("stop-btn").addEventListener("click", () => container.stop());
document.getElementById("restart-btn").addEventListener("click", async () => {
await container.destroy();
tsParticles.load({ id: "tsparticles", options: container.options });
});
document.getElementById("theme-dark-btn").addEventListener("click", () => {
container.loadTheme("default");
});
document.getElementById("theme-light-btn").addEventListener("click", () => {
container.loadTheme("light");
});
})();
</script>
</body>
</html>Ahora has cubierto todos los patrones principales de integración de JavaScript Vanilla para tsParticles v4. Cada ejemplo es un archivo HTML independiente que puedes abrir en tu navegador para ver tsParticles en acción.
