UNPKG

suryajs-animfx

Version:

SuryaJS - A powerful JavaScript animation library with 20+ image, text, and advanced 3D effects

576 lines (456 loc) 18.3 kB
class AdvancedEffects { constructor() { this.mouseFollowers = new Map(); this.mouseMagnets = new Map(); this.isMouseTracking = false; this.mousePosition = { x: 0, y: 0 }; this.init(); } init() { // Initialize mouse tracking this.initMouseTracking(); } initMouseTracking() { if (!this.isMouseTracking) { document.addEventListener('mousemove', (e) => { this.mousePosition.x = e.clientX; this.mousePosition.y = e.clientY; this.updateMouseFollowers(); this.updateMouseMagnets(); }); this.isMouseTracking = true; } } // Effect 6: Mouse Follower mouseFollower(elements, options = {}) { const speed = options.speed || 0.1; const distance = options.distance || 50; const scale = options.scale || 1.2; elements.forEach((element, index) => { if (!element) return; // Create follower element const follower = document.createElement('div'); follower.style.position = 'fixed'; follower.style.width = '20px'; follower.style.height = '20px'; follower.style.background = options.color || '#667eea'; follower.style.borderRadius = '50%'; follower.style.pointerEvents = 'none'; follower.style.zIndex = '9999'; follower.style.transition = 'all 0.1s ease'; follower.style.opacity = '0.8'; follower.style.boxShadow = '0 0 20px rgba(102, 126, 234, 0.5)'; document.body.appendChild(follower); // Store follower reference this.mouseFollowers.set(element, { follower: follower, speed: speed, distance: distance + (index * 10), targetX: 0, targetY: 0, currentX: 0, currentY: 0 }); // Add hover effects to original element element.addEventListener('mouseenter', () => { element.style.transform = `scale(${scale})`; element.style.transition = 'transform 0.3s ease'; follower.style.transform = 'scale(1.5)'; follower.style.background = options.hoverColor || '#e17055'; }); element.addEventListener('mouseleave', () => { element.style.transform = 'scale(1)'; follower.style.transform = 'scale(1)'; follower.style.background = options.color || '#667eea'; }); }); } // Effect 7: Mouse Magnet mouseMagnet(elements, options = {}) { const strength = options.strength || 0.3; const distance = options.distance || 100; elements.forEach((element, index) => { if (!element) return; element.style.transition = 'transform 0.3s ease'; this.mouseMagnets.set(element, { strength: strength, distance: distance, originalX: 0, originalY: 0 }); // Store original position const rect = element.getBoundingClientRect(); const magnetData = this.mouseMagnets.get(element); magnetData.originalX = rect.left + rect.width / 2; magnetData.originalY = rect.top + rect.height / 2; }); } // Effect 8: 3D Tilt tilt3D(elements, options = {}) { const maxTilt = options.maxTilt || 15; const perspective = options.perspective || 1000; const scale = options.scale || 1.05; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.transition = 'transform 0.3s ease'; element.addEventListener('mouseenter', () => { element.style.transform = `perspective(${perspective}px) scale(${scale})`; }); element.addEventListener('mousemove', (e) => { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const deltaX = (e.clientX - centerX) / (rect.width / 2); const deltaY = (e.clientY - centerY) / (rect.height / 2); const rotateX = deltaY * maxTilt; const rotateY = deltaX * maxTilt; element.style.transform = `perspective(${perspective}px) scale(${scale}) rotateX(${-rotateX}deg) rotateY(${rotateY}deg)`; }); element.addEventListener('mouseleave', () => { element.style.transform = 'perspective(1000px) scale(1) rotateX(0deg) rotateY(0deg)'; }); }); } // Effect 9: Parallax 3D parallax3D(elements, options = {}) { const depth = options.depth || 0.5; const speed = options.speed || 0.1; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.transition = 'transform 0.1s ease'; const layerDepth = depth * (index + 1); element.addEventListener('mousemove', (e) => { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const deltaX = (e.clientX - centerX) * speed * layerDepth; const deltaY = (e.clientY - centerY) * speed * layerDepth; element.style.transform = `translate3d(${deltaX}px, ${deltaY}px, ${layerDepth * 10}px)`; }); element.addEventListener('mouseleave', () => { element.style.transform = 'translate3d(0px, 0px, 0px)'; }); }); } // Effect 10: Magnetic Pull magneticPull(elements, options = {}) { const pullStrength = options.pullStrength || 0.4; const pullDistance = options.pullDistance || 80; elements.forEach((element, index) => { if (!element) return; element.style.transition = 'transform 0.2s ease'; document.addEventListener('mousemove', (e) => { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const distance = Math.sqrt( Math.pow(e.clientX - centerX, 2) + Math.pow(e.clientY - centerY, 2) ); if (distance < pullDistance) { const force = (pullDistance - distance) / pullDistance; const deltaX = (e.clientX - centerX) * force * pullStrength; const deltaY = (e.clientY - centerY) * force * pullStrength; element.style.transform = `translate(${deltaX}px, ${deltaY}px) scale(${1 + force * 0.1})`; } else { element.style.transform = 'translate(0px, 0px) scale(1)'; } }); }); } // Update mouse followers updateMouseFollowers() { this.mouseFollowers.forEach((data, element) => { const { follower, speed, distance } = data; data.targetX = this.mousePosition.x - distance; data.targetY = this.mousePosition.y - distance; data.currentX += (data.targetX - data.currentX) * speed; data.currentY += (data.targetY - data.currentY) * speed; follower.style.left = data.currentX + 'px'; follower.style.top = data.currentY + 'px'; }); } // Update mouse magnets updateMouseMagnets() { this.mouseMagnets.forEach((data, element) => { const { strength, distance } = data; const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const deltaX = this.mousePosition.x - centerX; const deltaY = this.mousePosition.y - centerY; const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (dist < distance) { const force = (distance - dist) / distance; const moveX = deltaX * force * strength; const moveY = deltaY * force * strength; element.style.transform = `translate(${moveX}px, ${moveY}px) scale(${1 + force * 0.1})`; } else { element.style.transform = 'translate(0px, 0px) scale(1)'; } }); } // Effect 11: Liquid Distortion liquidDistortion(elements, options = {}) { const intensity = options.intensity || 20; const speed = options.speed || 0.02; elements.forEach((element, index) => { if (!element) return; let animationId; let startTime = Date.now(); const animate = () => { const elapsed = Date.now() - startTime; const wave1 = Math.sin(elapsed * speed) * intensity; const wave2 = Math.cos(elapsed * speed * 1.5) * intensity * 0.5; element.style.transform = `skew(${wave1 * 0.1}deg, ${wave2 * 0.1}deg) scale(${1 + Math.sin(elapsed * speed * 0.5) * 0.05})`; element.style.filter = `hue-rotate(${wave1 * 2}deg)`; animationId = requestAnimationFrame(animate); }; element.addEventListener('mouseenter', () => { animate(); }); element.addEventListener('mouseleave', () => { if (animationId) { cancelAnimationFrame(animationId); } element.style.transform = 'none'; element.style.filter = 'none'; }); }); } // Effect 12: Floating Animation floatingAnimation(elements, options = {}) { const amplitude = options.amplitude || 10; const speed = options.speed || 0.02; elements.forEach((element, index) => { if (!element) return; const startTime = Date.now() + (index * 1000); // Stagger start times const animate = () => { const elapsed = Date.now() - startTime; const y = Math.sin(elapsed * speed) * amplitude; const rotation = Math.sin(elapsed * speed * 0.5) * 2; element.style.transform = `translateY(${y}px) rotate(${rotation}deg)`; requestAnimationFrame(animate); }; animate(); }); } // Effect 13: Morphing Shape morphingShape(elements, options = {}) { const morphSteps = options.morphSteps || [ 'border-radius: 50%', 'border-radius: 0% 50% 50% 50%', 'border-radius: 50% 0% 50% 50%', 'border-radius: 50% 50% 0% 50%', 'border-radius: 50% 50% 50% 0%', 'border-radius: 0%' ]; const duration = options.duration || 3000; elements.forEach((element, index) => { if (!element) return; let currentStep = 0; const morph = () => { element.style.cssText += morphSteps[currentStep]; element.style.transition = 'all 0.5s ease'; currentStep = (currentStep + 1) % morphSteps.length; setTimeout(morph, duration / morphSteps.length); }; setTimeout(() => { morph(); }, index * 500); }); } // Effect 14: 3D Card Flip card3DFlip(elements, options = {}) { const perspective = options.perspective || 1000; const duration = options.duration || 800; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.perspective = perspective + 'px'; element.style.cursor = 'pointer'; element.addEventListener('click', () => { const isFlipped = element.classList.contains('flipped-3d'); if (!isFlipped) { element.style.transition = `transform ${duration}ms ease`; element.style.transform = 'rotateY(180deg)'; element.classList.add('flipped-3d'); } else { element.style.transform = 'rotateY(0deg)'; element.classList.remove('flipped-3d'); } }); }); } // Effect 15: 3D Cube Rotation cube3DRotation(elements, options = {}) { const speed = options.speed || 0.02; const amplitude = options.amplitude || 15; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.perspective = '1000px'; let animationId; let startTime = Date.now() + (index * 1000); const animate = () => { const elapsed = Date.now() - startTime; const rotateX = Math.sin(elapsed * speed) * amplitude; const rotateY = Math.cos(elapsed * speed * 0.7) * amplitude; const rotateZ = Math.sin(elapsed * speed * 0.5) * (amplitude * 0.5); element.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`; animationId = requestAnimationFrame(animate); }; element.addEventListener('mouseenter', () => { animate(); }); element.addEventListener('mouseleave', () => { if (animationId) { cancelAnimationFrame(animationId); } element.style.transform = 'perspective(1000px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)'; }); }); } // Effect 16: 3D Depth Layers depth3DLayers(elements, options = {}) { const maxDepth = options.maxDepth || 100; const sensitivity = options.sensitivity || 0.1; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.transition = 'transform 0.2s ease'; const depth = (index + 1) * 20; element.addEventListener('mousemove', (e) => { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const deltaX = (e.clientX - centerX) * sensitivity; const deltaY = (e.clientY - centerY) * sensitivity; element.style.transform = ` perspective(1000px) translate3d(${deltaX}px, ${deltaY}px, ${depth}px) rotateX(${-deltaY * 0.1}deg) rotateY(${deltaX * 0.1}deg) `; }); element.addEventListener('mouseleave', () => { element.style.transform = `perspective(1000px) translate3d(0px, 0px, 0px) rotateX(0deg) rotateY(0deg)`; }); }); } // Effect 17: 3D Hover Lift hover3DLift(elements, options = {}) { const liftHeight = options.liftHeight || 50; const tiltAngle = options.tiltAngle || 10; const scale = options.scale || 1.05; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.transition = 'all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)'; element.style.cursor = 'pointer'; element.addEventListener('mouseenter', (e) => { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const deltaX = (e.clientX - centerX) / (rect.width / 2); const deltaY = (e.clientY - centerY) / (rect.height / 2); const rotateX = deltaY * tiltAngle; const rotateY = deltaX * tiltAngle; element.style.transform = ` perspective(1000px) translate3d(0px, -${liftHeight}px, 0px) rotateX(${-rotateX}deg) rotateY(${rotateY}deg) scale3d(${scale}, ${scale}, ${scale}) `; }); element.addEventListener('mouseleave', () => { element.style.transform = 'perspective(1000px) translate3d(0px, 0px, 0px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)'; }); }); } // Effect 18: 3D Perspective Shift perspective3DShift(elements, options = {}) { const maxRotation = options.maxRotation || 25; const perspective = options.perspective || 1000; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.perspective = perspective + 'px'; element.style.transition = 'transform 0.3s ease'; element.addEventListener('mousemove', (e) => { const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const rotateY = ((e.clientX - centerX) / (rect.width / 2)) * maxRotation; const rotateX = ((e.clientY - centerY) / (rect.height / 2)) * -maxRotation; element.style.transform = `perspective(${perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`; }); element.addEventListener('mouseleave', () => { element.style.transform = `perspective(${perspective}px) rotateX(0deg) rotateY(0deg)`; }); }); } // Effect 19: 3D Ripple Wave ripple3DWave(elements, options = {}) { const waveHeight = options.waveHeight || 30; const waveSpeed = options.waveSpeed || 0.05; elements.forEach((element, index) => { if (!element) return; element.style.transformStyle = 'preserve-3d'; element.style.perspective = '1000px'; let animationId; let startTime = Date.now() + (index * 200); const animate = () => { const elapsed = Date.now() - startTime; const wave1 = Math.sin(elapsed * waveSpeed) * waveHeight; const wave2 = Math.cos(elapsed * waveSpeed * 1.5) * (waveHeight * 0.5); const wave3 = Math.sin(elapsed * waveSpeed * 0.8) * (waveHeight * 0.3); element.style.transform = ` perspective(1000px) translate3d(0px, ${wave1}px, ${wave2}px) rotateX(${wave3}deg) `; animationId = requestAnimationFrame(animate); }; element.addEventListener('mouseenter', () => { animate(); }); element.addEventListener('mouseleave', () => { if (animationId) { cancelAnimationFrame(animationId); } element.style.transform = 'perspective(1000px) translate3d(0px, 0px, 0px) rotateX(0deg)'; }); }); } // Cleanup methods removeMouseFollower(element) { const data = this.mouseFollowers.get(element); if (data && data.follower) { data.follower.remove(); this.mouseFollowers.delete(element); } } removeMouseMagnet(element) { this.mouseMagnets.delete(element); element.style.transform = 'none'; } // Cleanup all effects cleanup() { // Remove all mouse followers this.mouseFollowers.forEach((data, element) => { if (data.follower) { data.follower.remove(); } }); this.mouseFollowers.clear(); // Reset all magnets this.mouseMagnets.forEach((data, element) => { element.style.transform = 'none'; }); this.mouseMagnets.clear(); } } export default AdvancedEffects;