(function () { const config = { magneticRadius: 300, pullStrength: 0.8, scaleMin: 1.0, scaleMax: 1.15, parallaxStrength: 1.03, springStrength: 0.25, springDamping: 0.7, velocityMultiplier: 0.15, }; let magneticElements = [], rafId = null, mouseX = 0, mouseY = 0, prevMouseX = 0, prevMouseY = 0, mouseVelocityX = 0, mouseVelocityY = 0; function shouldEnableMagneticEffect() { if (typeof window.matchMedia !== "function") return true; return window.matchMedia("(hover: hover) and (pointer: fine)").matches; } function resetElementTransforms() { magneticElements.forEach(({ element, svg, isCentered }) => { if (element) { element.style.transform = isCentered ? "translate(-50%, -50%)" : ""; } if (svg) { svg.style.transform = ""; } }); } function initMagneticEffect() { if (typeof gsap === "undefined") { setTimeout(initMagneticEffect, 100); return; } magneticElements = []; const staticButtons = [ document.querySelector(".play-button-overlay .play-button"), document.querySelector(".video-w-modal-play-button"), ].filter(Boolean); staticButtons.forEach((button, index) => { const name = index === 0 ? "Hero Play Button" : "Modal Play Button"; const svg = button.querySelector("svg"); gsap.set(button, { clearProps: "transform" }); if (svg) gsap.set(svg, { clearProps: "transform" }); magneticElements.push({ element: button, svg: svg, currentX: 0, currentY: 0, targetX: 0, targetY: 0, velocityX: 0, velocityY: 0, currentScale: 1, targetScale: 1, isCentered: false, name, }); }); magneticElements.push({ element: null, svg: null, currentX: 0, currentY: 0, targetX: 0, targetY: 0, velocityX: 0, velocityY: 0, currentScale: 1, targetScale: 1, isCentered: true, isDynamic: true, name: "Video Stacks Play Button (Dynamic)", }); if (magneticElements.length === 0) { console.warn("No play buttons found"); return; } if (!shouldEnableMagneticEffect()) { resetElementTransforms(); console.log("Magnetic effect disabled for touch/coarse pointer devices"); return; } document.addEventListener("mousemove", handleMouseMove); animateMagneticEffect(); } function handleMouseMove(e) { prevMouseX = mouseX; prevMouseY = mouseY; mouseX = e.clientX; mouseY = e.clientY; mouseVelocityX = mouseX - prevMouseX; mouseVelocityY = mouseY - prevMouseY; } function animateMagneticEffect() { magneticElements.forEach((item) => { if (item.isDynamic) { const frontCardButton = document.querySelector( ".front-card .video-stacks-play-button", ); if (frontCardButton !== item.element) { if (item.element) { item.element.style.transform = ""; if (item.svg) item.svg.style.transform = ""; } item.element = frontCardButton; item.svg = frontCardButton ? frontCardButton.querySelector("svg") : null; item.currentX = 0; item.currentY = 0; item.velocityX = 0; item.velocityY = 0; item.currentScale = 1; } } const { element, svg } = item; if (!element || !element.offsetParent) { item.targetX = 0; item.targetY = 0; item.targetScale = 1; } else { const rect = element.getBoundingClientRect(); const elementCenterX = rect.left + rect.width / 2; const elementCenterY = rect.top + rect.height / 2; const deltaX = mouseX - elementCenterX; const deltaY = mouseY - elementCenterY; const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < config.magneticRadius && distance > 0) { const speed = Math.sqrt( mouseVelocityX * mouseVelocityX + mouseVelocityY * mouseVelocityY, ); const speedMultiplier = 1 + speed * config.velocityMultiplier; const effectMultiplier = item.isCentered ? 0.5 : 1.0; const scaleRange = item.isCentered ? (config.scaleMax - config.scaleMin) * 0.6 : config.scaleMax - config.scaleMin; const strength = (1 - distance / config.magneticRadius) * config.pullStrength * speedMultiplier * effectMultiplier; item.targetX = deltaX * strength; item.targetY = deltaY * strength; const scaleProgress = 1 - distance / config.magneticRadius; item.targetScale = config.scaleMin + scaleProgress * scaleRange; } else { item.targetX = 0; item.targetY = 0; item.targetScale = 1; } } const dx = item.targetX - item.currentX; const dy = item.targetY - item.currentY; item.velocityX += dx * config.springStrength; item.velocityY += dy * config.springStrength; item.velocityX *= config.springDamping; item.velocityY *= config.springDamping; item.currentX += item.velocityX; item.currentY += item.velocityY; item.currentScale += (item.targetScale - item.currentScale) * 0.25; if (element) { if (item.isCentered) { element.style.transform = `translate(-50%, -50%) translate(${item.currentX}px, ${item.currentY}px) scale(${item.currentScale})`; } else { element.style.transform = `translate(${item.currentX}px, ${item.currentY}px) scale(${item.currentScale})`; } if (svg) { const parallaxX = item.currentX * config.parallaxStrength; const parallaxY = item.currentY * config.parallaxStrength; svg.style.transform = `translate(${parallaxX - item.currentX}px, ${parallaxY - item.currentY}px)`; } } }); rafId = requestAnimationFrame(animateMagneticEffect); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", initMagneticEffect); } else { initMagneticEffect(); } window.cleanupMagneticEffect = function () { if (rafId) { cancelAnimationFrame(rafId); rafId = null; } document.removeEventListener("mousemove", handleMouseMove); resetElementTransforms(); magneticElements = []; }; })();