:root { –cable-color: #facc15; –bg-color: #ffffff; –spark-color: #facc15; } /* WICHTIG: Wir zielen nur auf den Inhaltsbereich ab, damit das WordPress-Menü nicht kaputt geht */ .content { height: 400vh; padding: 50px; max-width: 600px; } .animation-track { position: fixed; top: 0; right: 0; width: 200px; height: 100vh; z-index: 100; pointer-events: none; /* Damit man durch die Animation klicken kann */ } .animation-track svg { width: 100%; height: 100%; } #cable { fill: none; stroke: var(–cable-color); stroke-width: 6; stroke-linecap: round; } #plug-body { fill: #1e293b; } .prong { fill: #94a3b8; } .socket-bg { fill: #e2e8f0; stroke: #cbd5e1; stroke-width: 2; } .socket-hole { fill: #475569; } .spark { fill: none; stroke: var(–spark-color); stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; opacity: 0; } .animate-spark-l { animation: spark-move-l 0.4s ease-out forwards; } .animate-spark-r { animation: spark-move-r 0.4s ease-out forwards; } @keyframes spark-move-l { 0% { opacity: 0; transform: translate(0, 0) scale(0.5); } 20% { opacity: 1; transform: translate(-5px, -5px) scale(1.1); } 100% { opacity: 0; transform: translate(-30px, -60px) scale(0.8); } } @keyframes spark-move-r { 0% { opacity: 0; transform: translate(0, 0) scale(0.5); } 20% { opacity: 1; transform: translate(5px, -5px) scale(1.1); } 100% { opacity: 0; transform: translate(30px, -60px) scale(0.8); } }

Pixel Perfect Connection

Scrolle ganz nach unten für den Effekt.

(function() { const cable = document.getElementById(‘cable’); const plugGroup = document.getElementById(‘plug-group’); const prong1 = document.getElementById(‘prong1’); const prong2 = document.getElementById(‘prong2’); const sparkL = document.getElementById(‘spark-l’); const sparkR = document.getElementById(‘spark-r’); function updateAnimation() { const scrollPercent = window.scrollY / (document.body.scrollHeight – window.innerHeight); const socketTopY = 940; const plugHeight = 45; const maxTravel = socketTopY – plugHeight + 5; const currentY = scrollPercent * maxTravel; let pathData = “M 50 0”; const segments = 60; for (let i = 1; i 0.92; const currentWaveX = 50 + Math.sin((segments / 4) + (scrollPercent * 20)) * (25 * scrollPercent * (1 – Math.pow(scrollPercent, 3))); const finalX = isNearEnd ? 50 : currentWaveX; plugGroup.setAttribute(‘transform’, `translate(${finalX – 50}, ${currentY})`); if (scrollPercent > 0.97) { const depth = (scrollPercent – 0.97) * 100; prong1.style.opacity = Math.max(0, 1 – depth); prong2.style.opacity = Math.max(0, 1 – depth); cable.style.stroke = “#facc15”; if (!sparkL.classList.contains(‘animate-spark-l’)) { sparkL.classList.add(‘animate-spark-l’); sparkR.classList.add(‘animate-spark-r’); } } else { prong1.style.opacity = “1”; prong2.style.opacity = “1”; cable.style.stroke = “var(–cable-color)”; sparkL.classList.remove(‘animate-spark-l’); sparkR.classList.remove(‘animate-spark-r’); } } window.addEventListener(‘scroll’, updateAnimation); updateAnimation(); })();