¡Link copiado!

Efecto de partículas de código flotante en el fondo

Animaciones | | 5 min de lectura

El efecto de partículas de código flotando en el fondo es una forma sutil pero poderosa de darle personalidad a tu sitio web, especialmente si eres desarrollador.

🎮 Pruébalo en vivo

Aquí puedes experimentar con las diferentes configuraciones del componente:

Demo interactiva

Deja vacío para usar los valores por defecto

#505050

🛠️ Cómo usar el componente

Simplemente importa y usa CodeParticles con las props que necesites:

   ---
import CodeParticles from '@/components/CodeParticles.astro'
---

<!-- Configuración por defecto -->
<CodeParticles />

<!-- Personalizado -->
<CodeParticles
	opacity={0.3}
	animationDuration={5}
	particleCount={30}
	distribution='full'
	color='#ff000050'
	customSnippets={['React', 'Vue', 'Angular', 'Svelte', 'Astro']}
/>

Props disponibles

PropTipoDefaultDescripción
opacitynumber0.2Opacidad de las partículas (0-1)
animationDurationnumber2Duración de la animación en segundos
particleCountnumber20Número de partículas a generar
distribution'margins' | 'full''margins'Distribución de partículas
colorstring'#505050'Color de las partículas
customSnippetsstring[]Ver descripciónArray de snippets personalizados

💻 El código del componente

Aquí está la implementación completa:

   ---
interface Props {
	opacity?: number
	animationDuration?: number
	particleCount?: number
	distribution?: 'margins' | 'full'
	color?: string
}

const {
	opacity = 0.2,
	animationDuration = 2,
	particleCount = 20,
	distribution = 'margins',
	color = '#50505090'
} = Astro.props
---

<div class='code-background' aria-hidden='true'></div>

<style>
	.code-background {
		position: fixed;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		z-index: 0;
		pointer-events: none;
		overflow: hidden;
	}

	@keyframes float {
		0% {
			transform: translateY(0) rotate(0deg);
		}
		100% {
			transform: translateY(-20%) rotate(2deg);
		}
	}
</style>

<script define:vars={{ opacity, animationDuration, particleCount, distribution, color }}>
	const codeBackground = document.querySelector('.code-background')
	if (codeBackground) {
		const codeSnippets = [
			'{ }',
			'[ ]',
			'( )',
			'=>',
			'const',
			'let',
			'function',
			'<div>',
			'</>',
			'import',
			'export'
		]

		const generateParticles = () => {
			codeBackground.innerHTML = ''
			const viewportWidth = window.innerWidth
			const viewportHeight = window.innerHeight

			for (let i = 0; i < particleCount; i++) {
				const particle = document.createElement('div')
				particle.textContent = codeSnippets[Math.floor(Math.random() * codeSnippets.length)]
				particle.style.position = 'fixed'
				particle.style.fontSize = Math.random() * 15 + 12 + 'px'
				particle.style.opacity = String(opacity)
				particle.style.fontFamily = 'Courier New, monospace'
				particle.style.color = color
				particle.style.animation = `float ${animationDuration}s linear infinite alternate`
				particle.style.pointerEvents = 'none'

				if (distribution === 'full') {
					particle.style.left = Math.random() * viewportWidth + 'px'
					particle.style.top = Math.random() * viewportHeight + 'px'
				} else {
					const zone = Math.floor(Math.random() * 3)
					if (zone === 0) {
						particle.style.left = Math.random() * viewportWidth + 'px'
						particle.style.top = Math.random() * (viewportHeight * 0.25) + 'px'
					} else if (zone === 1) {
						particle.style.left = Math.random() * (viewportWidth * 0.15) + 'px'
						particle.style.top = Math.random() * viewportHeight + 'px'
					} else {
						particle.style.left =
							viewportWidth * 0.85 + Math.random() * (viewportWidth * 0.15) + 'px'
						particle.style.top = Math.random() * viewportHeight + 'px'
					}
				}

				codeBackground.appendChild(particle)
			}
		}

		generateParticles()

		let resizeTimeout
		window.addEventListener('resize', () => {
			clearTimeout(resizeTimeout)
			resizeTimeout = setTimeout(generateParticles, 250)
		})
	}
</script>

✨ Por qué funciona

  1. Basado en viewport: Usa position: fixed y calcula posiciones con window.innerWidth/Height
  2. Responsive: Se regenera automáticamente al redimensionar la ventana
  3. No distrae: Las partículas están en los márgenes o donde tú elijas
  4. Configurable: Todas las props son opcionales con valores sensatos por defecto
  5. Performance: pointer-events: none asegura que no interfiera con la interacción

¡Gracias por leer!

Si te ha gustado este artículo, ¡compártelo con tus amigos y seguidores! Tu apoyo me motiva a llegar a más personas y a seguir creando contenido increíble para ti.