// Visual effects: particles, cursor, matrix rain, etc. import { DOM } from './dom.js'; // Particle class for managing individual particles class Particle { constructor(x, y) { this.x = x; this.y = y; this.size = Math.random() * 3 + 1; this.speedY = Math.random() * 1 + 0.5; this.speedX = (Math.random() - 0.5) * 0.5; this.opacity = 1; } update() { this.y += this.speedY; this.x += this.speedX; this.opacity -= 0.01; } draw(ctx) { ctx.fillStyle = `rgba(0, 122, 204, ${this.opacity})`; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); } } // Add mouse trail effect with falling particles export function addMouseTrail() { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); document.body.appendChild(canvas); canvas.style.position = 'fixed'; canvas.style.top = '0'; canvas.style.left = '0'; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = '1000'; function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resizeCanvas); resizeCanvas(); let particles = []; let mouseX = 0; let mouseY = 0; document.addEventListener('mousemove', (e) => { mouseX = e.clientX; mouseY = e.clientY; if (Math.random() > 0.5) { particles.push(new Particle(mouseX, mouseY)); } }); function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); particles = particles.filter((particle) => { particle.update(); particle.draw(ctx); return ( particle.opacity > 0 && particle.y < canvas.height && particle.x > 0 && particle.x < canvas.width ); }); requestAnimationFrame(animate); } animate(); } // Matrix Rain Effect export function addMatrixRain() { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.style.position = 'fixed'; canvas.style.top = '0'; canvas.style.left = '0'; canvas.style.width = '100%'; canvas.style.height = '100%'; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = '-1'; canvas.style.opacity = '0.1'; document.body.appendChild(canvas); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const matrix = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789@#$%^&*()*&^%+-/~{[|`]}'; const matrixArray = matrix.split(''); const font_size = 10; const columns = canvas.width / font_size; const drops = []; for (let x = 0; x < columns; x++) { drops[x] = 1; } function drawMatrix() { ctx.fillStyle = 'rgba(0, 0, 0, 0.04)'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#007acc'; ctx.font = font_size + 'px arial'; for (let i = 0; i < drops.length; i++) { const text = matrixArray[Math.floor(Math.random() * matrixArray.length)]; ctx.fillText(text, i * font_size, drops[i] * font_size); if (drops[i] * font_size > canvas.height && Math.random() > 0.975) { drops[i] = 0; } drops[i]++; } } setInterval(drawMatrix, 35); window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); } // Custom Cursor export function addCustomCursor() { const cursor = document.createElement('div'); cursor.className = 'custom-cursor'; document.body.appendChild(cursor); const trail = document.createElement('div'); trail.className = 'custom-cursor-trail'; document.body.appendChild(trail); let mouseX = 0, mouseY = 0; let trailX = 0, trailY = 0; document.addEventListener('mousemove', (e) => { mouseX = e.clientX; mouseY = e.clientY; cursor.style.left = mouseX - 10 + 'px'; cursor.style.top = mouseY - 10 + 'px'; }); function animateTrail() { trailX += (mouseX - trailX) * 0.1; trailY += (mouseY - trailY) * 0.1; trail.style.left = trailX - 4 + 'px'; trail.style.top = trailY - 4 + 'px'; requestAnimationFrame(animateTrail); } animateTrail(); const interactiveElements = DOM.getAll('a, button, .avatar, .brand-name'); interactiveElements.forEach((el) => { el.addEventListener('mouseenter', () => { cursor.style.transform = 'scale(2)'; cursor.style.background = 'radial-gradient(circle, rgba(255, 107, 107, 0.8) 0%, rgba(255, 107, 107, 0.4) 50%, transparent 100%)'; }); el.addEventListener('mouseleave', () => { cursor.style.transform = 'scale(1)'; cursor.style.background = 'radial-gradient(circle, rgba(0, 122, 204, 0.8) 0%, rgba(0, 122, 204, 0.4) 50%, transparent 100%)'; }); }); } // Interactive Background export function addInteractiveBackground() { const canvas = document.createElement('canvas'); canvas.style.position = 'fixed'; canvas.style.top = '0'; canvas.style.left = '0'; canvas.style.width = '100%'; canvas.style.height = '100%'; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = '-2'; canvas.style.opacity = '0.3'; document.body.appendChild(canvas); const ctx = canvas.getContext('2d'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; const particles = []; const particleCount = 50; class BgParticle { constructor() { this.x = Math.random() * canvas.width; this.y = Math.random() * canvas.height; this.vx = (Math.random() - 0.5) * 2; this.vy = (Math.random() - 0.5) * 2; this.size = Math.random() * 3 + 1; this.opacity = Math.random() * 0.5 + 0.2; } update() { this.x += this.vx; this.y += this.vy; if (this.x < 0 || this.x > canvas.width) this.vx *= -1; if (this.y < 0 || this.y > canvas.height) this.vy *= -1; } draw() { ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fillStyle = `rgba(0, 122, 204, ${this.opacity})`; ctx.fill(); } } for (let i = 0; i < particleCount; i++) { particles.push(new BgParticle()); } function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); particles.forEach((particle) => { particle.update(); particle.draw(); }); // Draw connections particles.forEach((particle, i) => { particles.slice(i + 1).forEach((otherParticle) => { const dx = particle.x - otherParticle.x; const dy = particle.y - otherParticle.y; const distance = Math.sqrt(dx * dx + dy * dy); if (distance < 100) { ctx.beginPath(); ctx.moveTo(particle.x, particle.y); ctx.lineTo(otherParticle.x, otherParticle.y); ctx.strokeStyle = `rgba(0, 122, 204, ${0.1 * (1 - distance / 100)})`; ctx.lineWidth = 1; ctx.stroke(); } }); }); requestAnimationFrame(animate); } animate(); window.addEventListener('resize', () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); }