// ============================================
// FUTURISTIC CHRISTMAS - LEAFBOX TECHNOLOGIES
// JavaScript Interactions & Animations
// ============================================
// ========== CONFIGURATION ==========
const CONFIG = {
snow: {
count: 100,
maxSize: 4,
minSize: 1,
speed: 0.5
},
tree: {
particleCount: 150,
glowIntensity: 20
},
sound: {
enabled: false,
volume: 0.3
}
};
// ========== PARTICLE SNOW ANIMATION ==========
class SnowCanvas {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
this.particles = [];
this.init();
this.animate();
}
init() {
this.resize();
window.addEventListener('resize', () => this.resize());
this.createParticles();
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
}
createParticles() {
this.particles = [];
const particleCount = window.innerWidth < 768 ? 50 : CONFIG.snow.count;
for (let i = 0; i < particleCount; i++) {
this.particles.push({
x: Math.random() * this.canvas.width,
y: Math.random() * this.canvas.height,
size: Math.random() * (CONFIG.snow.maxSize - CONFIG.snow.minSize) + CONFIG.snow.minSize,
speedY: Math.random() * CONFIG.snow.speed + 0.5,
speedX: Math.random() * 0.5 - 0.25,
opacity: Math.random() * 0.5 + 0.3,
color: this.getSnowColor()
});
}
}
getSnowColor() {
const colors = ['#00E5FF', '#00FF99', '#FFFFFF'];
return colors[Math.floor(Math.random() * colors.length)];
}
animate() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.particles.forEach(particle => {
// Draw particle
this.ctx.beginPath();
this.ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
this.ctx.fillStyle = particle.color;
this.ctx.globalAlpha = particle.opacity;
this.ctx.fill();
// Add glow effect
const gradient = this.ctx.createRadialGradient(
particle.x, particle.y, 0,
particle.x, particle.y, particle.size * 2
);
gradient.addColorStop(0, particle.color);
gradient.addColorStop(1, 'transparent');
this.ctx.fillStyle = gradient;
this.ctx.globalAlpha = particle.opacity * 0.5;
this.ctx.fill();
// Update position
particle.y += particle.speedY;
particle.x += particle.speedX;
// Reset particle when it goes off screen
if (particle.y > this.canvas.height) {
particle.y = -10;
particle.x = Math.random() * this.canvas.width;
}
if (particle.x > this.canvas.width || particle.x < 0) {
particle.x = Math.random() * this.canvas.width;
}
});
this.ctx.globalAlpha = 1;
requestAnimationFrame(() => this.animate());
}
}
// ========== DIGITAL CHRISTMAS TREE ==========
class DigitalTree {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.ctx = this.canvas.getContext('2d');
this.particles = [];
this.lines = [];
this.animationProgress = 0;
this.init();
}
init() {
// Set canvas size
const size = window.innerWidth < 768 ? 300 : 400;
this.canvas.width = size;
this.canvas.height = size;
this.createTreeStructure();
this.animate();
}
createTreeStructure() {
const centerX = this.canvas.width / 2;
const baseY = this.canvas.height - 50;
const topY = 30;
const maxWidth = this.canvas.width * 0.6;
// Create tree outline with particles
for (let i = 0; i < CONFIG.tree.particleCount; i++) {
const progress = i / CONFIG.tree.particleCount;
const y = baseY - (baseY - topY) * progress;
const width = maxWidth * (1 - progress);
const x = centerX + (Math.random() - 0.5) * width;
this.particles.push({
x: x,
y: y,
targetX: x,
targetY: y,
currentX: centerX,
currentY: baseY,
size: Math.random() * 3 + 1,
color: this.getTreeColor(),
delay: Math.random() * 50,
glowSize: Math.random() * 10 + 5
});
}
// Create connecting lines
for (let i = 0; i < this.particles.length - 1; i++) {
if (Math.random() > 0.7) {
this.lines.push({
start: this.particles[i],
end: this.particles[i + 1]
});
}
}
// Add star at top
this.star = {
x: centerX,
y: topY - 20,
size: 15,
points: 5,
rotation: 0
};
// Add trunk
this.trunk = {
x: centerX,
y: baseY,
width: 20,
height: 40
};
}
getTreeColor() {
const colors = ['#00FF99', '#00E5FF', '#FFD700'];
return colors[Math.floor(Math.random() * colors.length)];
}
drawStar(x, y, size, rotation) {
this.ctx.save();
this.ctx.translate(x, y);
this.ctx.rotate(rotation);
this.ctx.beginPath();
for (let i = 0; i < 5; i++) {
const angle = (Math.PI * 2 * i) / 5 - Math.PI / 2;
const x = Math.cos(angle) * size;
const y = Math.sin(angle) * size;
if (i === 0) {
this.ctx.moveTo(x, y);
} else {
this.ctx.lineTo(x, y);
}
const innerAngle = angle + Math.PI / 5;
const innerX = Math.cos(innerAngle) * (size * 0.4);
const innerY = Math.sin(innerAngle) * (size * 0.4);
this.ctx.lineTo(innerX, innerY);
}
this.ctx.closePath();
this.ctx.fillStyle = '#FFD700';
this.ctx.fill();
// Add glow
this.ctx.shadowBlur = 20;
this.ctx.shadowColor = '#FFD700';
this.ctx.fill();
this.ctx.restore();
}
animate() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// Update animation progress
if (this.animationProgress < 1) {
this.animationProgress += 0.01;
}
// Draw connecting lines
this.lines.forEach(line => {
const startProgress = Math.min(1, this.animationProgress * 2);
const endProgress = Math.min(1, (this.animationProgress - 0.3) * 2);
if (startProgress > line.start.delay / 100) {
this.ctx.beginPath();
this.ctx.moveTo(line.start.currentX, line.start.currentY);
this.ctx.lineTo(line.end.currentX, line.end.currentY);
this.ctx.strokeStyle = 'rgba(0, 255, 153, 0.3)';
this.ctx.lineWidth = 1;
this.ctx.stroke();
}
});
// Draw and update particles
this.particles.forEach(particle => {
if (this.animationProgress > particle.delay / 100) {
// Animate to target position
const progress = Math.min(1, (this.animationProgress - particle.delay / 100) * 2);
particle.currentX = particle.currentX + (particle.targetX - particle.currentX) * progress * 0.1;
particle.currentY = particle.currentY + (particle.targetY - particle.currentY) * progress * 0.1;
// Draw particle glow
const gradient = this.ctx.createRadialGradient(
particle.currentX, particle.currentY, 0,
particle.currentX, particle.currentY, particle.glowSize
);
gradient.addColorStop(0, particle.color);
gradient.addColorStop(1, 'transparent');
this.ctx.fillStyle = gradient;
this.ctx.globalAlpha = 0.6;
this.ctx.fillRect(
particle.currentX - particle.glowSize,
particle.currentY - particle.glowSize,
particle.glowSize * 2,
particle.glowSize * 2
);
// Draw particle
this.ctx.globalAlpha = 1;
this.ctx.beginPath();
this.ctx.arc(particle.currentX, particle.currentY, particle.size, 0, Math.PI * 2);
this.ctx.fillStyle = particle.color;
this.ctx.fill();
}
});
// Draw trunk
this.ctx.fillStyle = '#374151';
this.ctx.fillRect(
this.trunk.x - this.trunk.width / 2,
this.trunk.y,
this.trunk.width,
this.trunk.height
);
// Draw star
if (this.animationProgress > 0.8) {
this.star.rotation += 0.02;
this.drawStar(this.star.x, this.star.y, this.star.size, this.star.rotation);
}
requestAnimationFrame(() => this.animate());
}
}
// ========== COUNTDOWN TIMER ==========
class CountdownTimer {
constructor() {
this.targetDate = new Date('2026-01-01T00:00:00').getTime();
this.elements = {
days: document.getElementById('days'),
hours: document.getElementById('hours'),
minutes: document.getElementById('minutes'),
seconds: document.getElementById('seconds')
};
this.update();
setInterval(() => this.update(), 1000);
}
update() {
const now = new Date().getTime();
const distance = this.targetDate - now;
if (distance < 0) {
this.displayTime(0, 0, 0, 0);
return;
}
const days = Math.floor(distance / (1000 * 60 * 60 * 24));
const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((distance % (1000 * 60)) / 1000);
this.displayTime(days, hours, minutes, seconds);
}
displayTime(days, hours, minutes, seconds) {
this.elements.days.textContent = String(days).padStart(2, '0');
this.elements.hours.textContent = String(hours).padStart(2, '0');
this.elements.minutes.textContent = String(minutes).padStart(2, '0');
this.elements.seconds.textContent = String(seconds).padStart(2, '0');
}
}
// ========== THEME TOGGLE ==========
class ThemeToggle {
constructor() {
this.button = document.getElementById('themeToggle');
this.currentTheme = localStorage.getItem('theme') || 'dark';
this.init();
}
init() {
this.applyTheme(this.currentTheme);
this.button.addEventListener('click', () => this.toggle());
}
toggle() {
this.currentTheme = this.currentTheme === 'dark' ? 'light' : 'dark';
this.applyTheme(this.currentTheme);
localStorage.setItem('theme', this.currentTheme);
}
applyTheme(theme) {
if (theme === 'light') {
document.body.classList.add('light-theme');
} else {
document.body.classList.remove('light-theme');
}
}
}
// ========== SOUND TOGGLE ==========
class SoundToggle {
constructor() {
this.button = document.getElementById('soundToggle');
this.audio = null;
this.isPlaying = false;
this.init();
}
init() {
this.button.addEventListener('click', () => this.toggle());
// Create audio context (simple chime sound using Web Audio API)
this.createAudioContext();
}
createAudioContext() {
try {
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
} catch (e) {
console.log('Web Audio API not supported');
}
}
playChime() {
if (!this.audioContext) return;
const now = this.audioContext.currentTime;
const oscillator = this.audioContext.createOscillator();
const gainNode = this.audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(this.audioContext.destination);
// Christmas bell-like sound
oscillator.frequency.setValueAtTime(800, now);
oscillator.frequency.exponentialRampToValueAtTime(400, now + 0.1);
gainNode.gain.setValueAtTime(0.3, now);
gainNode.gain.exponentialRampToValueAtTime(0.01, now + 0.5);
oscillator.start(now);
oscillator.stop(now + 0.5);
}
toggle() {
this.isPlaying = !this.isPlaying;
if (this.isPlaying) {
this.button.classList.remove('muted');
this.playChime();
// Play chime periodically
this.interval = setInterval(() => this.playChime(), 5000);
} else {
this.button.classList.add('muted');
if (this.interval) {
clearInterval(this.interval);
}
}
}
}
// ========== EASTER EGG ==========
class EasterEgg {
constructor() {
this.modal = document.getElementById('easterEggModal');
this.closeBtn = document.getElementById('modalClose');
this.trigger = document.getElementById('easterEgg');
this.privacyLink = document.getElementById('privacyLink');
this.clickCount = 0;
this.init();
}
init() {
// Easter egg on cybersecurity card
this.trigger.addEventListener('click', (e) => {
this.clickCount++;
if (this.clickCount === 3) {
this.show();
this.clickCount = 0;
}
});
// Easter egg on privacy link
this.privacyLink.addEventListener('click', (e) => {
e.preventDefault();
this.show();
});
this.closeBtn.addEventListener('click', () => this.hide());
this.modal.addEventListener('click', (e) => {
if (e.target === this.modal) {
this.hide();
}
});
// Keyboard shortcut: Ctrl+Shift+X
document.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.shiftKey && e.key === 'X') {
this.show();
}
});
}
show() {
this.modal.classList.add('active');
document.body.style.overflow = 'hidden';
}
hide() {
this.modal.classList.remove('active');
document.body.style.overflow = '';
}
}
// ========== SMOOTH SCROLL ==========
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
const href = this.getAttribute('href');
if (href === '#' || href === '#!') return;
e.preventDefault();
const target = document.querySelector(href);
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
// ========== SCROLL ANIMATIONS ==========
class ScrollAnimations {
constructor() {
this.elements = document.querySelectorAll('.timeline-item, .service-card');
this.init();
}
init() {
this.observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, {
threshold: 0.1
});
this.elements.forEach(el => {
this.observer.observe(el);
});
}
}
// ========== INTERACTIVE PARTICLES ON HOVER ==========
class InteractiveParticles {
constructor() {
this.init();
}
init() {
const serviceCards = document.querySelectorAll('.service-card');
serviceCards.forEach(card => {
card.addEventListener('mouseenter', (e) => {
this.createParticleBurst(e.currentTarget);
});
});
}
createParticleBurst(element) {
const rect = element.getBoundingClientRect();
const particles = 10;
for (let i = 0; i < particles; i++) {
const particle = document.createElement('div');
particle.style.position = 'fixed';
particle.style.left = rect.left + rect.width / 2 + 'px';
particle.style.top = rect.top + rect.height / 2 + 'px';
particle.style.width = '4px';
particle.style.height = '4px';
particle.style.borderRadius = '50%';
particle.style.background = 'var(--leaf-green)';
particle.style.pointerEvents = 'none';
particle.style.zIndex = '9999';
particle.style.boxShadow = '0 0 10px var(--leaf-green)';
document.body.appendChild(particle);
const angle = (Math.PI * 2 * i) / particles;
const velocity = 100;
const vx = Math.cos(angle) * velocity;
const vy = Math.sin(angle) * velocity;
let x = 0, y = 0;
const animate = () => {
x += vx * 0.01;
y += vy * 0.01;
particle.style.transform = `translate(${x}px, ${y}px)`;
particle.style.opacity = Math.max(0, 1 - Math.sqrt(x * x + y * y) / 100);
if (Math.sqrt(x * x + y * y) < 100) {
requestAnimationFrame(animate);
} else {
particle.remove();
}
};
animate();
}
}
}
// ========== CONTACT BUTTON INTERACTION ==========
function initContactButton() {
const contactButton = document.getElementById('contactButton');
contactButton.addEventListener('click', () => {
// Create a glowing pulse effect
const pulse = document.createElement('div');
pulse.style.position = 'fixed';
pulse.style.left = '50%';
pulse.style.top = '50%';
pulse.style.transform = 'translate(-50%, -50%)';
pulse.style.width = '0px';
pulse.style.height = '0px';
pulse.style.borderRadius = '50%';
pulse.style.border = '2px solid var(--leaf-green)';
pulse.style.pointerEvents = 'none';
pulse.style.zIndex = '9999';
document.body.appendChild(pulse);
let size = 0;
const animate = () => {
size += 20;
pulse.style.width = size + 'px';
pulse.style.height = size + 'px';
pulse.style.opacity = Math.max(0, 1 - size / 500);
if (size < 500) {
requestAnimationFrame(animate);
} else {
pulse.remove();
}
};
animate();
// Show alert
setTimeout(() => {
alert('🎄 Thank you for your interest! Our team will contact you soon.\n\nEmail: hello@leafbox.tech\nPhone: +1 (555) 123-4567');
}, 300);
});
}
// ========== CURSOR TRAIL EFFECT ==========
class CursorTrail {
constructor() {
this.trail = [];
this.maxTrail = 20;
this.init();
}
init() {
if (window.innerWidth < 768) return; // Disable on mobile
document.addEventListener('mousemove', (e) => {
this.trail.push({
x: e.clientX,
y: e.clientY,
timestamp: Date.now()
});
if (this.trail.length > this.maxTrail) {
this.trail.shift();
}
this.render();
});
}
render() {
// Remove old trail elements
document.querySelectorAll('.cursor-trail').forEach(el => {
if (Date.now() - parseInt(el.dataset.timestamp) > 500) {
el.remove();
}
});
// Create new trail element
if (this.trail.length > 0) {
const last = this.trail[this.trail.length - 1];
const trail = document.createElement('div');
trail.className = 'cursor-trail';
trail.style.position = 'fixed';
trail.style.left = last.x + 'px';
trail.style.top = last.y + 'px';
trail.style.width = '6px';
trail.style.height = '6px';
trail.style.borderRadius = '50%';
trail.style.background = 'var(--ice-blue)';
trail.style.pointerEvents = 'none';
trail.style.zIndex = '9998';
trail.style.boxShadow = '0 0 10px var(--ice-blue)';
trail.style.opacity = '0.6';
trail.style.transform = 'translate(-50%, -50%)';
trail.style.transition = 'opacity 0.5s ease-out';
trail.dataset.timestamp = last.timestamp;
document.body.appendChild(trail);
setTimeout(() => {
trail.style.opacity = '0';
}, 10);
}
}
}
// ========== INITIALIZE ALL ==========
document.addEventListener('DOMContentLoaded', () => {
console.log('🎄 LeafBox Technologies - Merry Christmas! 🎄');
console.log('Where technology meets the magic of Christmas ✨');
// Initialize all components
const snowCanvas = new SnowCanvas('snowCanvas');
const digitalTree = new DigitalTree('treeCanvas');
const countdown = new CountdownTimer();
const themeToggle = new ThemeToggle();
const soundToggle = new SoundToggle();
const easterEgg = new EasterEgg();
const scrollAnimations = new ScrollAnimations();
const interactiveParticles = new InteractiveParticles();
const cursorTrail = new CursorTrail();
initSmoothScroll();
initContactButton();
// Log easter egg hint
console.log('💡 Hint: Try clicking the Cybersecurity card 3 times... 🎁');
console.log('💡 Or use the keyboard shortcut: Ctrl+Shift+X');
});
// ========== PERFORMANCE OPTIMIZATION ==========
// Reduce animations on low-end devices
if (navigator.hardwareConcurrency < 4) {
CONFIG.snow.count = 50;
CONFIG.tree.particleCount = 100;
}
// Pause animations when tab is not visible
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
// Pause non-essential animations
console.log('Tab hidden - pausing animations');
} else {
console.log('Tab visible - resuming animations');
}
});