Animations can transform a static interface into an engaging user experience. Whether you're looking to add subtle transitions or dynamic effects, the right animation library can make all the difference.
In this article, we'll explore ten standout animation libraries that can elevate your UI design. From lightweight options to feature-rich frameworks, there's something here for every project.
CODE1
Here's the code:
CODETEXT1
CODE2
Here's the code:
CODETEXT2
CODE3
Here's the code:
CODETEXT3
CODE4
Here's the code:
CODETEXT4
CODE5
Here's the code:
CODETEXT5
Subframe's drag-and-drop interface and intuitive, responsive canvas make it easy to create pixel-perfect UI every time. Loved by designers and developers alike, Subframe empowers you to design stunning animation libraries effortlessly.
Start for free and elevate your UI design today!
CODE6
Here's the code:
CODETEXT6
CODE7
Here's the code:
CODETEXT7
CODE8
Here's the code:
CODETEXT8
CODE9
Here's the code:
CODETEXT9
CODE10
Here's the code:
CODETEXT10
Ready to elevate your UI design? With Subframe, you can create pixel-perfect interfaces and stunning animation libraries effortlessly. Our drag-and-drop editor ensures efficiency and precision.
Don't wait—start creating beautiful UIs immediately. Start for free and experience the power of Subframe today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>E-commerce Product Animation Library</title> <style> :root { --primary: #4a6fff; --secondary: #f9f9fb; --accent: #ff496c; --text: #2c3e50; --text-light: #6b7c93; --shadow: rgba(74, 111, 255, 0.15); --transition-slow: 600ms cubic-bezier(0.16, 1, 0.3, 1); --transition-fast: 300ms cubic-bezier(0.16, 1, 0.3, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { width: 100%; height: 100%; background-color: var(--secondary); color: var(--text); overflow-x: hidden; position: relative; } .container { width: 100%; height: 100vh; max-width: 700px; margin: 0 auto; padding: 2rem; display: flex; flex-direction: column; } header { margin-bottom: 2rem; } h1 { font-size: 1.8rem; line-height: 1.2; margin-bottom: 0.5rem; font-weight: 700; background: linear-gradient(to right, var(--primary), var(--accent)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } p { color: var(--text-light); line-height: 1.6; font-size: 0.95rem; } .controls { display: flex; gap: 1rem; margin-bottom: 1.5rem; flex-wrap: wrap; } .control-btn { background-color: white; border: 1px solid rgba(0, 0, 0, 0.1); padding: 0.6rem 1rem; border-radius: 3rem; font-size: 0.85rem; cursor: pointer; transition: all var(--transition-fast); box-shadow: 0 2px 5px var(--shadow); color: var(--text); font-weight: 500; } .control-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 10px var(--shadow); } .control-btn.active { background-color: var(--primary); color: white; border-color: var(--primary); } .showcase { position: relative; height: 350px; background-color: white; border-radius: 12px; overflow: hidden; box-shadow: 0 10px 30px var(--shadow); } .product-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; opacity: 0; transition: opacity var(--transition-slow); pointer-events: none; } .product-container.active { opacity: 1; pointer-events: all; } .product-image { flex: 1; padding: 1.5rem; display: flex; align-items: center; justify-content: center; position: relative; } .product-image img { max-width: 90%; max-height: 80%; object-fit: contain; transform: translateY(30px); opacity: 0; transition: transform var(--transition-slow), opacity var(--transition-slow); box-shadow: 0 20px 25px var(--shadow); } .product-container.active .product-image img { transform: translateY(0); opacity: 1; } .product-info { flex: 1; padding: 2rem; display: flex; flex-direction: column; justify-content: center; transform: translateX(30px); opacity: 0; transition: transform var(--transition-slow), opacity var(--transition-slow); transition-delay: 100ms; } .product-container.active .product-info { transform: translateX(0); opacity: 1; } .product-title { font-size: 1.4rem; margin-bottom: 0.5rem; font-weight: 700; } .product-price { font-size: 1.2rem; margin-bottom: 1rem; color: var(--primary); font-weight: 600; } .product-description { margin-bottom: 1.5rem; font-size: 0.9rem; color: var(--text-light); } .product-btn { align-self: flex-start; padding: 0.7rem 1.5rem; background-color: var(--primary); color: white; border: none; border-radius: 3rem; cursor: pointer; font-weight: 500; box-shadow: 0 4px 10px var(--shadow); transition: all var(--transition-fast); position: relative; overflow: hidden; } .product-btn:hover { transform: translateY(-2px) scale(1.05); box-shadow: 0 6px 15px var(--shadow); } .product-btn::before { content: ''; position: absolute; top: 50%; left: 50%; width: 10px; height: 10px; background: rgba(255, 255, 255, 0.5); border-radius: 50%; transform: translate(-50%, -50%) scale(0); opacity: 0; transition: transform 0.8s, opacity 0.8s; } .product-btn:active::before { transform: translate(-50%, -50%) scale(20); opacity: 1; transition: transform 0.4s, opacity 0.4s; } .dots { display: flex; justify-content: center; margin-top: 1.5rem; gap: 0.5rem; } .dot { width: 10px; height: 10px; border-radius: 50%; background-color: rgba(0, 0, 0, 0.1); cursor: pointer; transition: all var(--transition-fast); } .dot.active { background-color: var(--primary); transform: scale(1.3); } .background-pattern { position: absolute; width: 100%; height: 100%; top: 0; left: 0; z-index: -1; opacity: 0.4; pointer-events: none; } .pattern-dot { position: absolute; width: 20px; height: 20px; border-radius: 50%; background-color: var(--primary); opacity: 0.1; } @media (max-width: 600px) { .container { padding: 1rem; } h1 { font-size: 1.5rem; } .showcase { height: 450px; } .product-container { flex-direction: column; } .product-image { flex: 0 0 40%; } .product-info { flex: 0 0 60%; padding: 1rem 1.5rem; } .product-title { font-size: 1.2rem; } .controls { justify-content: center; } } /* Animations */ @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-10px); } 100% { transform: translateY(0px); } } .parallax-container { position: absolute; width: 100%; height: 100%; transform-style: preserve-3d; pointer-events: none; } .parallax-layer { position: absolute; width: 100%; height: 100%; transform-style: preserve-3d; } .decorative-element { position: absolute; border-radius: 50%; background: linear-gradient(135deg, var(--primary), var(--accent)); opacity: 0.1; } </style> </head> <body> <div class="container"> <header> <h1>Motion Product Showcase</h1> <p>Experiment with our fluid animation transitions designed for modern e-commerce. These performance-optimized animations enhance product visibility while maintaining a minimal aesthetic.</p> </header> <div class="controls"> <button class="control-btn active" data-animation="fade">Fade Transition</button> <button class="control-btn" data-animation="slide">Slide Transition</button> <button class="control-btn" data-animation="parallax">Parallax Effect</button> <button class="control-btn" data-animation="zoom">Zoom Focus</button> </div> <div class="showcase"> <div class="parallax-container"> <div class="parallax-layer" data-depth="0.2"> <div class="decorative-element" style="top: 10%; left: 15%; width: 40px; height: 40px;"></div> <div class="decorative-element" style="bottom: 20%; right: 10%; width: 30px; height: 30px;"></div> </div> <div class="parallax-layer" data-depth="0.5"> <div class="decorative-element" style="top: 30%; right: 20%; width: 25px; height: 25px;"></div> <div class="decorative-element" style="bottom: 30%; left: 25%; width: 20px; height: 20px;"></div> </div> </div> <div class="product-container active" data-product="1"> <div class="product-image"> <img src="https://i.imgur.com/xdbw1m7.png" alt="Wireless Headphones"> </div> <div class="product-info"> <h2 class="product-title">AudioPlus Wireless Headphones</h2> <div class="product-price">$129.99</div> <p class="product-description">Studio-quality sound with 36 hours of battery life. Adaptive noise cancellation that adjusts to your environment for uninterrupted listening.</p> <button class="product-btn">Add to Cart</button> </div> </div> <div class="product-container" data-product="2"> <div class="product-image"> <img src="https://i.imgur.com/Mm7nm2L.png" alt="Smart Watch"> </div> <div class="product-info"> <h2 class="product-title">Pulse Pro Smartwatch</h2> <div class="product-price">$189.99</div> <p class="product-description">Real-time health metrics with advanced sleep tracking. Water-resistant design with a customizable face that adapts to your activity and environment.</p> <button class="product-btn">Add to Cart</button> </div> </div> <div class="product-container" data-product="3"> <div class="product-image"> <img src="https://i.imgur.com/Oa0SbUI.png" alt="Wireless Speaker"> </div> <div class="product-info"> <h2 class="product-title">SoundSphere Wireless Speaker</h2> <div class="product-price">$79.99</div> <p class="product-description">360-degree audio projection with immersive bass technology. Connect multiple units wirelessly to create your own custom sound environment.</p> <button class="product-btn">Add to Cart</button> </div> </div> </div> <div class="dots"> <div class="dot active" data-product="1"></div> <div class="dot" data-product="2"></div> <div class="dot" data-product="3"></div> </div> </div> <div class="background-pattern"></div> <script> document.addEventListener('DOMContentLoaded', function() { // Generate background pattern const pattern = document.querySelector('.background-pattern'); for (let i = 0; i < 20; i++) { const dot = document.createElement('div'); dot.classList.add('pattern-dot'); dot.style.left = `${Math.random() * 100}%`; dot.style.top = `${Math.random() * 100}%`; dot.style.width = `${10 + Math.random() * 20}px`; dot.style.height = dot.style.width; pattern.appendChild(dot); } // Product showcase functionality const dots = document.querySelectorAll('.dot'); const products = document.querySelectorAll('.product-container'); let currentAnimation = 'fade'; let currentProduct = 1; // Handle dot navigation dots.forEach(dot => { dot.addEventListener('click', function() { const productId = this.getAttribute('data-product'); changeProduct(productId); }); }); // Change animation style const controlButtons = document.querySelectorAll('.control-btn'); controlButtons.forEach(btn => { btn.addEventListener('click', function() { currentAnimation = this.getAttribute('data-animation'); controlButtons.forEach(b => b.classList.remove('active')); this.classList.add('active'); // Update animation classes document.querySelector('.showcase').setAttribute('data-animation', currentAnimation); // Apply animation specific styles products.forEach(product => { const img = product.querySelector('img'); const info = product.querySelector('.product-info'); // Reset styles product.style.transition = ''; img.style.animation = ''; img.style.transition = ''; info.style.transition = ''; // Apply new styles based on selected animation switch(currentAnimation) { case 'fade': product.style.transition = 'opacity var(--transition-slow)'; img.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; info.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; break; case 'slide': product.style.transition = 'opacity var(--transition-slow), transform var(--transition-slow)'; product.style.transform = 'translateX(100px)'; img.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; info.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; break; case 'parallax': product.style.transition = 'opacity var(--transition-slow)'; img.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; img.style.transform = 'translateY(0) scale(1.1)'; info.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; info.style.transform = 'translateX(0) translateY(30px)'; break; case 'zoom': product.style.transition = 'opacity var(--transition-slow)'; img.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; img.style.transform = 'scale(0.8)'; info.style.transition = 'transform var(--transition-slow), opacity var(--transition-slow)'; break; } }); // Reapply animation to current product changeProduct(currentProduct, true); }); }); // Autoplay let autoplayInterval = setInterval(() => { let nextProduct = currentProduct % 3 + 1; changeProduct(nextProduct); }, 5000); // Clear autoplay on user interaction document.querySelector('.showcase').addEventListener('mouseenter', () => { clearInterval(autoplayInterval); }); // Parallax effect for decorative elements document.querySelector('.showcase').addEventListener('mousemove', handleParallax); function handleParallax(e) { const layers = document.querySelectorAll('.parallax-layer'); const centerX = e.clientX - e.currentTarget.getBoundingClientRect().left; const centerY = e.clientY - e.currentTarget.getBoundingClientRect().top; const width = e.currentTarget.offsetWidth; const height = e.currentTarget.offsetHeight; const moveX = (centerX - width / 2) / 25; const moveY = (centerY - height / 2) / 25; layers.forEach(layer => { const depth = parseFloat(layer.getAttribute('data-depth')); const translateX = moveX * depth; const translateY = moveY * depth; layer.style.transform = `translate3d(${translateX}px, ${translateY}px, 0)`; }); } function changeProduct(productId, forceAnimation = false) { if (currentProduct === parseInt(productId) && !forceAnimation) return; currentProduct = parseInt(productId); // Update active dot dots.forEach(d => { if (d.getAttribute('data-product') === productId) { d.classList.add('active'); } else { d.classList.remove('active'); } }); // Hide all products products.forEach(product => { if (product.getAttribute('data-product') === productId) { // Apply animation specific effects for active product switch(currentAnimation) { case 'fade': product.classList.add('active'); break; case 'slide': product.style.transform = 'translateX(0)'; product.classList.add('active'); break; case 'parallax': const img = product.querySelector('img'); const info = product.querySelector('.product-info'); img.style.transform = 'translateY(0) scale(1)'; info.style.transform = 'translateX(0) translateY(0)'; product.classList.add('active'); break; case 'zoom': const zoomImg = product.querySelector('img'); zoomImg.style.transform = 'scale(1)'; product.classList.add('active'); break; } } else { // Reset and hide inactive products product.classList.remove('active'); if (currentAnimation === 'slide') { product.style.transform = 'translateX(100px)'; } else if (currentAnimation === 'parallax') { const img = product.querySelector('img'); const info = product.querySelector('.product-info'); img.style.transform = 'translateY(30px) scale(1.1)'; info.style.transform = 'translateX(30px) translateY(30px)'; } else if (currentAnimation === 'zoom') { const zoomImg = product.querySelector('img'); zoomImg.style.transform = 'scale(0.8)'; } } }); } // Add floating animation to active product image function addFloatAnimation() { const activeProductImg = document.querySelector('.product-container.active img'); if (activeProductImg) { activeProductImg.style.animation = 'float 3s ease-in-out infinite'; } } // Apply initial animations document.querySelector('.control-btn.active').click(); // Ripple effect for buttons const buttons = document.querySelectorAll('.product-btn, .control-btn'); buttons.forEach(button => { button.addEventListener('click', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const ripple = document.createElement('span'); ripple.style.left = x + 'px'; ripple.style.top = y + 'px'; setTimeout(() => ripple.remove(), 600); }); }); // Add floating animation to initially active product setTimeout(addFloatAnimation, 600); // Add floating animation whenever the active product changes const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { if (mutation.target.classList.contains('active')) { setTimeout(addFloatAnimation, 600); } } }); }); products.forEach(product => { observer.observe(product, { attributes: true }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>DataFlowViz: Animated Data Visualization Library</title> <style> :root { --bg-color: #131722; --text-color: #ffffff; --text-secondary: #9fa4b4; --highlight: #5b8ff9; --accent-1: #4cc3a4; --accent-2: #f6bd16; --accent-3: #e8684a; --grid-line: rgba(255, 255, 255, 0.08); --card-bg: rgba(30, 34, 45, 0.85); --tooltip-bg: rgba(22, 26, 36, 0.95); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } body { background-color: var(--bg-color); color: var(--text-color); width: 100%; height: 100vh; overflow: hidden; display: flex; flex-direction: column; justify-content: flex-start; align-items: center; padding: 1.5rem; } header { width: 100%; margin-bottom: 1.5rem; text-align: center; } h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; letter-spacing: -0.02em; } .subtitle { color: var(--text-secondary); font-size: 0.875rem; font-weight: 400; max-width: 600px; margin: 0 auto; } .dashboard { width: 100%; height: calc(100vh - 7rem); max-height: 600px; display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 1rem; } .card { background: var(--card-bg); border-radius: 12px; padding: 1rem; position: relative; display: flex; flex-direction: column; overflow: hidden; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15); transition: transform 0.3s ease, box-shadow 0.3s ease; } .card:hover { transform: translateY(-2px); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.2); } .card-title { font-size: 0.875rem; font-weight: 500; margin-bottom: 0.75rem; display: flex; justify-content: space-between; align-items: center; } .card-value { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; } .card-change { font-size: 0.75rem; display: flex; align-items: center; gap: 0.25rem; } .positive { color: var(--accent-1); } .negative { color: var(--accent-3); } .chart-container { flex: 1; position: relative; min-height: 180px; } .chart-tooltip { position: absolute; background: var(--tooltip-bg); border-radius: 6px; padding: 0.75rem; font-size: 0.75rem; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); pointer-events: none; opacity: 0; transition: opacity 0.2s ease; z-index: 10; max-width: 180px; } .chart-tooltip-title { font-weight: 600; margin-bottom: 0.25rem; } .chart-tooltip-value { color: var(--text-secondary); } .controls { display: flex; justify-content: center; gap: 1rem; margin-top: 1rem; } button { background: rgba(91, 143, 249, 0.15); color: var(--highlight); border: none; border-radius: 6px; padding: 0.5rem 1rem; font-size: 0.75rem; font-weight: 500; cursor: pointer; transition: background 0.2s ease, transform 0.2s ease; } button:hover { background: rgba(91, 143, 249, 0.25); transform: translateY(-1px); } button:active { transform: translateY(0); } .chart-legend { display: flex; flex-wrap: wrap; gap: 0.75rem; font-size: 0.75rem; margin-top: 0.5rem; } .legend-item { display: flex; align-items: center; gap: 0.35rem; } .legend-color { width: 8px; height: 8px; border-radius: 50%; } /* Time period selector */ .time-selector { display: flex; background: rgba(255, 255, 255, 0.05); border-radius: 6px; padding: 2px; } .time-option { font-size: 0.65rem; padding: 4px 8px; border-radius: 4px; cursor: pointer; transition: all 0.2s ease; } .time-option.active { background: rgba(91, 143, 249, 0.3); color: var(--highlight); } .data-label { position: absolute; font-size: 0.65rem; color: var(--text-secondary); text-align: center; transition: opacity 0.3s ease; } /* Loading indicator */ .loading-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(19, 23, 34, 0.7); display: flex; justify-content: center; align-items: center; z-index: 20; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .loading-spinner { width: 24px; height: 24px; border: 2px solid rgba(255, 255, 255, 0.1); border-top-color: var(--highlight); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Responsive adjustments */ @media (max-width: 600px) { .dashboard { grid-template-columns: 1fr; grid-template-rows: repeat(4, 1fr); height: auto; overflow-y: auto; } h1 { font-size: 1.25rem; } .card-title { font-size: 0.8rem; } .card-value { font-size: 1.25rem; } } /* Animation keyframes */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @keyframes dataPoint { 0% { transform: scale(0); opacity: 0; } 50% { transform: scale(1.5); opacity: 1; } 100% { transform: scale(1); opacity: 1; } } /* Chart dots & bars */ .data-point { position: absolute; border-radius: 50%; cursor: pointer; transition: transform 0.2s ease, box-shadow 0.2s ease; animation: dataPoint 0.5s ease forwards; box-shadow: 0 0 0 rgba(255, 255, 255, 0); } .data-point:hover { transform: scale(1.5) !important; box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); z-index: 5; } .data-bar { position: absolute; bottom: 0; border-radius: 3px 3px 0 0; cursor: pointer; transition: height 0.5s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.3s ease; } .data-bar:hover { opacity: 0.8; } .data-line { position: absolute; stroke-dasharray: 1000; stroke-dashoffset: 1000; animation: drawLine 1.5s ease-in-out forwards; } @keyframes drawLine { to { stroke-dashoffset: 0; } } /* Area chart */ .area-chart-container { position: relative; width: 100%; height: 100%; overflow: hidden; } .area-gradient { position: absolute; width: 100%; height: 100%; background: linear-gradient(180deg, rgba(91, 143, 249, 0.15) 0%, rgba(91, 143, 249, 0) 100%); opacity: 0; transition: opacity 1s ease; } /* Grid lines */ .grid-line { position: absolute; background: var(--grid-line); z-index: 1; } .grid-line.horizontal { height: 1px; width: 100%; left: 0; } .grid-line.vertical { width: 1px; height: 100%; top: 0; } .refresh-icon { width: 14px; height: 14px; cursor: pointer; transition: transform 0.3s ease; } .refresh-icon:hover { transform: rotate(30deg); } .refresh-icon path { fill: var(--text-secondary); } /* Fancy toggle switch */ .toggle-container { display: flex; align-items: center; gap: 0.5rem; font-size: 0.75rem; } .toggle-track { position: relative; width: 32px; height: 16px; background: rgba(255, 255, 255, 0.1); border-radius: 10px; cursor: pointer; transition: background 0.3s ease; } .toggle-track.active { background: rgba(76, 195, 164, 0.3); } .toggle-thumb { position: absolute; width: 12px; height: 12px; background: var(--text-secondary); border-radius: 50%; top: 2px; left: 2px; transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.3s ease; } .toggle-track.active .toggle-thumb { transform: translateX(16px); background: var(--accent-1); } </style> </head> <body> <header> <h1>DataFlowViz: Performance Dashboard</h1> <p class="subtitle">A high-performance data visualization library built for real-time analytics with fluid, intuitive animations.</p> </header> <div class="dashboard"> <div class="card"> <div class="card-title"> <span>User Engagement Trends</span> <div class="time-selector"> <div class="time-option active" data-period="day">D</div> <div class="time-option" data-period="week">W</div> <div class="time-option" data-period="month">M</div> </div> </div> <div class="card-value">87.6%</div> <div class="card-change positive">+12.3% vs previous period</div> <div class="chart-container" id="line-chart"> <div class="loading-overlay"> <div class="loading-spinner"></div> </div> <!-- Line chart populated by JS --> </div> <div class="chart-legend"> <div class="legend-item"> <div class="legend-color" style="background: var(--highlight);"></div> <span>Active Users</span> </div> <div class="legend-item"> <div class="legend-color" style="background: var(--accent-1);"></div> <span>Session Duration</span> </div> </div> </div> <div class="card"> <div class="card-title"> <span>Memory Consumption</span> <svg class="refresh-icon" viewBox="0 0 24 24"> <path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/> </svg> </div> <div class="toggle-container"> <span>Live Updates</span> <div class="toggle-track active"> <div class="toggle-thumb"></div> </div> </div> <div class="chart-container" id="area-chart"> <div class="area-gradient"></div> <!-- Area chart populated by JS --> </div> <div class="chart-tooltip"> <div class="chart-tooltip-title">Memory Usage</div> <div class="chart-tooltip-value">256MB at 14:30</div> </div> </div> <div class="card"> <div class="card-title"> <span>API Request Distribution</span> </div> <div class="card-value">1,458 requests/min</div> <div class="card-change negative">-3.2% vs previous hour</div> <div class="chart-container" id="donut-chart"> <!-- Donut chart populated by JS --> </div> <div class="chart-legend"> <div class="legend-item"> <div class="legend-color" style="background: var(--highlight);"></div> <span>GET (68%)</span> </div> <div class="legend-item"> <div class="legend-color" style="background: var(--accent-1);"></div> <span>POST (22%)</span> </div> <div class="legend-item"> <div class="legend-color" style="background: var(--accent-2);"></div> <span>PUT (8%)</span> </div> <div class="legend-item"> <div class="legend-color" style="background: var(--accent-3);"></div> <span>DELETE (2%)</span> </div> </div> </div> <div class="card"> <div class="card-title"> <span>Processing Time Distribution</span> </div> <div class="chart-container" id="bar-chart"> <!-- Bar chart populated by JS --> </div> <div class="controls"> <button id="filter-btn">Filter Data</button> <button id="animate-btn">Animate Transition</button> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Initialize charts initLineChart(); initAreaChart(); initDonutChart(); initBarChart(); // Set up event listeners setupEventListeners(); // Simulate loading state document.querySelectorAll('.loading-overlay').forEach(overlay => { overlay.style.opacity = '1'; setTimeout(() => { overlay.style.opacity = '0'; }, 800); }); }); function setupEventListeners() { // Time period selectors document.querySelectorAll('.time-option').forEach(option => { option.addEventListener('click', function() { const container = this.closest('.time-selector'); container.querySelector('.active').classList.remove('active'); this.classList.add('active'); // Update the related chart const period = this.getAttribute('data-period'); const cardContainer = this.closest('.card'); const chartContainer = cardContainer.querySelector('.chart-container'); // Show loading state const loadingOverlay = cardContainer.querySelector('.loading-overlay'); if (loadingOverlay) { loadingOverlay.style.opacity = '1'; setTimeout(() => { loadingOverlay.style.opacity = '0'; // Update chart based on the container ID if (chartContainer.id === 'line-chart') { updateLineChart(period); } }, 600); } }); }); // Refresh icon document.querySelector('.refresh-icon').addEventListener('click', function() { const cardContainer = this.closest('.card'); const chartContainer = cardContainer.querySelector('.chart-container'); // Animate the refresh icon this.style.transform = 'rotate(180deg)'; setTimeout(() => { this.style.transform = 'rotate(0deg)'; }, 600); // Refresh the area chart refreshAreaChart(); }); // Toggle switch document.querySelector('.toggle-track').addEventListener('click', function() { this.classList.toggle('active'); // Start or stop live updates if (this.classList.contains('active')) { startLiveUpdates(); } else { stopLiveUpdates(); } }); // Filter button document.getElementById('filter-btn').addEventListener('click', function() { filterBarData(); }); // Animate transition button document.getElementById('animate-btn').addEventListener('click', function() { animateBarTransition(); }); } // Line Chart function initLineChart() { const container = document.getElementById('line-chart'); container.innerHTML = ''; // Clear the container // Add grid lines for (let i = 1; i <= 4; i++) { const gridLine = document.createElement('div'); gridLine.classList.add('grid-line', 'horizontal'); gridLine.style.bottom = `${i * 20}%`; container.appendChild(gridLine); } // Generate random data points for two series const numPoints = 12; const seriesData1 = []; const seriesData2 = []; for (let i = 0; i < numPoints; i++) { seriesData1.push(40 + Math.random() * 40); seriesData2.push(20 + Math.random() * 30); } // Add data points for active users for (let i = 0; i < numPoints; i++) { const point = document.createElement('div'); point.classList.add('data-point'); point.style.backgroundColor = 'var(--highlight)'; point.style.width = '6px'; point.style.height = '6px'; const x = 10 + (i * (container.clientWidth - 20) / (numPoints - 1)); const y = container.clientHeight - (seriesData1[i] / 100 * container.clientHeight); point.style.left = `${x}px`; point.style.top = `${y}px`; point.style.animationDelay = `${i * 50}ms`; point.setAttribute('data-value', seriesData1[i].toFixed(1)); point.setAttribute('data-index', i); // Add hover event for tooltip point.addEventListener('mouseenter', showTooltip); point.addEventListener('mouseleave', hideTooltip); container.appendChild(point); } // Draw line for active users drawLine(container, seriesData1, 'var(--highlight)'); // Add data points for session duration for (let i = 0; i < numPoints; i++) { const point = document.createElement('div'); point.classList.add('data-point'); point.style.backgroundColor = 'var(--accent-1)'; point.style.width = '6px'; point.style.height = '6px'; const x = 10 + (i * (container.clientWidth - 20) / (numPoints - 1)); const y = container.clientHeight - (seriesData2[i] / 100 * container.clientHeight); point.style.left = `${x}px`; point.style.top = `${y}px`; point.style.animationDelay = `${i * 50 + 300}ms`; point.setAttribute('data-value', seriesData2[i].toFixed(1)); point.setAttribute('data-index', i); // Add hover event for tooltip point.addEventListener('mouseenter', showTooltip); point.addEventListener('mouseleave', hideTooltip); container.appendChild(point); } // Draw line for session duration drawLine(container, seriesData2, 'var(--accent-1)'); } function drawLine(container, data, color) { const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute('width', '100%'); svg.setAttribute('height', '100%'); svg.style.position = 'absolute'; svg.style.top = '0'; svg.style.left = '0'; svg.style.zIndex = '1'; const line = document.createElementNS("http://www.w3.org/2000/svg", "path"); let pathData = ''; const numPoints = data.length; for (let i = 0; i < numPoints; i++) { const x = 10 + (i * (container.clientWidth - 20) / (numPoints - 1)); const y = container.clientHeight - (data[i] / 100 * container.clientHeight); if (i === 0) { pathData += `M ${x} ${y}`; } else { pathData += ` L ${x} ${y}`; } } line.setAttribute('d', pathData); line.setAttribute('fill', 'none'); line.setAttribute('stroke', color); line.setAttribute('stroke-width', '2'); line.classList.add('data-line'); svg.appendChild(line); container.appendChild(svg); } function updateLineChart(period) { const container = document.getElementById('line-chart'); // Clear only the data points and lines, keep grid lines container.querySelectorAll('.data-point, svg').forEach(el => el.remove()); // Generate new random data points with different patterns based on the period const numPoints = period === 'day' ? 12 : (period === 'week' ? 7 : 30); const seriesData1 = []; const seriesData2 = []; // Create different patterns based on the period if (period === 'day') { for (let i = 0; i < numPoints; i++) { // Pattern for daily data - higher in middle of day seriesData1.push(40 + 30 * Math.sin(i / numPoints * Math.PI) + Math.random() * 10); seriesData2.push(20 + 25 * Math.sin(i / numPoints * Math.PI) + Math.random() * 10); } } else if (period === 'week') { for (let i = 0; i < numPoints; i++) { // Pattern for weekly data - weekend dips const weekendFactor = (i === 5 || i === 6) ? 0.7 : 1; seriesData1.push((50 + Math.random() * 30) * weekendFactor); seriesData2.push((30 + Math.random() * 20) * weekendFactor); } } else { for (let i = 0; i < numPoints; i++) { // Pattern for monthly data - upward trend seriesData1.push(30 + (i / numPoints * 30) + Math.random() * 20); seriesData2.push(15 + (i / numPoints * 25) + Math.random() * 15); } } // Add new data points for active users for (let i = 0; i < numPoints; i++) { const point = document.createElement('div'); point.classList.add('data-point'); point.style.backgroundColor = 'var(--highlight)'; point.style.width = '6px'; point.style.height = '6px'; const x = 10 + (i * (container.clientWidth - 20) / (numPoints - 1)); const y = container.clientHeight - (seriesData1[i] / 100 * container.clientHeight); point.style.left = `${x}px`; point.style.top = `${y}px`; point.style.animationDelay = `${i * 50}ms`; point.setAttribute('data-value', seriesData1[i].toFixed(1)); point.setAttribute('data-index', i); // Add hover event for tooltip point.addEventListener('mouseenter', showTooltip); point.addEventListener('mouseleave', hideTooltip); container.appendChild(point); } // Draw line for active users drawLine(container, seriesData1, 'var(--highlight)'); // Add data points for session duration for (let i = 0; i < numPoints; i++) { const point = document.createElement('div'); point.classList.add('data-point'); point.style.backgroundColor = 'var(--accent-1)'; point.style.width = '6px'; point.style.height = '6px'; const x = 10 + (i * (container.clientWidth - 20) / (numPoints - 1)); const y = container.clientHeight - (seriesData2[i] / 100 * container.clientHeight); point.style.left = `${x}px`; point.style.top = `${y}px`; point.style.animationDelay = `${i * 50 + 300}ms`; point.setAttribute('data-value', seriesData2[i].toFixed(1)); point.setAttribute('data-index', i); // Add hover event for tooltip point.addEventListener('mouseenter', showTooltip); point.addEventListener('mouseleave', hideTooltip); container.appendChild(point); } // Draw line for session duration drawLine(container, seriesData2, 'var(--accent-1)'); // Update the card value and change percentage const card = container.closest('.card'); const newValue = (period === 'day' ? 87.6 : (period === 'week' ? 92.3 : 78.9)); const changeValue = (period === 'day' ? 12.3 : (period === 'week' ? 8.7 : -3.2)); const valueEl = card.querySelector('.card-value'); const changeEl = card.querySelector('.card-change'); valueEl.innerHTML = `${newValue}%`; changeEl.className = 'card-change ' + (changeValue >= 0 ? 'positive' : 'negative'); changeEl.innerHTML = `${changeValue >= 0 ? '+' : ''}${changeValue}% vs previous period`; } function showTooltip(e) { // Create a tooltip if it doesn't exist let tooltip = document.querySelector('.chart-tooltip'); if (!tooltip) { tooltip = document.createElement('div'); tooltip.classList.add('chart-tooltip'); document.body.appendChild(tooltip); } // Get the value from the data attribute const value = parseFloat(this.getAttribute('data-value')); const index = parseInt(this.getAttribute('data-index')); // Calculate time label based on index const timeLabels = ['00:00', '02:00', '04:00', '06:00', '08:00', '10:00', '12:00', '14:00', '16:00', '18:00', '20:00', '22:00', '24:00']; // Generate tooltip content const color = this.style.backgroundColor.includes('highlight') ? 'Active Users' : 'Session Duration'; tooltip.innerHTML = ` <div class="chart-tooltip-title">${color}</div> <div class="chart-tooltip-value">${value}% at ${timeLabels[index % timeLabels.length]}</div> `; // Position the tooltip near the data point const rect = this.getBoundingClientRect(); tooltip.style.left = `${rect.left + window.scrollX}px`; tooltip.style.top = `${rect.top + window.scrollY - 60}px`; // Make the tooltip visible tooltip.style.opacity = '1'; // Make the data point grow this.style.transform = 'scale(1.5)'; this.style.zIndex = '5'; } function hideTooltip() { // Hide the tooltip const tooltip = document.querySelector('.chart-tooltip'); if (tooltip) { tooltip.style.opacity = '0'; } // Reset the data point size this.style.transform = 'scale(1)'; this.style.zIndex = '1'; } // Area Chart function initAreaChart() { const container = document.getElementById('area-chart'); container.innerHTML = ''; // Clear the container // Add grid lines for (let i = 1; i <= 4; i++) { const gridLine = document.createElement('div'); gridLine.classList.add('grid-line', 'horizontal'); gridLine.style.bottom = `${i * 20}%`; container.appendChild(gridLine); } for (let i = 1; i <= 5; i++) { const gridLine = document.createElement('div'); gridLine.classList.add('grid-line', 'vertical'); gridLine.style.left = `${i * 16.67}%`; container.appendChild(gridLine); } // Time labels at the bottom const timeLabels = ['12:00', '14:00', '16:00', '18:00', '20:00', '22:00']; timeLabels.forEach((label, i) => { const labelEl = document.createElement('div'); labelEl.classList.add('data-label'); labelEl.textContent = label; labelEl.style.bottom = '5px'; labelEl.style.left = `${i * 16.67 + 8}%`; container.appendChild(labelEl); }); // Memory usage labels on the left const memoryLabels = ['0MB', '128MB', '256MB', '384MB', '512MB']; memoryLabels.forEach((label, i) => { const labelEl = document.createElement('div'); labelEl.classList.add('data-label'); labelEl.textContent = label; labelEl.style.left = '5px'; labelEl.style.bottom = `${i * 20 + 10}%`; container.appendChild(labelEl); }); // Generate random data series const numPoints = 50; const seriesData = []; // Create a fluctuating pattern with a spike for (let i = 0; i < numPoints; i++) { // Base value let value = 30 + Math.sin(i / 8) * 15; // Add a spike in the middle if (i > numPoints * 0.6 && i < numPoints * 0.8) { value += 25 * Math.sin((i - numPoints * 0.6) / (numPoints * 0.2) * Math.PI); } // Add some noise value += Math.random() * 5; seriesData.push(value); } // Create SVG for the area chart const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute('width', '100%'); svg.setAttribute('height', '100%'); svg.style.position = 'absolute'; svg.style.top = '0'; svg.style.left = '0'; svg.style.zIndex = '2'; // Create path for line const line = document.createElementNS("http://www.w3.org/2000/svg", "path"); // Create path for area const area = document.createElementNS("http://www.w3.org/2000/svg", "path"); let lineData = ''; let areaData = ''; for (let i = 0; i < numPoints; i++) { const x = (i * container.clientWidth / (numPoints - 1)); const y = container.clientHeight - (seriesData[i] / 100 * container.clientHeight); if (i === 0) { lineData += `M ${x} ${y}`; areaData += `M ${x} ${container.clientHeight} L ${x} ${y}`; } else { lineData += ` L ${x} ${y}`; areaData += ` L ${x} ${y}`; } if (i === numPoints - 1) { areaData += ` L ${x} ${container.clientHeight} Z`; } } line.setAttribute('d', lineData); line.setAttribute('fill', 'none'); line.setAttribute('stroke', 'var(--highlight)'); line.setAttribute('stroke-width', '2'); line.classList.add('data-line'); area.setAttribute('d', areaData); area.setAttribute('fill', 'url(#areaGradient)'); area.setAttribute('stroke', 'none'); area.setAttribute('opacity', '0.3'); // Create gradient const gradient = document.createElementNS("http://www.w3.org/2000/svg", "linearGradient"); gradient.setAttribute('id', 'areaGradient'); gradient.setAttribute('x1', '0'); gradient.setAttribute('y1', '0'); gradient.setAttribute('x2', '0'); gradient.setAttribute('y2', '1'); const stop1 = document.createElementNS("http://www.w3.org/2000/svg", "stop"); stop1.setAttribute('offset', '0%'); stop1.setAttribute('stop-color', 'var(--highlight)'); stop1.setAttribute('stop-opacity', '0.4'); const stop2 = document.createElementNS("http://www.w3.org/2000/svg", "stop"); stop2.setAttribute('offset', '100%'); stop2.setAttribute('stop-color', 'var(--highlight)'); stop2.setAttribute('stop-opacity', '0'); gradient.appendChild(stop1); gradient.appendChild(stop2); const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); defs.appendChild(gradient); svg.appendChild(defs); svg.appendChild(area); svg.appendChild(line); container.appendChild(svg);
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Gestio: Mobile Gesture Animation Library</title> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@400;500;600;700&display=swap'); :root { --primary: #4E38FF; --secondary: #F2468B; --tertiary: #00CFFD; --success: #0BD977; --warning: #FFB443; --dark: #121215; --light: #F8F8FC; --gray: #8E8EA0; --background: linear-gradient(135deg, #121215 0%, #1E1E24 100%); --card-bg: rgba(255, 255, 255, 0.08); --shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', sans-serif; background: var(--background); color: var(--light); width: 100%; height: 100vh; overflow: hidden; display: flex; justify-content: center; align-items: center; } .container { width: 700px; height: 700px; padding: 1.5rem; overflow: hidden; position: relative; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; } .logo { font-family: 'Space Grotesk', sans-serif; font-weight: 700; font-size: 1.8rem; background: linear-gradient(90deg, var(--primary), var(--tertiary)); -webkit-background-clip: text; background-clip: text; color: transparent; position: relative; } .logo::after { content: 'beta'; position: absolute; top: -5px; right: -35px; font-size: 0.7rem; background: var(--secondary); color: white; padding: 2px 6px; border-radius: 10px; } .menu-button { background: transparent; border: none; color: var(--light); cursor: pointer; font-size: 1.5rem; } .gesture-showcase { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; height: calc(100% - 120px); } .animation-card { background: var(--card-bg); border-radius: 18px; padding: 1.5rem; display: flex; flex-direction: column; position: relative; overflow: hidden; backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.1); transform: translateY(0); transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); cursor: pointer; } .animation-card:hover { transform: translateY(-5px); } .animation-card.active { transform: scale(1.02); border-color: var(--primary); box-shadow: 0 0 20px rgba(78, 56, 255, 0.3); } .card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .card-title { font-weight: 600; font-size: 1.1rem; margin: 0; } .card-badge { font-size: 0.7rem; padding: 3px 10px; border-radius: 12px; background: rgba(78, 56, 255, 0.2); color: var(--primary); } .card-badge.new { background: rgba(242, 70, 139, 0.2); color: var(--secondary); } .card-content { flex: 1; display: flex; align-items: center; justify-content: center; } .demo-element { width: 70px; height: 70px; border-radius: 15px; background: var(--primary); position: relative; } .demo-swipe { width: 90%; height: 70px; border-radius: 15px; background: rgba(255, 255, 255, 0.1); display: flex; align-items: center; padding: 0 15px; position: relative; overflow: hidden; } .swipe-handle { position: absolute; left: 0; width: 70px; height: 70px; border-radius: 15px; background: var(--success); display: flex; justify-content: center; align-items: center; color: white; font-weight: 600; cursor: grab; touch-action: none; z-index: 2; } .swipe-text { margin-left: 80px; color: var(--gray); font-size: 0.9rem; } .card-footer { margin-top: 1rem; font-size: 0.75rem; color: var(--gray); } .demo-pinch { width: 100px; height: 100px; border-radius: 20px; background: var(--tertiary); display: flex; justify-content: center; align-items: center; color: white; font-weight: 600; transform-origin: center; user-select: none; } .demo-rotate { width: 80px; height: 80px; background: linear-gradient(135deg, var(--secondary), var(--warning)); border-radius: 16px; display: flex; justify-content: center; align-items: center; color: white; transform-origin: center; user-select: none; } .features-bar { position: absolute; bottom: 0; left: 0; width: 100%; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: space-around; padding: 1rem; backdrop-filter: blur(10px); transform: translateY(100%); transition: transform 0.3s cubic-bezier(0.19, 1, 0.22, 1); } .container:hover .features-bar { transform: translateY(0); } .feature-item { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; } .feature-icon { width: 40px; height: 40px; border-radius: 50%; background: var(--card-bg); display: flex; justify-content: center; align-items: center; font-size: 1.2rem; } .feature-text { font-size: 0.75rem; color: var(--gray); } .bounce-animation { animation: bounce 1.5s infinite; } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-15px); } } .notification { position: absolute; top: 20px; left: 50%; transform: translateX(-50%) translateY(-100px); background: var(--success); color: white; padding: 1rem 2rem; border-radius: 12px; font-weight: 500; box-shadow: var(--shadow); opacity: 0; transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55); z-index: 1000; } .notification.show { transform: translateX(-50%) translateY(0); opacity: 1; } .pulse { width: 100px; height: 100px; position: relative; } .pulse::before, .pulse::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: var(--warning); opacity: 0.6; animation: pulse 2s linear infinite; } .pulse::after { animation-delay: 1s; } @keyframes pulse { 0% { transform: scale(0.5); opacity: 0.6; } 100% { transform: scale(1.5); opacity: 0; } } .dot { position: absolute; width: 40px; height: 40px; border-radius: 50%; background: var(--warning); z-index: 2; } @media (max-width: 700px) { .container { padding: 1rem; } .gesture-showcase { grid-template-columns: 1fr; height: calc(100% - 90px); overflow-y: auto; } .header { margin-bottom: 1rem; } .logo { font-size: 1.5rem; } } </style> </head> <body> <div class="container"> <div class="header"> <h1 class="logo">Gestio</h1> <button class="menu-button">☰</button> </div> <div class="gesture-showcase"> <div class="animation-card" id="bounce-card"> <div class="card-header"> <h3 class="card-title">Elastic Bounce</h3> <span class="card-badge">Popular</span> </div> <div class="card-content"> <div class="demo-element bounce-animation" id="bounce-element"></div> </div> <div class="card-footer">60fps hardware-accelerated / 3kb</div> </div> <div class="animation-card" id="swipe-card"> <div class="card-header"> <h3 class="card-title">Momentum Swipe</h3> <span class="card-badge">Interactive</span> </div> <div class="card-content"> <div class="demo-swipe"> <div class="swipe-handle" id="swipe-handle">Drag</div> <div class="swipe-text">Swipe to unlock haptic feedback</div> </div> </div> <div class="card-footer">Customizable resistance / Spring physics</div> </div> <div class="animation-card" id="pinch-card"> <div class="card-header"> <h3 class="card-title">Zoom Pinch</h3> <span class="card-badge new">New</span> </div> <div class="card-content"> <div class="demo-pinch" id="pinch-element">Pinch Me</div> </div> <div class="card-footer">Multi-touch / Smooth scale transitions</div> </div> <div class="animation-card" id="rotate-card"> <div class="card-header"> <h3 class="card-title">Fluid Rotation</h3> <span class="card-badge">Advanced</span> </div> <div class="card-content"> <div class="demo-rotate" id="rotate-element">Rotate</div> </div> <div class="card-footer">Inertia effects / Snap to angles</div> </div> </div> <div class="features-bar"> <div class="feature-item"> <div class="feature-icon">🚀</div> <div class="feature-text">Hardware Accelerated</div> </div> <div class="feature-item"> <div class="feature-icon">📱</div> <div class="feature-text">Cross-platform</div> </div> <div class="feature-item"> <div class="feature-icon">⚡</div> <div class="feature-text">4kb Minified</div> </div> <div class="feature-item"> <div class="feature-icon">🎨</div> <div class="feature-text">Customizable</div> </div> </div> <div class="notification" id="notification">Animation copied to clipboard!</div> </div> <script> // Bounce Animation Card Interaction const bounceCard = document.getElementById('bounce-card'); const bounceElement = document.getElementById('bounce-element'); bounceCard.addEventListener('click', () => { toggleActive(bounceCard); bounceElement.style.animationPlayState = bounceElement.style.animationPlayState === 'paused' ? 'running' : 'paused'; showNotification('Elastic Bounce animation added to library!'); }); // Swipe Animation Interaction const swipeHandle = document.getElementById('swipe-handle'); const swipeCard = document.getElementById('swipe-card'); let isDragging = false; let startX, currentX; swipeHandle.addEventListener('mousedown', startDrag); swipeHandle.addEventListener('touchstart', (e) => { startDrag(e.touches[0]); }, { passive: true }); document.addEventListener('mousemove', drag); document.addEventListener('touchmove', (e) => { drag(e.touches[0]); }, { passive: false }); document.addEventListener('mouseup', endDrag); document.addEventListener('touchend', endDrag); function startDrag(e) { isDragging = true; startX = e.clientX || e.pageX; currentX = startX; swipeHandle.style.cursor = 'grabbing'; swipeHandle.style.transition = 'none'; } function drag(e) { if (!isDragging) return; e.preventDefault?.(); currentX = e.clientX || e.pageX; let deltaX = currentX - startX; // Limit drag to parent width const parentWidth = swipeHandle.parentElement.offsetWidth; const handleWidth = swipeHandle.offsetWidth; const maxDrag = parentWidth - handleWidth; deltaX = Math.max(0, Math.min(deltaX, maxDrag)); swipeHandle.style.transform = `translateX(${deltaX}px)`; // Success state when dragged far enough if (deltaX > maxDrag * 0.8) { swipeHandle.style.background = 'var(--success)'; swipeHandle.textContent = '✓'; } else { swipeHandle.style.background = 'var(--success)'; swipeHandle.textContent = 'Drag'; } } function endDrag() { if (!isDragging) return; isDragging = false; const parentWidth = swipeHandle.parentElement.offsetWidth; const handleWidth = swipeHandle.offsetWidth; const maxDrag = parentWidth - handleWidth; const currentDrag = currentX - startX; swipeHandle.style.transition = 'transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275)'; swipeHandle.style.cursor = 'grab'; if (currentDrag > maxDrag * 0.8) { swipeHandle.style.transform = `translateX(${maxDrag}px)`; showNotification('Momentum Swipe interaction unlocked!'); toggleActive(swipeCard); // Reset after a moment setTimeout(() => { swipeHandle.style.transition = 'transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55)'; swipeHandle.style.transform = 'translateX(0)'; swipeHandle.textContent = 'Drag'; swipeCard.classList.remove('active'); }, 1500); } else { // Spring back animation swipeHandle.style.transform = 'translateX(0)'; } } // Pinch Animation Interaction const pinchElement = document.getElementById('pinch-element'); const pinchCard = document.getElementById('pinch-card'); pinchCard.addEventListener('click', () => { toggleActive(pinchCard); // Simulate pinch animation pinchElement.style.transition = 'transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275)'; if (pinchElement.style.transform === 'scale(1.5)') { pinchElement.style.transform = 'scale(1)'; } else { pinchElement.style.transform = 'scale(1.5)'; showNotification('Zoom Pinch animation applied!'); } }); // Rotate Animation Interaction const rotateElement = document.getElementById('rotate-element'); const rotateCard = document.getElementById('rotate-card'); let rotation = 0; rotateCard.addEventListener('click', () => { toggleActive(rotateCard); rotation += 90; rotateElement.style.transition = 'transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1)'; rotateElement.style.transform = `rotate(${rotation}deg)`; showNotification('Fluid Rotation animation copied!'); }); // Helper Functions function toggleActive(element) { document.querySelectorAll('.animation-card').forEach(card => { card.classList.remove('active'); }); element.classList.add('active'); } function showNotification(message) { const notification = document.getElementById('notification'); notification.textContent = message; notification.classList.add('show'); setTimeout(() => { notification.classList.remove('show'); }, 2000); } // Touch Feedback Animation document.querySelectorAll('.animation-card').forEach(card => { card.addEventListener('mousedown', function() { this.style.transform = 'scale(0.98)'; }); card.addEventListener('mouseup', function() { this.style.transform = ''; }); card.addEventListener('mouseleave', function() { this.style.transform = ''; }); }); // Random animation triggering for demo setTimeout(() => { bounceCard.click(); }, 1000); setTimeout(() => { rotateCard.click(); }, 3000); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Healthcare Portal Animation Library</title> <style> :root { --primary: #5B9BD5; --secondary: #8CC7D9; --accent: #9FD8CB; --text: #2E4756; --background: #F5F9FC; --calm-pink: #F7DCE5; --soothing-lavender: #E2D9F3; --pale-yellow: #FFF8E1; --light-green: #DCF2E9; --white: #FFFFFF; --success: #6FCF97; --warning: #F2C94C; --error: #EB5757; --shadow: rgba(46, 71, 86, 0.08); --transition-slow: 0.6s cubic-bezier(0.33, 1, 0.68, 1); --transition-medium: 0.4s cubic-bezier(0.33, 1, 0.68, 1); --transition-fast: 0.2s cubic-bezier(0.33, 1, 0.68, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: var(--background); color: var(--text); overflow-x: hidden; height: 100%; width: 100%; display: flex; flex-direction: column; justify-content: flex-start; align-items: center; padding: 20px; } .container { max-width: 650px; width: 100%; margin: 0 auto; background: var(--white); border-radius: 16px; box-shadow: 0 8px 30px var(--shadow); overflow: hidden; position: relative; } header { padding: 24px; background-color: var(--primary); color: white; text-align: center; position: relative; overflow: hidden; } header h1 { font-size: 24px; font-weight: 600; margin-bottom: 8px; position: relative; z-index: 2; } header p { font-size: 14px; opacity: 0.9; max-width: 500px; margin: 0 auto; position: relative; z-index: 2; } .pattern { position: absolute; top: 0; right: 0; width: 100%; height: 100%; opacity: 0.1; background-image: radial-gradient(var(--white) 2px, transparent 2px); background-size: 20px 20px; } .category-tabs { display: flex; justify-content: space-between; padding: 0 16px; margin-top: 20px; position: relative; overflow-x: auto; -webkit-overflow-scrolling: touch; scroll-behavior: smooth; white-space: nowrap; } .category-tabs::-webkit-scrollbar { height: 4px; } .category-tabs::-webkit-scrollbar-thumb { background: var(--secondary); border-radius: 10px; } .tab { padding: 12px 20px; margin: 0 4px; border-radius: 8px; font-size: 14px; color: var(--text); font-weight: 500; cursor: pointer; transition: all var(--transition-medium); position: relative; background-color: transparent; opacity: 0; transform: translateY(20px); animation: fadeSlideUp 0.5s forwards; animation-delay: calc(var(--i) * 0.1s); } .tab:first-child { margin-left: 0; } .tab:last-child { margin-right: 0; } .tab.active { background-color: var(--primary); color: white; } .tab:not(.active):hover { background-color: rgba(91, 155, 213, 0.1); } .tab::after { content: ''; position: absolute; bottom: 0; left: 50%; width: 0; height: 3px; background-color: var(--accent); transition: all var(--transition-medium); transform: translateX(-50%); } .tab.active::after { width: 80%; } .animation-showcase { padding: 30px 24px; } .section-title { font-size: 18px; font-weight: 600; margin-bottom: 20px; color: var(--text); opacity: 0; transform: translateY(20px); animation: fadeSlideUp 0.6s forwards; } .animation-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-bottom: 30px; } @media (max-width: 580px) { .animation-grid { grid-template-columns: 1fr; } } .animation-card { background-color: var(--white); border-radius: 12px; border: 1px solid rgba(91, 155, 213, 0.1); box-shadow: 0 4px 20px var(--shadow); padding: 20px; cursor: pointer; transition: all var(--transition-medium); position: relative; overflow: hidden; opacity: 0; transform: translateY(30px); animation: fadeSlideUp 0.8s forwards; animation-delay: calc(var(--i) * 0.15s); } .animation-card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(91, 155, 213, 0.15); } .animation-card h3 { font-size: 16px; margin-bottom: 12px; color: var(--primary); transition: color var(--transition-fast); } .animation-card p { font-size: 14px; color: var(--text); opacity: 0.8; line-height: 1.5; margin-bottom: 16px; } .demo-button { display: inline-flex; align-items: center; padding: 8px 16px; border-radius: 6px; background-color: var(--light-green); color: var(--primary); font-size: 13px; font-weight: 500; cursor: pointer; transition: all var(--transition-fast); border: none; outline: none; } .demo-button:hover { background-color: var(--primary); color: white; } .demo-button svg { margin-left: 6px; transition: transform var(--transition-fast); } .demo-button:hover svg { transform: translateX(4px); } .card-accent { position: absolute; top: 0; right: 0; width: 160px; height: 160px; border-radius: 50%; opacity: 0.1; z-index: 0; transition: all var(--transition-medium); } .animation-card:hover .card-accent { transform: scale(1.2); opacity: 0.15; } .fade .card-accent { background-color: var(--primary); } .slide .card-accent { background-color: var(--secondary); } .pulse .card-accent { background-color: var(--soothing-lavender); } .scale .card-accent { background-color: var(--calm-pink); } .card-content { position: relative; z-index: 1; } .preference-panel { background-color: var(--pale-yellow); border-radius: 12px; padding: 20px; margin-top: 30px; position: relative; opacity: 0; transform: translateY(20px); animation: fadeSlideUp 0.7s forwards; animation-delay: 0.6s; } .preference-panel h3 { font-size: 16px; margin-bottom: 16px; color: var(--text); } .preference-option { display: flex; align-items: center; margin-bottom: 12px; } .preference-option:last-child { margin-bottom: 0; } .toggle-switch { position: relative; display: inline-block; width: 46px; height: 24px; margin-right: 10px; } .toggle-switch input { opacity: 0; width: 0; height: 0; } .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #e0e0e0; transition: var(--transition-medium); border-radius: 34px; } .toggle-slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: var(--transition-medium); border-radius: 50%; } input:checked + .toggle-slider { background-color: var(--primary); } input:checked + .toggle-slider:before { transform: translateX(22px); } .preference-label { font-size: 14px; color: var(--text); } .demo-container { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.5); justify-content: center; align-items: center; z-index: 100; opacity: 0; transition: opacity var(--transition-medium); } .demo-box { background-color: var(--white); border-radius: 16px; max-width: 500px; width: 90%; max-height: 90vh; overflow-y: auto; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.15); transform: translateY(50px); transition: transform var(--transition-medium); position: relative; } .demo-box.active { transform: translateY(0); } .demo-header { padding: 20px; border-bottom: 1px solid rgba(0, 0, 0, 0.05); display: flex; justify-content: space-between; align-items: center; } .demo-header h2 { font-size: 18px; color: var(--primary); } .close-demo { background: none; border: none; cursor: pointer; width: 30px; height: 30px; display: flex; justify-content: center; align-items: center; border-radius: 50%; transition: background-color var(--transition-fast); } .close-demo:hover { background-color: rgba(0, 0, 0, 0.05); } .demo-content { padding: 30px; } .demo-element { width: 100%; height: 200px; background-color: var(--light-green); display: flex; justify-content: center; align-items: center; border-radius: 12px; color: var(--primary); font-weight: 500; margin-bottom: 20px; } .code-block { background-color: #f5f5f5; border-radius: 8px; padding: 16px; font-family: 'Courier New', monospace; font-size: 14px; line-height: 1.5; overflow-x: auto; color: #333; } .copy-button { display: inline-flex; align-items: center; padding: 8px 16px; border-radius: 6px; background-color: var(--primary); color: white; font-size: 13px; font-weight: 500; cursor: pointer; transition: all var(--transition-fast); border: none; outline: none; margin-top: 16px; } .copy-button svg { margin-right: 6px; } .copy-button:hover { background-color: #4a87c0; } .reduced-motion .animation-card:hover { transform: none; } @keyframes fadeSlideUp { to { opacity: 1; transform: translateY(0); } } @keyframes fadeIn { to { opacity: 1; } } @keyframes fadeSlideRight { to { opacity: 1; transform: translateX(0); } } /* animation classes */ .demo-fade { opacity: 0; transition: opacity var(--transition-medium); } .demo-fade.show { opacity: 1; } .demo-slide { opacity: 0; transform: translateY(30px); transition: all var(--transition-medium); } .demo-slide.show { opacity: 1; transform: translateY(0); } .demo-pulse { animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .demo-scale { transition: transform var(--transition-medium); } .demo-scale.show { transform: scale(1.1); } .feedback-toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%) translateY(100px); background-color: var(--success); color: white; padding: 12px 20px; border-radius: 8px; font-size: 14px; opacity: 0; transition: all var(--transition-medium); z-index: 1000; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); } .feedback-toast.show { transform: translateX(-50%) translateY(0); opacity: 1; } /* Responsive adjustments */ @media (max-width: 500px) { header h1 { font-size: 20px; } .section-title { font-size: 16px; } .animation-card { padding: 16px; } .animation-card h3 { font-size: 15px; } .demo-box { width: 95%; } .demo-content { padding: 20px; } } </style> </head> <body> <div class="container"> <header> <div class="pattern"></div> <h1>Healthcare Portal Animation Library</h1> <p>Gentle, reassuring, and accessible animations to enhance the patient experience</p> </header> <div class="category-tabs"> <div class="tab active" style="--i:1">Transitions</div> <div class="tab" style="--i:2">Feedback</div> <div class="tab" style="--i:3">Notifications</div> <div class="tab" style="--i:4">Indicators</div> <div class="tab" style="--i:5">Progress</div> </div> <div class="animation-showcase"> <h2 class="section-title">Core Animation Components</h2> <div class="animation-grid"> <div class="animation-card fade" style="--i:1" data-type="fade"> <div class="card-accent"></div> <div class="card-content"> <h3>Gentle Fade Transitions</h3> <p>Soft opacity transitions for UI elements that provide visual calm when content appears or changes.</p> <button class="demo-button">View Demo <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></button> </div> </div> <div class="animation-card slide" style="--i:2" data-type="slide"> <div class="card-accent"></div> <div class="card-content"> <h3>Smooth Slide Effects</h3> <p>Gradual movement animations that help guide attention and create a sense of flow across information.</p> <button class="demo-button">View Demo <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></button> </div> </div> <div class="animation-card pulse" style="--i:3" data-type="pulse"> <div class="card-accent"></div> <div class="card-content"> <h3>Subtle Pulse Indicators</h3> <p>Gentle breathing animations for highlighting important elements without causing visual stress.</p> <button class="demo-button">View Demo <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></button> </div> </div> <div class="animation-card scale" style="--i:4" data-type="scale"> <div class="card-accent"></div> <div class="card-content"> <h3>Subtle Scale Transforms</h3> <p>Refined size transitions that provide feedback while maintaining a professional atmosphere.</p> <button class="demo-button">View Demo <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg></button> </div> </div> </div> <div class="preference-panel"> <h3>Accessibility Preferences</h3> <div class="preference-option"> <label class="toggle-switch"> <input type="checkbox" id="reduced-motion"> <span class="toggle-slider"></span> </label> <span class="preference-label">Reduced motion mode</span> </div> <div class="preference-option"> <label class="toggle-switch"> <input type="checkbox" id="high-contrast"> <span class="toggle-slider"></span> </label> <span class="preference-label">High contrast mode</span> </div> </div> </div> </div> <div class="demo-container"> <div class="demo-box"> <div class="demo-header"> <h2>Animation Demo</h2> <button class="close-demo"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> </button> </div> <div class="demo-content"> <div class="demo-element"> Click to trigger animation </div> <div class="code-block"> <code></code> </div> <button class="copy-button"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8 5H6C4.89543 5 4 5.89543 4 7V19C4 20.1046 4.89543 21 6 21H16C17.1046 21 18 20.1046 18 19V18M8 5C8 6.10457 8.89543 7 10 7H12C13.1046 7 14 6.10457 14 5M8 5C8 3.89543 8.89543 3 10 3H12C13.1046 3 14 3.89543 14 5M14 5H16C17.1046 5 18 5.89543 18 7V12M20 14V16.5L18 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </svg> Copy Code </button> </div> </div> </div> <div class="feedback-toast"> Code copied to clipboard </div> <script> document.addEventListener('DOMContentLoaded', function() { // Tab functionality const tabs = document.querySelectorAll('.tab'); tabs.forEach(tab => { tab.addEventListener('click', function() { tabs.forEach(t => t.classList.remove('active')); this.classList.add('active'); }); }); // Animation preferences const reducedMotionToggle = document.getElementById('reduced-motion'); const highContrastToggle = document.getElementById('high-contrast'); // Check system preferences if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { reducedMotionToggle.checked = true; document.body.classList.add('reduced-motion'); } if (window.matchMedia('(prefers-contrast: more)').matches) { highContrastToggle.checked = true; document.body.classList.add('high-contrast'); } reducedMotionToggle.addEventListener('change', function() { if (this.checked) { document.body.classList.add('reduced-motion'); } else { document.body.classList.remove('reduced-motion'); } }); highContrastToggle.addEventListener('change', function() { if (this.checked) { document.body.classList.add('high-contrast'); } else { document.body.classList.remove('high-contrast'); } }); // Demo functionality const demoButtons = document.querySelectorAll('.demo-button'); const demoContainer = document.querySelector('.demo-container'); const demoBox = document.querySelector('.demo-box'); const closeDemo = document.querySelector('.close-demo'); const demoElement = document.querySelector('.demo-element'); const codeBlock = document.querySelector('.code-block code'); const copyButton = document.querySelector('.copy-button'); const feedbackToast = document.querySelector('.feedback-toast'); let currentDemoType = ''; const demoCodeExamples = { fade: `.fade-element {\n opacity: 0;\n transition: opacity 0.6s cubic-bezier(0.33, 1, 0.68, 1);\n}\n\n.fade-element.show {\n opacity: 1;\n}`, slide: `.slide-element {\n opacity: 0;\n transform: translateY(30px);\n transition: all 0.6s cubic-bezier(0.33, 1, 0.68, 1);\n}\n\n.slide-element.show {\n opacity: 1;\n transform: translateY(0);\n}`, pulse: `.pulse-element {\n animation: pulse 2s infinite cubic-bezier(0.33, 1, 0.68, 1);\n}\n\n@keyframes pulse {\n 0% {\n transform: scale(1);\n }\n 50% {\n transform: scale(1.05);\n }\n 100% {\n transform: scale(1);\n }\n}`, scale: `.scale-element {\n transition: transform 0.4s cubic-bezier(0.33, 1, 0.68, 1);\n}\n\n.scale-element.active {\n transform: scale(1.1);\n}` }; demoButtons.forEach(button => { button.addEventListener('click', function() { const card = this.closest('.animation-card'); currentDemoType = card.dataset.type; // Set demo header text document.querySelector('.demo-header h2').textContent = card.querySelector('h3').textContent; // Set code example codeBlock.textContent = demoCodeExamples[currentDemoType]; // Remove any active classes from demo element demoElement.className = 'demo-element'; // Add appropriate class based on demo type demoElement.classList.add('demo-' + currentDemoType); // Show demo container demoContainer.style.display = 'flex'; setTimeout(() => { demoContainer.style.opacity = '1'; demoBox.classList.add('active'); }, 10); }); }); closeDemo.addEventListener('click', function() { demoContainer.style.opacity = '0'; demoBox.classList.remove('active'); setTimeout(() => { demoContainer.style.display = 'none'; }, 400); }); demoElement.addEventListener('click', function() { // Toggle animation if (currentDemoType === 'pulse') { // For pulse, we just temporarily stop and restart the animation this.style.animation = 'none'; setTimeout(() => { this.style.animation = ''; }, 10); } else { this.classList.toggle('show'); } }); copyButton.addEventListener('click', function() { const textToCopy = codeBlock.textContent; navigator.clipboard.writeText(textToCopy).then(() => { showFeedbackToast(); }); }); function showFeedbackToast() { feedbackToast.classList.add('show'); setTimeout(() => { feedbackToast.classList.remove('show'); }, 2000); } // Close demo when clicking outside demoContainer.addEventListener('click', function(e) { if (e.target === demoContainer) { closeDemo.click(); } }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>FinPulse Dashboard Animation Library</title> <style> :root { --primary: #0a2463; --secondary: #3e92cc; --accent: #2a9d8f; --success: #2a9d8f; --warning: #e9c46a; --danger: #e76f51; --neutral: #eff1f3; --dark: #2d3142; --shadow: rgba(10, 36, 99, 0.1); --chart-1: #3e92cc; --chart-2: #2a9d8f; --chart-3: #e9c46a; --chart-4: #e76f51; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; } body { background-color: #f7f9fc; color: var(--dark); font-size: 14px; line-height: 1.5; overflow-x: hidden; height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; } .container { width: 100%; max-width: 700px; height: 700px; background-color: white; border-radius: 16px; box-shadow: 0 8px 30px var(--shadow); display: flex; flex-direction: column; overflow: hidden; position: relative; } .header { display: flex; justify-content: space-between; align-items: center; padding: 20px 24px; border-bottom: 1px solid rgba(0, 0, 0, 0.05); height: 72px; } .logo { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 18px; color: var(--primary); } .logo-icon { width: 30px; height: 30px; background: var(--primary); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; } .header-actions { display: flex; gap: 16px; align-items: center; } .header-actions .btn { background: none; border: none; cursor: pointer; color: var(--dark); opacity: 0.7; transition: all 0.2s; } .header-actions .btn:hover { opacity: 1; } .sidebar { width: 220px; background-color: white; border-right: 1px solid rgba(0, 0, 0, 0.05); height: calc(100% - 72px); padding: 20px 0; position: absolute; left: 0; top: 72px; transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); z-index: 10; } .sidebar.collapsed { transform: translateX(-220px); } .nav-item { display: flex; align-items: center; padding: 12px 24px; gap: 12px; color: var(--dark); opacity: 0.7; cursor: pointer; transition: all 0.2s; border-left: 3px solid transparent; } .nav-item:hover, .nav-item.active { opacity: 1; background-color: rgba(62, 146, 204, 0.05); border-left: 3px solid var(--secondary); } .nav-item.active { color: var(--secondary); font-weight: 600; } .main-content { flex: 1; padding: 24px; margin-left: 220px; transition: margin-left 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); overflow-y: auto; height: calc(100% - 72px); } .main-content.full { margin-left: 0; } .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; } .dashboard-title { font-size: 24px; font-weight: 700; color: var(--primary); } .date-range { padding: 8px 16px; background-color: white; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 8px; display: flex; align-items: center; gap: 8px; font-size: 14px; cursor: pointer; transition: all 0.2s; } .date-range:hover { border-color: var(--secondary); } .metrics-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 16px; margin-bottom: 24px; opacity: 0; transform: translateY(20px); animation: fadeUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; animation-delay: 0.2s; } .metric-card { background-color: white; border-radius: 12px; padding: 16px; box-shadow: 0 4px 12px var(--shadow); transition: all 0.3s; } .metric-card:hover { transform: translateY(-5px); box-shadow: 0 8px 20px var(--shadow); } .metric-icon { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; margin-bottom: 12px; color: white; } .metric-value { font-size: 24px; font-weight: 700; margin-bottom: 4px; } .metric-label { color: rgba(0, 0, 0, 0.6); font-size: 13px; } .metric-change { margin-top: 8px; font-size: 12px; display: flex; align-items: center; gap: 4px; } .change-positive { color: var(--success); } .change-negative { color: var(--danger); } .charts-row { display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-bottom: 24px; opacity: 0; transform: translateY(20px); animation: fadeUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; animation-delay: 0.4s; } .chart-wrapper { background-color: white; border-radius: 12px; box-shadow: 0 4px 12px var(--shadow); padding: 16px; height: 260px; position: relative; } .chart-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; } .chart-title { font-weight: 600; font-size: 16px; } .chart-legend { display: flex; gap: 12px; font-size: 12px; } .legend-item { display: flex; align-items: center; gap: 4px; } .legend-color { width: 10px; height: 10px; border-radius: 2px; } .chart-content { position: relative; height: calc(100% - 40px); } .line-chart, .donut-chart { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .chart-tooltip { position: absolute; background-color: rgba(0, 0, 0, 0.8); color: white; border-radius: 4px; padding: 8px 12px; font-size: 12px; pointer-events: none; z-index: 100; opacity: 0; transition: opacity 0.2s; } .recent-transactions { background-color: white; border-radius: 12px; box-shadow: 0 4px 12px var(--shadow); padding: 16px; margin-bottom: 24px; opacity: 0; transform: translateY(20px); animation: fadeUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; animation-delay: 0.6s; } .transactions-list { margin-top: 16px; } .transaction-item { display: flex; align-items: center; padding: 12px 0; border-bottom: 1px solid rgba(0, 0, 0, 0.05); } .transaction-item:last-child { border-bottom: none; } .transaction-icon { width: 40px; height: 40px; border-radius: 50%; background-color: var(--neutral); display: flex; align-items: center; justify-content: center; margin-right: 12px; flex-shrink: 0; } .transaction-details { flex: 1; } .transaction-name { font-weight: 500; } .transaction-date { font-size: 12px; color: rgba(0, 0, 0, 0.5); } .transaction-amount { font-weight: 600; } .transaction-status { font-size: 12px; padding: 4px 8px; border-radius: 12px; margin-left: 8px; } .status-completed { background-color: rgba(42, 157, 143, 0.1); color: var(--success); } .status-pending { background-color: rgba(233, 196, 106, 0.1); color: var(--warning); } .status-failed { background-color: rgba(231, 111, 81, 0.1); color: var(--danger); } .secure-banner { display: flex; align-items: center; gap: 12px; background-color: rgba(42, 157, 143, 0.05); border: 1px solid rgba(42, 157, 143, 0.2); border-radius: 8px; padding: 12px 16px; margin-bottom: 24px; opacity: 0; transform: translateY(20px); animation: fadeUp 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; animation-delay: 0.8s; } .secure-icon { color: var(--success); } .secure-text { font-size: 12px; color: var(--dark); } .loading-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.9); display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 1000; opacity: 1; transition: opacity 0.5s; } .loading-spinner { width: 40px; height: 40px; border: 3px solid rgba(62, 146, 204, 0.1); border-radius: 50%; border-top-color: var(--secondary); animation: spin 1s linear infinite; margin-bottom: 16px; } .loading-text { font-size: 14px; color: var(--secondary); font-weight: 500; } .progress-bar { width: 200px; height: 4px; background-color: rgba(62, 146, 204, 0.1); border-radius: 2px; margin-top: 8px; overflow: hidden; } .progress-value { height: 100%; background-color: var(--secondary); width: 0%; transition: width 0.3s; } .success-checkmark { display: none; width: 50px; height: 50px; margin-bottom: 16px; } .checkmark-circle { stroke-dasharray: 166; stroke-dashoffset: 166; stroke-width: 2; stroke-miterlimit: 10; stroke: var(--success); fill: none; animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards; } .checkmark { width: 50px; height: 50px; border-radius: 50%; display: block; stroke-width: 2; stroke: #fff; stroke-miterlimit: 10; box-shadow: inset 0px 0px 0px var(--success); animation: fill 0.4s ease-in-out 0.4s forwards, scale 0.3s ease-in-out 0.9s both; } .checkmark-check { transform-origin: 50% 50%; stroke-dasharray: 48; stroke-dashoffset: 48; animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards; } @keyframes stroke { 100% { stroke-dashoffset: 0; } } @keyframes scale { 0%, 100% { transform: none; } 50% { transform: scale3d(1.1, 1.1, 1); } } @keyframes fill { 100% { box-shadow: inset 0px 0px 0px 30px var(--success); } } @keyframes spin { to { transform: rotate(360deg); } } @keyframes fadeUp { to { opacity: 1; transform: translateY(0); } } /* Data Visualization Styles */ .line-point { fill: var(--chart-1); stroke: white; stroke-width: 2; transition: r 0.2s; cursor: pointer; } .line-point:hover { r: 6; } /* Responsive Adjustments */ @media (max-width: 768px) { .sidebar { width: 180px; } .sidebar.collapsed { transform: translateX(-180px); } .main-content { margin-left: 180px; } .metrics-grid { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); } .charts-row { grid-template-columns: 1fr; } } @media (max-width: 576px) { .dashboard-header { flex-direction: column; align-items: flex-start; gap: 12px; } .sidebar { width: 240px; } .sidebar.collapsed { transform: translateX(-240px); } .main-content { margin-left: 0; padding: 16px; } .metrics-grid { grid-template-columns: repeat(2, 1fr); } .metric-card { padding: 12px; } .metric-value { font-size: 20px; } } /* Animation Classes */ .animate-pulse { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.7; } } .animate-fade-in { animation: fadeIn 0.5s ease-out forwards; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } /* Special Animation: Secure Data Badge */ .secure-badge { display: inline-flex; align-items: center; background-color: rgba(42, 157, 143, 0.1); color: var(--success); padding: 4px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; margin-left: 8px; gap: 4px; position: relative; overflow: hidden; } .secure-badge::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); animation: shimmer 2s infinite; } @keyframes shimmer { 100% { left: 100%; } } /* Custom Toggle Switch */ .toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; } .toggle-switch input { opacity: 0; width: 0; height: 0; } .toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 24px; } .toggle-slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .4s; border-radius: 50%; } input:checked + .toggle-slider { background-color: var(--secondary); } input:checked + .toggle-slider:before { transform: translateX(20px); } /* Notification Badge */ .notification-badge { position: relative; } .badge { position: absolute; top: -4px; right: -4px; width: 8px; height: 8px; background-color: var(--danger); border-radius: 50%; } </style> </head> <body> <div class="container"> <div class="loading-overlay"> <div class="loading-spinner"></div> <div class="loading-text">Securely loading your financial data...</div> <div class="progress-bar"> <div class="progress-value"></div> </div> <div class="success-checkmark"> <svg class="checkmark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52"> <circle class="checkmark-circle" cx="26" cy="26" r="25" fill="none"/> <path class="checkmark-check" fill="none" d="M14.1 27.2l7.1 7.2 16.7-16.8"/> </svg> </div> </div> <header class="header"> <div class="logo"> <div class="logo-icon">FP</div> <span>FinPulse</span> </div> <div class="header-actions"> <button class="btn notification-badge"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path> <path d="M13.73 21a2 2 0 0 1-3.46 0"></path> </svg> <span class="badge"></span> </button> <button class="btn" id="toggleSidebar"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="3" y1="12" x2="21" y2="12"></line> <line x1="3" y1="6" x2="21" y2="6"></line> <line x1="3" y1="18" x2="21" y2="18"></line> </svg> </button> </div> </header> <aside class="sidebar"> <div class="nav-item active"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="7" height="7"></rect> <rect x="14" y="3" width="7" height="7"></rect> <rect x="14" y="14" width="7" height="7"></rect> <rect x="3" y="14" width="7" height="7"></rect> </svg> <span>Dashboard</span> </div> <div class="nav-item"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="12" y1="1" x2="12" y2="23"></line> <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path> </svg> <span>Transactions</span> </div> <div class="nav-item"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path> </svg> <span>Reports</span> </div> <div class="nav-item"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path> <circle cx="12" cy="7" r="4"></circle> </svg> <span>Accounts</span> </div> <div class="nav-item"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="3"></circle> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> </svg> <span>Settings</span> </div> </aside> <main class="main-content"> <div class="dashboard-header"> <h1 class="dashboard-title">Financial Overview</h1> <div class="date-range"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect> <line x1="16" y1="2" x2="16" y2="6"></line> <line x1="8" y1="2" x2="8" y2="6"></line> <line x1="3" y1="10" x2="21" y2="10"></line> </svg> <span>Apr 1 - Apr 30, 2023</span> </div> </div> <div class="metrics-grid"> <div class="metric-card"> <div class="metric-icon" style="background-color: var(--chart-1);"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="12" y1="1" x2="12" y2="23"></line> <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path> </svg> </div> <div class="metric-value">$87,432</div> <div class="metric-label">Total Balance</div> <div class="metric-change change-positive"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> 3.2% </div> </div> <div class="metric-card"> <div class="metric-icon" style="background-color: var(--chart-2);"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline> <polyline points="17 6 23 6 23 12"></polyline> </svg> </div> <div class="metric-value">$12,574</div> <div class="metric-label">Monthly Income</div> <div class="metric-change change-positive"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="18 15 12 9 6 15"></polyline> </svg> 5.8% </div> </div> <div class="metric-card"> <div class="metric-icon" style="background-color: var(--chart-3);"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="23 18 13.5 8.5 8.5 13.5 1 6"></polyline> <polyline points="17 18 23 18 23 12"></polyline> </svg> </div> <div class="metric-value">$8,942</div> <div class="metric-label">Monthly Expense</div> <div class="metric-change change-negative"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="6 9 12 15 18 9"></polyline> </svg> 2.1% </div> </div> </div> <div class="charts-row"> <div class="chart-wrapper"> <div class="chart-header"> <div class="chart-title">Cash Flow</div> <div class="chart-legend"> <div class="legend-item"> <div class="legend-color" style="background-color: var(--chart-1);"></div> <span>Income</span> </div> <div class="legend-item"> <div class="legend-color" style="background-color: var(--chart-2);"></div> <span>Expenses</span> </div> </div> </div> <div class="chart-content"> <svg class="line-chart" viewBox="0 0 400 180" preserveAspectRatio="none"></svg> <div class="chart-tooltip"></div> </div> </div> <div class="chart-wrapper"> <div class="chart-header"> <div class="chart-title">Expense Breakdown</div> <label class="toggle-switch"> <input type="checkbox" checked> <span class="toggle-slider"></span> </label> </div> <div class="chart-content"> <svg class="donut-chart" viewBox="0 0 200 180" preserveAspectRatio="xMidYMid meet"></svg> </div> </div> </div> <div class="recent-transactions"> <div class="chart-header"> <div class="chart-title">Recent Transactions</div> <div class="secure-badge"> <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect> <path d="M7 11V7a5 5 0 0 1 10 0v4"></path> </svg> Encrypted </div> </div> <div class="transactions-list"> <div class="transaction-item"> <div class="transaction-icon" style="background-color: rgba(62, 146, 204, 0.1); color: var(--chart-1);"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="23 6 13.5 15.5 8.5 10.5 1 18"></polyline> <polyline points="17 6 23 6 23 12"></polyline> </svg> </div> <div class="transaction-details"> <div class="transaction-name">Payroll Deposit</div> <div class="transaction-date">Apr 28, 2023 • 09:24 AM</div> </div> <div> <div class="transaction-amount">+$4,287.32</div> <div class="transaction-status status-completed">Completed</div> </div> </div> <div class="transaction-item"> <div class="transaction-icon" style="background-color: rgba(233, 196, 106, 0.1); color: var(--chart-3);"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="2" y="5" width="20" height="14" rx="2"></rect
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>LearnMotion: Educational Animation Library</title> <style> :root { --primary: #4F46E5; --primary-light: #A5B4FC; --primary-dark: #3730A3; --secondary: #FB7185; --secondary-light: #FDA4AF; --tertiary: #14B8A6; --light: #F9FAFB; --dark: #1F2937; --gray-100: #F3F4F6; --gray-200: #E5E7EB; --gray-300: #D1D5DB; --gray-400: #9CA3AF; --success: #22C55E; --warning: #FBBF24; --error: #EF4444; --font-heading: 'Poppins', sans-serif; --font-body: 'Inter', sans-serif; } @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap'); * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: var(--font-body); color: var(--dark); background-color: var(--light); transition: background-color 0.5s ease; height: 100%; overflow-x: hidden; } .container { max-width: 700px; height: 700px; margin: 0 auto; padding: 1.5rem; display: flex; flex-direction: column; position: relative; overflow: hidden; } h1, h2, h3, h4, h5, h6 { font-family: var(--font-heading); line-height: 1.2; } h1 { font-size: 2rem; font-weight: 700; margin-bottom: 1rem; background: linear-gradient(120deg, var(--primary), var(--tertiary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-align: center; } p { margin-bottom: 1rem; line-height: 1.6; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; flex-direction: column; gap: 0.5rem; } .header-description { text-align: center; max-width: 90%; color: var(--gray-400); font-size: 0.9rem; } .card-container { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1rem; margin-bottom: 1.5rem; } .card { background: white; border-radius: 0.75rem; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 1.25rem; transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); position: relative; overflow: hidden; cursor: pointer; height: 100%; display: flex; flex-direction: column; } .card:hover { transform: translateY(-5px); box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); } .card:before { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 4px; background: linear-gradient(to right, var(--primary), var(--tertiary)); transform: scaleX(0); transform-origin: left; transition: transform 0.3s ease; } .card:hover:before { transform: scaleX(1); } .card h3 { font-size: 1.1rem; margin-bottom: 0.5rem; color: var(--dark); position: relative; z-index: 1; } .card p { font-size: 0.85rem; color: var(--gray-400); margin-bottom: 1rem; position: relative; z-index: 1; } .card-icon { font-size: 1.25rem; color: var(--primary); margin-bottom: 0.75rem; background: var(--primary-light); width: 2.5rem; height: 2.5rem; display: flex; align-items: center; justify-content: center; border-radius: 0.5rem; opacity: 0.9; transition: all 0.3s ease; } .card:hover .card-icon { transform: scale(1.1); opacity: 1; } .btn { display: inline-flex; align-items: center; justify-content: center; padding: 0.5rem 1rem; border-radius: 0.5rem; font-weight: 500; font-size: 0.875rem; transition: all 0.3s ease; cursor: pointer; border: none; outline: none; text-decoration: none; margin-top: auto; } .btn-primary { background-color: var(--primary); color: white; } .btn-primary:hover { background-color: var(--primary-dark); transform: translateY(-2px); } .btn-outline { background-color: transparent; color: var(--primary); border: 1px solid var(--primary); } .btn-outline:hover { background-color: var(--primary); color: white; transform: translateY(-2px); } .btn-icon { margin-left: 0.5rem; transition: transform 0.3s ease; } .btn:hover .btn-icon { transform: translateX(3px); } .feature-section { margin-top: 2rem; } .feature-title { font-size: 1.25rem; margin-bottom: 1rem; color: var(--dark); position: relative; display: inline-block; } .feature-title:after { content: ""; position: absolute; bottom: -4px; left: 0; width: 60%; height: 2px; background: linear-gradient(to right, var(--primary), var(--tertiary)); } .demo-container { background: white; border-radius: 0.75rem; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 1.5rem; margin-bottom: 1.5rem; position: relative; overflow: hidden; } .progress-demo { margin-top: 1rem; } .progress-bar-container { height: 8px; background-color: var(--gray-200); border-radius: 4px; margin-bottom: 1rem; overflow: hidden; position: relative; } .progress-bar { height: 100%; background: linear-gradient(to right, var(--primary), var(--tertiary)); border-radius: 4px; width: 0%; transition: width 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); position: relative; } .progress-bar:after { content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 15px; background: rgba(255, 255, 255, 0.3); transform: skew(-20deg); animation: shimmer 1.5s infinite; } @keyframes shimmer { 0% { transform: translateX(-150%) skew(-20deg); } 100% { transform: translateX(150%) skew(-20deg); } } .progress-steps { display: flex; justify-content: space-between; margin-top: 1rem; position: relative; } .progress-step { display: flex; flex-direction: column; align-items: center; position: relative; z-index: 2; } .step-icon { width: 2rem; height: 2rem; border-radius: 50%; display: flex; align-items: center; justify-content: center; background-color: var(--gray-300); color: white; margin-bottom: 0.5rem; font-size: 0.875rem; transition: all 0.3s ease; } .progress-step.active .step-icon { background-color: var(--primary); transform: scale(1.1); box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.2); } .progress-step.completed .step-icon { background-color: var(--success); } .step-label { font-size: 0.75rem; color: var(--gray-400); transition: color 0.3s ease; } .progress-step.active .step-label { color: var(--primary); font-weight: 500; } .progress-step.completed .step-label { color: var(--success); } .progress-line { position: absolute; top: 1rem; left: 2.5rem; right: 2.5rem; height: 2px; background-color: var(--gray-300); z-index: 1; } .progress-line-fill { position: absolute; top: 0; left: 0; height: 100%; background-color: var(--success); width: 0%; transition: width 0.5s ease; } .demo-controls { display: flex; justify-content: space-between; margin-top: 1.5rem; } .animation-showcase { margin-top: 2rem; position: relative; } .animation-card { background: white; border-radius: 0.75rem; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); padding: 1.5rem; display: flex; flex-direction: column; position: relative; overflow: hidden; height: 200px; } .animation-card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; } .animation-card-title { font-size: 1rem; font-weight: 600; } .animation-options { display: flex; gap: 0.5rem; } .animation-option { width: 1.5rem; height: 1.5rem; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.75rem; cursor: pointer; transition: all 0.3s ease; } .option-slow { background-color: var(--primary-light); color: var(--primary-dark); } .option-medium { background-color: var(--secondary-light); color: var(--secondary); } .option-fast { background-color: var(--gray-200); color: var(--gray-400); } .animation-option.active { transform: scale(1.1); box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.2); } .animation-content { display: flex; align-items: center; justify-content: center; flex-grow: 1; position: relative; } .animation-element { width: 50px; height: 50px; background: linear-gradient(135deg, var(--primary), var(--tertiary)); border-radius: 8px; position: relative; transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .particle { position: absolute; width: 8px; height: 8px; border-radius: 50%; background-color: var(--primary-light); opacity: 0; animation: particleAnimation 1s ease-out forwards; } @keyframes particleAnimation { 0% { transform: translate(0, 0) scale(1); opacity: 1; } 100% { transform: translate(var(--tx), var(--ty)) scale(0); opacity: 0; } } .tooltip { position: absolute; background-color: var(--dark); color: white; padding: 0.5rem 0.75rem; border-radius: 0.5rem; font-size: 0.75rem; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; pointer-events: none; z-index: 10; } .tooltip:after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-width: 5px; border-style: solid; border-color: var(--dark) transparent transparent transparent; } .show-tooltip { opacity: 1; transform: translateY(0); } .theme-toggle { position: absolute; top: 1rem; right: 1rem; width: 40px; height: 40px; border-radius: 50%; background: white; box-shadow: 0 2px 8px rgba(0,0,0,0.1); display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 100; transition: all 0.3s ease; } .theme-toggle:hover { transform: rotate(45deg); } .theme-toggle i { font-size: 1.25rem; color: var(--dark); transition: all 0.3s ease; } .dark-mode { background-color: var(--dark); color: var(--light); } .dark-mode .card, .dark-mode .demo-container, .dark-mode .animation-card { background-color: #2D3748; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.2), 0 2px 4px -1px rgba(0, 0, 0, 0.1); } .dark-mode .card h3, .dark-mode .feature-title, .dark-mode .animation-card-title { color: var(--light); } .dark-mode .btn-outline { color: var(--primary-light); border-color: var(--primary-light); } .dark-mode .btn-outline:hover { background-color: var(--primary); color: white; } .dark-mode .theme-toggle { background-color: #2D3748; } .dark-mode .theme-toggle i { color: var(--light); } .dark-mode .header-description, .dark-mode .card p { color: var(--gray-300); } @media (max-width: 600px) { .card-container { grid-template-columns: 1fr; } .progress-steps { display: none; } .container { padding: 1rem; } h1 { font-size: 1.5rem; } } /* Pulse Animation */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } .pulse { animation: pulse 2s infinite; } /* Float Animation */ @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-10px); } 100% { transform: translateY(0px); } } .float { animation: float 3s ease-in-out infinite; } /* Shake Animation */ @keyframes shake { 0%, 100% { transform: translateX(0); } 20%, 60% { transform: translateX(-5px); } 40%, 80% { transform: translateX(5px); } } .shake { animation: shake 0.5s; } /* Success animation overlay */ .success-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(34, 197, 94, 0.1); z-index: 1000; display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .success-overlay.show { opacity: 1; pointer-events: auto; } .success-icon { width: 80px; height: 80px; border-radius: 50%; background-color: var(--success); display: flex; align-items: center; justify-content: center; transform: scale(0); transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .success-overlay.show .success-icon { transform: scale(1); } .checkmark { width: 40px; height: 40px; position: relative; } .checkmark:before, .checkmark:after { content: ""; position: absolute; background-color: white; } .checkmark:before { width: 2px; height: 20px; transform: rotate(-45deg); top: 10px; left: 18px; } .checkmark:after { width: 25px; height: 2px; transform: rotate(45deg); top: 22px; left: 8px; } </style> </head> <body> <div class="container"> <div class="theme-toggle" id="themeToggle"> <i class="theme-icon">☀️</i> </div> <div class="header"> <h1>LearnMotion</h1> <p class="header-description">Interactive animation library designed to enhance learning experiences and boost engagement.</p> </div> <div class="card-container"> <div class="card"> <div class="card-icon">📚</div> <h3>Step-by-Step Guides</h3> <p>Clear, sequenced animations that break down complex concepts into digestible learning paths.</p> <button class="btn btn-outline" data-feature="guides">Explore <span class="btn-icon">→</span></button> </div> <div class="card"> <div class="card-icon">💡</div> <h3>Micro-Interactions</h3> <p>Subtle motion cues that reinforce learning objectives and provide immediate visual feedback.</p> <button class="btn btn-outline" data-feature="micro">Try it <span class="btn-icon">→</span></button> </div> <div class="card"> <div class="card-icon">📊</div> <h3>Animated Assessments</h3> <p>Visualize progress through engaging animated indicators to celebrate learning achievements.</p> <button class="btn btn-outline" data-feature="assessments">View Demo <span class="btn-icon">→</span></button> </div> <div class="card"> <div class="card-icon">🔄</div> <h3>Feedback Loops</h3> <p>Responsive visual elements that adapt to learner interactions, offering real-time guidance.</p> <button class="btn btn-outline" data-feature="feedback">Explore <span class="btn-icon">→</span></button> </div> </div> <div class="feature-section" id="featureSection"> <h2 class="feature-title">Visual Learning Journey</h2> <div class="demo-container" id="demoContainer"> <p>Select a feature above to see its animation demo</p> <!-- Progress Demo (Initially Hidden) --> <div class="progress-demo" id="assessmentsDemo" style="display:none;"> <p>Track learning progress with animated indicators</p> <div class="progress-bar-container"> <div class="progress-bar" id="progressBar"></div> </div> <div class="progress-steps"> <div class="progress-line"> <div class="progress-line-fill" id="progressLineFill"></div> </div> <div class="progress-step" data-step="1"> <div class="step-icon">1</div> <span class="step-label">Intro</span> </div> <div class="progress-step" data-step="2"> <div class="step-icon">2</div> <span class="step-label">Concept</span> </div> <div class="progress-step" data-step="3"> <div class="step-icon">3</div> <span class="step-label">Practice</span> </div> <div class="progress-step" data-step="4"> <div class="step-icon">4</div> <span class="step-label">Master</span> </div> </div> <div class="demo-controls"> <button class="btn btn-primary" id="progressNext">Next Step</button> <button class="btn btn-outline" id="progressReset">Reset</button> </div> </div> <!-- Micro-interactions Demo (Initially Hidden) --> <div class="animation-showcase" id="microDemo" style="display:none;"> <p>Experience subtle, meaningful animations that guide user attention</p> <div class="animation-card"> <div class="animation-card-header"> <span class="animation-card-title">Animation Speed</span> <div class="animation-options"> <div class="animation-option option-slow active" data-speed="slow">S</div> <div class="animation-option option-medium" data-speed="medium">M</div> <div class="animation-option option-fast" data-speed="fast">F</div> </div> </div> <div class="animation-content"> <div class="animation-element" id="animationElement"></div> <div class="particles" id="particles"></div> <div class="tooltip" id="elementTooltip">Click to interact!</div> </div> </div> </div> <!-- Guides Demo (Initially Hidden) --> <div id="guidesDemo" style="display:none;"> <p>Step-by-step animated guides walk learners through complex concepts</p> <div class="animation-card"> <div class="animation-card-header"> <span class="animation-card-title">Learning Sequence</span> </div> <div id="guideSteps" style="margin-top: 1rem;"> <div class="guide-step active" data-step="1"> <div class="step-number">1</div> <div class="step-content"> <h4>Introduction to Concepts</h4> <p>Begin with foundational knowledge</p> </div> </div> </div> <div class="demo-controls"> <button class="btn btn-primary" id="guideNext">Next Step</button> </div> </div> </div> <!-- Feedback Demo (Initially Hidden) --> <div id="feedbackDemo" style="display:none;"> <p>Responsive visual feedback makes learning intuitive</p> <div class="animation-card"> <div class="animation-card-header"> <span class="animation-card-title">Interactive Quiz</span> </div> <div style="margin-top: 1rem;"> <p>Which animation property controls timing?</p> <div class="quiz-options" style="margin-top: 0.75rem;"> <div class="quiz-option" data-correct="false">transform</div> <div class="quiz-option" data-correct="false">opacity</div> <div class="quiz-option" data-correct="true">duration</div> <div class="quiz-option" data-correct="false">position</div> </div> </div> </div> </div> </div> </div> </div> <div class="success-overlay" id="successOverlay"> <div class="success-icon"> <div class="checkmark"></div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Theme Toggle const themeToggle = document.getElementById('themeToggle'); const themeIcon = themeToggle.querySelector('.theme-icon'); themeToggle.addEventListener('click', function() { document.body.classList.toggle('dark-mode'); themeIcon.textContent = document.body.classList.contains('dark-mode') ? '🌙' : '☀️'; }); // Feature Demo Switching const featureButtons = document.querySelectorAll('[data-feature]'); const demoContainer = document.getElementById('demoContainer'); const featureSection = document.getElementById('featureSection'); const featureTitle = document.querySelector('.feature-title'); // All demo divs const assessmentsDemo = document.getElementById('assessmentsDemo'); const microDemo = document.getElementById('microDemo'); const guidesDemo = document.getElementById('guidesDemo'); const feedbackDemo = document.getElementById('feedbackDemo'); // Hide all demos initially function hideAllDemos() { assessmentsDemo.style.display = 'none'; microDemo.style.display = 'none'; guidesDemo.style.display = 'none'; feedbackDemo.style.display = 'none'; } // Feature button click handlers featureButtons.forEach(button => { button.addEventListener('click', function() { const feature = this.dataset.feature; hideAllDemos(); // Update feature title let titleText = 'Visual Learning Journey'; switch(feature) { case 'assessments': assessmentsDemo.style.display = 'block'; titleText = 'Progress Tracking'; break; case 'micro': microDemo.style.display = 'block'; titleText = 'Micro-Interactions'; // Reset tooltip show timer setTimeout(() => { document.getElementById('elementTooltip').classList.add('show-tooltip'); }, 1000); break; case 'guides': guidesDemo.style.display = 'block'; titleText = 'Step-by-Step Guides'; setupGuideDemo(); break; case 'feedback': feedbackDemo.style.display = 'block'; titleText = 'Responsive Feedback'; setupFeedbackDemo(); break; } featureTitle.textContent = titleText; // Smooth scroll to demo section on mobile if (window.innerWidth <= 700) { featureSection.scrollIntoView({ behavior: 'smooth' }); } // Add highlighting effect to the demo container demoContainer.classList.add('pulse'); setTimeout(() => { demoContainer.classList.remove('pulse'); }, 1000); }); }); // Progress Demo const progressBar = document.getElementById('progressBar'); const progressLineFill = document.getElementById('progressLineFill'); const progressSteps = document.querySelectorAll('.progress-step'); const progressNext = document.getElementById('progressNext'); const progressReset = document.getElementById('progressReset'); let currentStep = 0; const totalSteps = progressSteps.length; function updateProgress() { const progressPercentage = (currentStep / totalSteps) * 100; progressBar.style.width = `${progressPercentage}%`; progressLineFill.style.width = `${progressPercentage}%`; // Update step status progressSteps.forEach((step, index) => { const stepNumber = parseInt(step.dataset.step); step.classList.remove('active', 'completed'); if (stepNumber === currentStep) { step.classList.add('active'); } else if (stepNumber < currentStep) { step.classList.add('completed'); } }); // Update button text if (currentStep === totalSteps) { progressNext.textContent = 'Completed!'; showSuccessOverlay(); } else { progressNext.textContent = 'Next Step'; } } progressNext.addEventListener('click', function() { if (currentStep < totalSteps) { currentStep++; updateProgress(); } }); progressReset.addEventListener('click', function() { currentStep = 0; updateProgress(); }); // Animation Element Demo const animationElement = document.getElementById('animationElement'); const particles = document.getElementById('particles'); const elementTooltip = document.getElementById('elementTooltip'); const animationOptions = document.querySelectorAll('.animation-option'); let animationSpeed = 'slow'; animationOptions.forEach(option => { option.addEventListener('click', function() { animationOptions.forEach(opt => opt.classList.remove('active')); this.classList.add('active'); animationSpeed = this.dataset.speed; // Update animation element based on speed animationElement.style.transition = `all ${getSpeedDuration(animationSpeed)}s cubic-bezier(0.175, 0.885, 0.32, 1.275)`; }); }); function getSpeedDuration(speed) { switch(speed) { case 'slow': return 1.5; case 'medium': return 0.8; case 'fast': return 0.3; default: return 1; } } animationElement.addEventListener('click', function() { // Hide tooltip elementTooltip.classList.remove('show-tooltip'); // Apply animation based on current speed const duration = getSpeedDuration(animationSpeed); // Random transform const transforms = [ 'rotate(180deg) scale(1.2)', 'translateY(-30px) rotate(45deg)', 'translateX(30px) scale(0.8)', 'skew(10deg, 10deg) scale(1.1)', 'rotate(-90deg) translateX(-20px)' ]; const randomTransform = transforms[Math.floor(Math.random() * transforms.length)]; this.style.transform = randomTransform; // Create particles createParticles(10); // Reset after animation setTimeout(() => { this.style.transform = 'none'; }, duration * 1000); }); function createParticles(count) { // Clear existing particles particles.innerHTML = ''; for (let i = 0; i < count; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); // Random position const x = 25 + (Math.random() * 50 - 25); const y = 25 + (Math.random() * 50 - 25); // Random direction const tx = (Math.random() - 0.5) * 100; const ty = (Math.random() - 0.5) * 100; particle.style.left = `${x}px`; particle.style.top = `${y}px`; particle.style.setProperty('--tx', `${tx}px`); particle.style.setProperty('--ty', `${ty}px`); // Random color const colors = ['#4F46E5', '#A5B4FC', '#14B8A6', '#FB7185']; particle.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]; particles.appendChild(particle); } } // Show tooltip after some time setTimeout(() => { elementTooltip.classList.add('show-tooltip'); }, 2000); // Guide Steps Demo function setupGuideDemo() { const guideSteps = document.getElementById('guideSteps'); const guideNext = document.getElementById('guideNext'); // Clear existing content guideSteps.innerHTML = ''; // Create steps const steps = [ { title: 'Introduction to Concepts', description: 'Begin with foundational knowledge' }, { title: 'Interactive Exploration', description: 'Engage with key ideas through visual examples' }, { title: 'Practical Application', description: 'Apply concepts through guided exercises' }, { title: 'Knowledge Assessment', description: 'Test understanding with animated quizzes' } ]; // Create initial step steps.forEach((step, index) => { const stepElement = document.createElement('div'); stepElement.classList.add('guide-step'); if (index === 0) stepElement.classList.add('active'); stepElement.dataset.step = index + 1; stepElement.innerHTML = ` <div class="step-number">${index + 1}</div> <div class="step-content"> <h4>${step.title}</h4> <p>${step.description}</p> </div> `; guideSteps.appendChild(stepElement); }); let currentGuideStep = 1; const totalGuideSteps = steps.length; // Style guide steps const guideStepStyles = document.createElement('style'); guideStepStyles.textContent = ` .guide-step { display: flex; align-items: center; margin-bottom: 1rem; padding: 0.75rem; border-radius:
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: #121318; color: #e0e0e0; overflow: hidden; perspective: 1200px; height: 100vh; width: 100%; display: flex; justify-content: center; align-items: center; } .vr-container { position: relative; width: 700px; height: 700px; transform-style: preserve-3d; display: flex; justify-content: center; align-items: center; } .vr-scene { position: relative; width: 600px; height: 600px; transform-style: preserve-3d; display: flex; justify-content: center; align-items: center; transition: transform 0.8s cubic-bezier(0.2, 0.8, 0.2, 1); transform: rotateX(10deg) rotateY(0); } .layer { position: absolute; width: 100%; height: 100%; background: rgba(16, 18, 27, 0.7); border-radius: 20px; transform-style: preserve-3d; box-shadow: 0 0 30px rgba(29, 80, 255, 0.1); backdrop-filter: blur(10px); border: 1px solid rgba(53, 76, 114, 0.3); display: flex; flex-direction: column; justify-content: center; align-items: center; padding: 40px; opacity: 0.9; transition: transform 0.5s ease, opacity 0.5s ease, box-shadow 0.3s ease; } .layer:hover { box-shadow: 0 0 40px rgba(29, 80, 255, 0.3); } .layer-1 { transform: translateZ(0px); } .layer-2 { transform: translateZ(-100px); } .layer-3 { transform: translateZ(-200px); } .layer-4 { transform: translateZ(-300px); } .interactive-element { padding: 15px 30px; background: rgba(32, 37, 55, 0.7); border: 1px solid rgba(87, 119, 235, 0.4); color: #8aafff; border-radius: 10px; margin: 15px 0; cursor: pointer; transform-style: preserve-3d; transition: all 0.3s ease, transform 0.2s ease; position: relative; overflow: hidden; font-weight: 500; letter-spacing: 0.5px; box-shadow: 0 0 20px rgba(29, 80, 255, 0.1); } .interactive-element:hover { background: rgba(47, 57, 92, 0.9); border-color: rgba(87, 119, 235, 0.8); transform: translateY(-5px) scale(1.05); color: #b0cdff; box-shadow: 0 10px 25px rgba(29, 80, 255, 0.2); } .interactive-element:active { transform: translateY(0) scale(0.98); } .interactive-element::before { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: radial-gradient(circle, rgba(87, 119, 235, 0.2) 0%, transparent 70%); transform: scale(0); transition: transform 0.6s ease-out; pointer-events: none; } .interactive-element:hover::before { transform: scale(1); } .element-3d { transform-style: preserve-3d; transition: transform 0.5s ease; } .glow-text { color: #5e81f5; text-shadow: 0 0 10px rgba(94, 129, 245, 0.5); font-weight: 600; } h1 { font-size: 2.5rem; margin-bottom: 20px; background: linear-gradient(to right, #5e81f5, #9fb4ff); -webkit-background-clip: text; background-clip: text; color: transparent; letter-spacing: 1px; } p { line-height: 1.6; margin-bottom: 25px; max-width: 90%; text-align: center; color: #a0a8c0; } .control-panel { position: absolute; bottom: 30px; display: flex; gap: 15px; } .control-btn { background: rgba(29, 32, 47, 0.8); border: 1px solid rgba(87, 119, 235, 0.4); color: #8aafff; border-radius: 50%; width: 50px; height: 50px; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 0 15px rgba(29, 80, 255, 0.1); } .control-btn:hover { background: rgba(47, 57, 92, 0.9); border-color: rgba(87, 119, 235, 0.8); transform: translateY(-3px); box-shadow: 0 5px 15px rgba(29, 80, 255, 0.2); } .control-btn:active { transform: translateY(0); } .particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; z-index: -1; } .particle { position: absolute; width: 3px; height: 3px; background: rgba(87, 119, 235, 0.5); border-radius: 50%; z-index: -1; } .depth-indicator { position: absolute; right: 20px; top: 50%; transform: translateY(-50%); width: 5px; height: 200px; background: rgba(53, 76, 114, 0.3); border-radius: 5px; display: flex; flex-direction: column; justify-content: space-between; padding: 10px 0; } .depth-marker { width: 15px; height: 15px; background: rgba(87, 119, 235, 0.4); border-radius: 50%; margin-left: -5px; transition: all 0.3s ease; } .depth-marker.active { background: rgba(87, 119, 235, 1); box-shadow: 0 0 15px rgba(87, 119, 235, 0.8); } .feature-icon { font-size: 2rem; margin-bottom: 15px; color: #5e81f5; } .hide { opacity: 0; pointer-events: none; } .fade-in { animation: fadeIn 0.8s forwards; } @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .loader { position: absolute; width: 100%; height: 100%; background: #121318; display: flex; justify-content: center; align-items: center; z-index: 100; transition: opacity 0.5s ease; } .loader-circle { width: 80px; height: 80px; border: 4px solid rgba(87, 119, 235, 0.2); border-top: 4px solid rgba(87, 119, 235, 1); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .code-example { background: rgba(25, 28, 39, 0.8); padding: 15px; border-radius: 8px; border-left: 3px solid #5e81f5; font-family: 'Courier New', monospace; margin: 15px 0; width: 100%; overflow-x: auto; color: #b0cdff; font-size: 0.9rem; line-height: 1.5; } @media (max-width: 700px) { .vr-scene { width: 90%; height: 90%; } h1 { font-size: 1.8rem; } .layer { padding: 20px; } .control-panel { bottom: 15px; } .control-btn { width: 40px; height: 40px; } } </style> </head> <body> <div class="loader"> <div class="loader-circle"></div> </div> <div class="particles"></div> <div class="vr-container"> <div class="vr-scene"> <div class="layer layer-1"> <div class="feature-icon">⚡</div> <h1>VR Web Transform</h1> <p>A complete 3D animation framework for seamless transitions between 2D web and immersive VR experiences. Click on any element to see depth-aware interactions.</p> <div class="interactive-element" data-layer="1">Initialize Perspective Transforms</div> <div class="interactive-element" data-layer="1">Enable Spatial Anchoring</div> <div class="code-example">transform: perspective(1000px) rotateX(20deg);</div> </div> <div class="layer layer-2 hide"> <div class="feature-icon">🔄</div> <h1>Layered Depths</h1> <p>Create depth-aware UI components that respond to user perspective. Our Z-axis mapping system provides accurate spatial positioning for all elements.</p> <div class="interactive-element" data-layer="2">Configure Depth Mapping</div> <div class="interactive-element" data-layer="2">Adjust Parallax Settings</div> <div class="code-example">vr.layer.setDepth(element, 200, { easing: 'cubic' });</div> </div> <div class="layer layer-3 hide"> <div class="feature-icon">✨</div> <h1>Spatial Transitions</h1> <p>Smooth animations between perspective shifts maintain user orientation. Our library handles complex vector calculations for seamless depth transitions.</p> <div class="interactive-element" data-layer="3">Generate Spatial Keyframes</div> <div class="interactive-element" data-layer="3">Apply Depth Gradients</div> <div class="code-example">transition: transform 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);</div> </div> <div class="layer layer-4 hide"> <div class="feature-icon">🌐</div> <h1>Interactive Triggers</h1> <p>Create complex event listeners that work across dimensions. Our events system handles perspective shifts and maintains interactive context across layers.</p> <div class="interactive-element" data-layer="4">Register Spatial Event Handlers</div> <div class="interactive-element" data-layer="4">Enable Cross-Layer Interaction</div> <div class="code-example">vr.on('depthshift', (e) => { handleLayerTransition(e); });</div> </div> </div> <div class="control-panel"> <div class="control-btn" id="prev-btn">←</div> <div class="control-btn" id="next-btn">→</div> </div> <div class="depth-indicator"> <div class="depth-marker" data-depth="1"></div> <div class="depth-marker" data-depth="2"></div> <div class="depth-marker" data-depth="3"></div> <div class="depth-marker" data-depth="4"></div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Hide loader after content loads setTimeout(() => { document.querySelector('.loader').style.opacity = '0'; setTimeout(() => { document.querySelector('.loader').style.display = 'none'; }, 500); }, 1000); // Initialize particles const particlesContainer = document.querySelector('.particles'); for (let i = 0; i < 50; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); particle.style.left = `${Math.random() * 100}%`; particle.style.top = `${Math.random() * 100}%`; particle.style.opacity = Math.random() * 0.5 + 0.1; particle.style.width = `${Math.random() * 3 + 1}px`; particle.style.height = particle.style.width; const duration = Math.random() * 60 + 30; particle.style.animation = `float ${duration}s linear infinite`; particlesContainer.appendChild(particle); // Add unique floating animation const keyframes = ` @keyframes float { 0% { transform: translate(0, 0); } 25% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px); } 50% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px); } 75% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 100 - 50}px); } 100% { transform: translate(0, 0); } }`; const style = document.createElement('style'); style.textContent = keyframes; document.head.appendChild(style); } // VR scene navigation let currentLayer = 1; const totalLayers = 4; // Show first layer and its marker document.querySelector(`.layer-${currentLayer}`).classList.remove('hide'); document.querySelector(`.depth-marker[data-depth="${currentLayer}"]`).classList.add('active'); // Setup interactive elements const interactiveElements = document.querySelectorAll('.interactive-element'); interactiveElements.forEach(element => { element.addEventListener('click', function() { this.style.transform = 'translateY(-5px) scale(1.05)'; // Create ripple effect const ripple = document.createElement('div'); ripple.style.position = 'absolute'; ripple.style.width = '5px'; ripple.style.height = '5px'; ripple.style.background = 'rgba(134, 174, 255, 0.8)'; ripple.style.borderRadius = '50%'; ripple.style.top = `${event.offsetY}px`; ripple.style.left = `${event.offsetX}px`; ripple.style.pointerEvents = 'none'; this.appendChild(ripple); // Animate ripple const anim = ripple.animate([ { opacity: 1, transform: 'scale(1)' }, { opacity: 0, transform: 'scale(40)' } ], { duration: 600, easing: 'cubic-bezier(0.2, 0.8, 0.2, 1)' }); anim.onfinish = () => ripple.remove(); // Create floating code effect const codeClone = document.createElement('div'); codeClone.textContent = '{...}'; codeClone.style.position = 'absolute'; codeClone.style.color = '#5e81f5'; codeClone.style.fontSize = '12px'; codeClone.style.top = `${event.offsetY}px`; codeClone.style.left = `${event.offsetX}px`; codeClone.style.pointerEvents = 'none'; this.appendChild(codeClone); const codeAnim = codeClone.animate([ { opacity: 1, transform: 'translateY(0)' }, { opacity: 0, transform: 'translateY(-30px)' } ], { duration: 1000, easing: 'cubic-bezier(0.2, 0.8, 0.2, 1)' }); codeAnim.onfinish = () => codeClone.remove(); setTimeout(() => { this.style.transform = ''; }, 300); }); }); // Navigation buttons document.getElementById('next-btn').addEventListener('click', () => { navigateToLayer(currentLayer + 1); }); document.getElementById('prev-btn').addEventListener('click', () => { navigateToLayer(currentLayer - 1); }); // Depth markers const depthMarkers = document.querySelectorAll('.depth-marker'); depthMarkers.forEach(marker => { marker.addEventListener('click', function() { const depth = parseInt(this.getAttribute('data-depth')); navigateToLayer(depth); }); }); function navigateToLayer(targetLayer) { if (targetLayer < 1 || targetLayer > totalLayers || targetLayer === currentLayer) return; // Hide current layer document.querySelector(`.layer-${currentLayer}`).classList.add('hide'); document.querySelector(`.depth-marker[data-depth="${currentLayer}"]`).classList.remove('active'); // Update current layer currentLayer = targetLayer; // Show new layer with fade-in effect const newLayer = document.querySelector(`.layer-${currentLayer}`); newLayer.classList.remove('hide'); newLayer.classList.add('fade-in'); // Update depth marker document.querySelector(`.depth-marker[data-depth="${currentLayer}"]`).classList.add('active'); // Update scene rotation const scene = document.querySelector('.vr-scene'); scene.style.transform = `rotateX(${10 - (currentLayer - 1) * 5}deg) rotateY(${(currentLayer - 1) * 5}deg)`; setTimeout(() => { newLayer.classList.remove('fade-in'); }, 800); } // Mouse move effect for 3D perspective const container = document.querySelector('.vr-container'); container.addEventListener('mousemove', (e) => { const xAxis = (window.innerWidth / 2 - e.pageX) / 25; const yAxis = (window.innerHeight / 2 - e.pageY) / 25; const scene = document.querySelector('.vr-scene'); scene.style.transform = `rotateX(${10 - (currentLayer - 1) * 5 + yAxis}deg) rotateY(${(currentLayer - 1) * 5 - xAxis}deg)`; }); // Reset on mouse leave container.addEventListener('mouseleave', () => { const scene = document.querySelector('.vr-scene'); scene.style.transform = `rotateX(${10 - (currentLayer - 1) * 5}deg) rotateY(${(currentLayer - 1) * 5}deg)`; }); // Add touch support for mobile let touchStartX, touchStartY; container.addEventListener('touchstart', (e) => { touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; }); container.addEventListener('touchmove', (e) => { if (!touchStartX || !touchStartY) return; const touchX = e.touches[0].clientX; const touchY = e.touches[0].clientY; const xDiff = touchStartX - touchX; const yDiff = touchStartY - touchY; if (Math.abs(xDiff) > Math.abs(yDiff)) { if (xDiff > 10) { // Swipe left navigateToLayer(currentLayer + 1); } else if (xDiff < -10) { // Swipe right navigateToLayer(currentLayer - 1); } } touchStartX = null; touchStartY = null; }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Social Media Feed Animation Library</title> <style> :root { --primary: #5851ff; --secondary: #ff3d79; --tertiary: #15eaca; --light: #f8f9fa; --dark: #2a2a38; --gray: #e9ecef; --gray-dark: #6c757d; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } html, body { height: 100%; background-color: var(--light); color: var(--dark); overflow-x: hidden; } .container { width: 100%; max-width: 700px; margin: 0 auto; padding: 20px; height: 700px; overflow-y: auto; overflow-x: hidden; scrollbar-width: thin; scrollbar-color: var(--primary) var(--light); } .container::-webkit-scrollbar { width: 6px; } .container::-webkit-scrollbar-track { background: var(--light); } .container::-webkit-scrollbar-thumb { background-color: var(--primary); border-radius: 20px; } header { position: sticky; top: 0; background: rgba(255, 255, 255, 0.92); backdrop-filter: blur(8px); padding: 15px 0; margin-bottom: 20px; border-radius: 16px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05); z-index: 100; display: flex; justify-content: space-between; align-items: center; } .logo { font-weight: 800; font-size: 1.5rem; background: linear-gradient(135deg, var(--primary), var(--secondary)); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; display: flex; align-items: center; gap: 10px; } .logo-icon { width: 30px; height: 30px; border-radius: 8px; background: linear-gradient(135deg, var(--primary), var(--secondary)); display: flex; align-items: center; justify-content: center; color: white; font-size: 16px; } .controls { display: flex; gap: 10px; } .control-btn { background: var(--light); border: none; width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; color: var(--dark); font-size: 1.1rem; } .control-btn:hover { background: var(--gray); transform: translateY(-2px); } .active .control-btn { background: var(--primary); color: white; } .feed { display: flex; flex-direction: column; gap: 20px; padding-bottom: 40px; } .post { background: white; border-radius: 16px; overflow: hidden; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06); transform: translateY(40px); opacity: 0; transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); } .post.visible { transform: translateY(0); opacity: 1; } .post-header { display: flex; align-items: center; padding: 16px; gap: 12px; } .profile-pic { width: 42px; height: 42px; border-radius: 50%; background: var(--gray); overflow: hidden; border: 2px solid white; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .profile-pic img { width: 100%; height: 100%; object-fit: cover; } .post-info { flex: 1; } .post-author { font-weight: 600; font-size: 0.95rem; margin-bottom: 2px; color: var(--dark); } .post-time { font-size: 0.8rem; color: var(--gray-dark); } .post-menu { color: var(--gray-dark); cursor: pointer; padding: 5px; border-radius: 50%; transition: all 0.2s ease; } .post-menu:hover { background: var(--gray); color: var(--dark); } .post-content { padding: 0 16px 16px; } .post-text { margin-bottom: 16px; line-height: 1.5; font-size: 0.95rem; } .post-media { border-radius: 12px; overflow: hidden; margin-bottom: 16px; position: relative; } .post-media img, .post-media video { width: 100%; display: block; object-fit: cover; } .carousel { position: relative; overflow: hidden; border-radius: 12px; } .carousel-inner { display: flex; transition: transform 0.5s ease; } .carousel-item { min-width: 100%; height: 300px; } .carousel-item img { width: 100%; height: 100%; object-fit: cover; } .carousel-indicators { position: absolute; bottom: 10px; left: 50%; transform: translateX(-50%); display: flex; gap: 6px; } .indicator { width: 8px; height: 8px; border-radius: 50%; background: rgba(255, 255, 255, 0.6); cursor: pointer; transition: all 0.3s ease; } .indicator.active { background: white; width: 20px; border-radius: 4px; } .carousel-control { position: absolute; top: 50%; transform: translateY(-50%); width: 40px; height: 40px; background: rgba(255, 255, 255, 0.3); backdrop-filter: blur(4px); border-radius: 50%; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 10; opacity: 0; transition: all 0.3s ease; } .carousel:hover .carousel-control { opacity: 1; } .carousel-control.prev { left: 10px; } .carousel-control.next { right: 10px; } .post-actions { display: flex; justify-content: space-between; border-top: 1px solid var(--gray); padding-top: 12px; } .action-group { display: flex; gap: 20px; } .action { display: flex; align-items: center; gap: 6px; color: var(--gray-dark); cursor: pointer; transition: all 0.2s ease; font-size: 0.9rem; } .action:hover { color: var(--primary); } .action.liked { color: var(--secondary); } .action.bookmarked { color: var(--tertiary); } .story-container { display: flex; gap: 12px; padding: 10px 0 20px; overflow-x: auto; scrollbar-width: none; position: relative; } .story-container::-webkit-scrollbar { display: none; } .story { min-width: 80px; display: flex; flex-direction: column; align-items: center; gap: 6px; cursor: pointer; transition: transform 0.3s ease; } .story:hover { transform: translateY(-3px); } .story-avatar { width: 70px; height: 70px; border-radius: 50%; padding: 3px; background: linear-gradient(45deg, var(--primary), var(--secondary), var(--tertiary)); } .story-avatar-inner { width: 100%; height: 100%; border-radius: 50%; border: 3px solid white; overflow: hidden; } .story-avatar-inner img { width: 100%; height: 100%; object-fit: cover; } .story-name { font-size: 0.75rem; color: var(--dark); text-align: center; max-width: 80px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .create-post { background: white; border-radius: 16px; padding: 16px; display: flex; gap: 12px; align-items: center; margin-bottom: 20px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06); } .post-input { flex: 1; background: var(--gray); border: none; border-radius: 30px; padding: 12px 20px; font-size: 0.9rem; transition: all 0.3s ease; } .post-input:focus { outline: none; box-shadow: 0 0 0 2px var(--primary); } .post-options { display: flex; gap: 10px; } .post-option { color: var(--gray-dark); cursor: pointer; transition: all 0.2s ease; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: 50%; } .post-option:hover { background: var(--gray); color: var(--primary); } .skeleton-loader { background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); background-size: 200% 100%; animation: loading 1.5s infinite; border-radius: 4px; } @keyframes loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } .skeleton-avatar { width: 42px; height: 42px; border-radius: 50%; } .skeleton-text { height: 14px; margin-bottom: 8px; width: 80%; } .skeleton-text:last-child { width: 60%; } .notification { position: fixed; bottom: -60px; left: 50%; transform: translateX(-50%); background: rgba(0, 0, 0, 0.8); color: white; padding: 12px 24px; border-radius: 30px; font-size: 0.9rem; transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55); z-index: 1000; } .notification.show { bottom: 20px; } .tag { display: inline-block; background: var(--gray); color: var(--gray-dark); padding: 4px 8px; border-radius: 4px; font-size: 0.8rem; margin-right: 5px; margin-bottom: 5px; cursor: pointer; transition: all 0.2s ease; } .tag:hover { background: var(--primary); color: white; } .trends { background: white; border-radius: 16px; padding: 16px; margin-bottom: 20px; box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06); } .trends-title { font-weight: 700; margin-bottom: 14px; font-size: 1.1rem; } .trend-item { margin-bottom: 12px; cursor: pointer; padding: 8px; border-radius: 8px; transition: all 0.2s ease; } .trend-item:hover { background: var(--gray); } .trend-topic { font-weight: 600; font-size: 0.9rem; margin-bottom: 2px; } .trend-count { font-size: 0.8rem; color: var(--gray-dark); } @media (max-width: 600px) { .container { padding: 10px; } header { padding: 10px 0; } .post-header { padding: 12px; } .post-content { padding: 0 12px 12px; } .carousel-item { height: 200px; } } /* Animation classes */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.05); } 100% { transform: scale(1); } } @keyframes shimmer { 0% { background-position: -100% 0; } 100% { background-position: 100% 0; } } .btn-reaction { background: none; border: none; padding: 0; cursor: pointer; transition: transform 0.2s; } .btn-reaction:hover { transform: scale(1.2); } .btn-reaction.active { animation: pulse 0.3s; } .reaction-animation { position: absolute; pointer-events: none; user-select: none; z-index: 999; font-size: 1.5rem; animation: floatUp 1s ease-out forwards; } @keyframes floatUp { 0% { opacity: 1; transform: translate(-50%, 0); } 100% { opacity: 0; transform: translate(-50%, -50px); } } .like-animation { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0); width: 80px; height: 80px; background: rgba(255, 61, 121, 0.2); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 2rem; color: var(--secondary); opacity: 0; pointer-events: none; z-index: 10; } .like-animation.active { animation: likeEffect 0.8s forwards; } @keyframes likeEffect { 0% { transform: translate(-50%, -50%) scale(0); opacity: 0; } 15% { transform: translate(-50%, -50%) scale(1.2); opacity: 1; } 30% { transform: translate(-50%, -50%) scale(0.9); opacity: 1; } 45% { transform: translate(-50%, -50%) scale(1); opacity: 1; } 80% { transform: translate(-50%, -50%) scale(1); opacity: 1; } 100% { transform: translate(-50%, -50%) scale(0); opacity: 0; } } /* Live Indicator */ .live-indicator { display: inline-flex; align-items: center; background: rgba(255, 61, 121, 0.1); color: var(--secondary); font-size: 0.7rem; padding: 3px 8px; border-radius: 12px; margin-left: 8px; font-weight: 600; } .live-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--secondary); margin-right: 4px; animation: pulseDot 1.5s infinite; } @keyframes pulseDot { 0% { transform: scale(0.8); opacity: 0.8; } 50% { transform: scale(1.2); opacity: 1; } 100% { transform: scale(0.8); opacity: 0.8; } } /* Modal */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(3px); display: flex; align-items: center; justify-content: center; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.3s ease; } .modal.open { opacity: 1; visibility: visible; } .modal-content { background: white; border-radius: 16px; width: 90%; max-width: 500px; max-height: 90vh; overflow-y: auto; transform: scale(0.9); transition: transform 0.3s ease; } .modal.open .modal-content { transform: scale(1); } .modal-header { padding: 16px; border-bottom: 1px solid var(--gray); display: flex; justify-content: space-between; align-items: center; } .modal-title { font-weight: 600; font-size: 1.1rem; } .modal-close { background: none; border: none; font-size: 1.2rem; cursor: pointer; color: var(--gray-dark); } .modal-body { padding: 16px; } .progress-bar { height: 3px; background: var(--gray); border-radius: 2px; overflow: hidden; margin-bottom: 8px; } .progress-fill { height: 100%; background: var(--primary); width: 0; transition: width 0.2s linear; } </style> </head> <body> <div class="container"> <header> <div class="logo"> <div class="logo-icon">P</div> Pulse </div> <div class="controls"> <div class="active"> <button class="control-btn" aria-label="Home"> <i class="fas fa-home"></i> </button> </div> <div> <button class="control-btn" aria-label="Explore"> <i class="fas fa-compass"></i> </button> </div> <div> <button class="control-btn" aria-label="Notifications"> <i class="fas fa-bell"></i> </button> </div> <div> <button class="control-btn" aria-label="Messages"> <i class="fas fa-envelope"></i> </button> </div> </div> </header> <div class="story-container"> <div class="story"> <div class="story-avatar" style="background: linear-gradient(45deg, #4CAF50, #8BC34A);"> <div class="story-avatar-inner"> <img src="https://i.pravatar.cc/150?img=1" alt="Your Story"> </div> </div> <div class="story-name">You</div> </div> <div class="story"> <div class="story-avatar"> <div class="story-avatar-inner"> <img src="https://i.pravatar.cc/150?img=2" alt="Alex"> </div> </div> <div class="story-name">Alex</div> </div> <div class="story"> <div class="story-avatar"> <div class="story-avatar-inner"> <img src="https://i.pravatar.cc/150?img=3" alt="Maya"> </div> </div> <div class="story-name">Maya</div> </div> <div class="story"> <div class="story-avatar"> <div class="story-avatar-inner"> <img src="https://i.pravatar.cc/150?img=4" alt="Jamie"> </div> </div> <div class="story-name">Jamie</div> </div> <div class="story"> <div class="story-avatar"> <div class="story-avatar-inner"> <img src="https://i.pravatar.cc/150?img=5" alt="Taylor"> </div> </div> <div class="story-name">Taylor</div> </div> <div class="story"> <div class="story-avatar"> <div class="story-avatar-inner"> <img src="https://i.pravatar.cc/150?img=6" alt="Jordan"> </div> </div> <div class="story-name">Jordan</div> </div> </div> <div class="create-post"> <div class="profile-pic"> <img src="https://i.pravatar.cc/150?img=1" alt="Your Profile"> </div> <input type="text" class="post-input" placeholder="What's happening?"> <div class="post-options"> <div class="post-option"> <i class="fas fa-image"></i> </div> <div class="post-option"> <i class="fas fa-smile"></i> </div> </div> </div> <div class="trends"> <div class="trends-title">Trending Now</div> <div class="trend-item"> <div class="trend-topic">#SocialMediaDesign</div> <div class="trend-count">24.5K posts</div> </div> <div class="trend-item"> <div class="trend-topic">#AnimationLibrary</div> <div class="trend-count">18.2K posts</div> </div> <div class="trend-item"> <div class="trend-topic">#UXmotion</div> <div class="trend-count">12.7K posts</div> </div> </div> <div class="feed"> <div class="post"> <div class="post-header"> <div class="profile-pic"> <img src="https://i.pravatar.cc/150?img=7" alt="Emma Design"> </div> <div class="post-info"> <div class="post-author">Emma Design <span class="live-indicator"><span class="live-dot"></span>LIVE</span></div> <div class="post-time">2 minutes ago</div> </div> <div class="post-menu"> <i class="fas fa-ellipsis-h"></i> </div> </div> <div class="post-content"> <div class="post-text">Just launched our new dynamic content animation library! Check out these scroll-triggered effects that make social feeds feel more alive 🚀</div> <div class="post-media carousel"> <div class="carousel-inner"> <div class="carousel-item"> <img src="https://images.unsplash.com/photo-1532289608209-64d50da16882?w=800&auto=format&fit=crop&q=80" alt="Animation Demo 1"> </div> <div class="carousel-item"> <img src="https://images.unsplash.com/photo-1580894908361-967195033215?w=800&auto=format&fit=crop&q=80" alt="Animation Demo 2"> </div> <div class="carousel-item"> <img src="https://images.unsplash.com/photo-1558655146-d09347e92766?w=800&auto=format&fit=crop&q=80" alt="Animation Demo 3"> </div> </div> <div class="carousel-indicators"> <div class="indicator active"></div> <div class="indicator"></div> <div class="indicator"></div> </div> <div class="carousel-control prev"> <i class="fas fa-chevron-left"></i> </div> <div class="carousel-control next"> <i class="fas fa-chevron-right"></i> </div> <div class="like-animation"> <i class="fas fa-heart"></i> </div> </div> <div> <span class="tag">#UIAnimation</span> <span class="tag">#DesignSystem</span> <span class="tag">#ScrollEffects</span> </div> </div> <div class="post-actions"> <div class="action-group"> <div class="action like-btn"> <i class="far fa-heart"></i> <span>245</span> </div> <div class="action"> <i class="far fa-comment"></i> <span>42</span> </div> <div class="action"> <i class="far fa-share-square"></i> <span>18</span> </div> </div> <div class="action bookmark-btn"> <i class="far fa-bookmark"></i> </div> </div> </div> <div class="post"> <div class="post-header"> <div class="profile-pic"> <img src="https://i.pravatar.cc/150?img=8" alt="UX Motion"> </div> <div class="post-info"> <div class="post-author">UX Motion</div> <div class="post-time">35 minutes ago</div> </div> <div class="post-menu"> <i class="fas fa-ellipsis-h"></i> </div> </div> <div class="post-content"> <div class="post-text">Subtle bounce and fade animations can increase engagement by 34% according to our latest research. Here's how we implemented them in our feed animation library:</div> <div class="post-media"> <video controls poster="https://images.unsplash.com/photo-1516649195228-a33d09c17933?w=800&auto=format&fit=crop&q=80"> <source src="https://samplelib.com/lib/preview/mp4/sample-5s.mp4" type="video/mp4"> Your browser does not support the video tag. </video> <div class="like-animation"> <i class="fas fa-heart"></i> </div> </div> </div> <div class="post-actions"> <div class="action-group"> <div class="action like-btn"> <i class="far fa-heart"></i> <span>189</span> </div> <div class="action"> <i class="far fa-comment"></i> <span>23</span> </div> <div class="action"> <i class="far fa-share-square"></i> <span>7</span> </div> </div> <div class="action bookmark-btn"> <i class="far fa-bookmark"></i> </div> </div> </div> <div class="post"> <div class="post-header"> <div class="profile-pic"> <img src="https://i.pravatar.cc/150?img=9" alt="Color Theory"> </div> <div class="post-info"> <div class="post-author">Color Theory</div> <div class="post-time">1 hour ago</div> </div> <div class="post-menu"> <i class="fas fa-ellipsis-h"></i> </div> </div> <div class="post-content"> <div class="post-text">The psychology behind energetic color schemes in social feeds: Vibrant colors can reduce bounce rates by 17% and increase time spent in-app. Here's our color palette for the animation library:</div> <div class="post-media"> <img src="https://images.unsplash.com/photo-1550684848-fac1c5b4e853?w=800&auto=format&fit=crop&q=80" alt="Color Palette"> <div class="like-animation"> <i class="fas fa-heart"></i> </div> </div> </div> <div class="post-actions"> <div class="action-group"> <div class="action like-btn"> <i class="far fa-heart"></i> <span>317</span> </div> <div class="action"> <i class="far fa-comment"></i> <span>52</span> </div> <div class="action"> <i class="far fa-share-square"></i> <span>41</span> </div> </div> <div class="action bookmark-btn"> <i class="far fa-bookmark"></i> </div> </div> </div> <div class="post"> <div class="post-header"> <div class="profile-pic"> <img src="https://i.pravatar.cc/150?img=10" alt="Interaction Lab"> </div> <div class="post-info"> <div class="post-author">Interaction Lab</div> <div class="post-time">3 hours ago</div> </div> <div class="post-menu"> <i class="fas fa-ellipsis-h"></i> </div> </div> <div class="post-content"> <div class="post-text">Real-time interactions are key to modern social feeds. Our carousel transitions are optimized for rapid content consumption, with 95% of users engaging with multiple images when presented with smooth transitions.</div> <div class="post-media carousel"> <div class="carousel-inner"> <div class="carousel-item"> <img src="https://images.unsplash.com/photo-1558655146-9f40138edfeb?w=800&auto=format&fit=crop&q=80" alt="Interaction Demo 1"> </div> <div class="carousel-item"> <img src="https://images.unsplash.com/photo-1498049794561-7780e7231661?w=800&auto=format&fit=crop&q=80" alt="Interaction Demo 2"> </div> </div> <div class="carousel-indicators"> <div class="indicator active"></div> <div class="indicator"></div> </div> <div class="carousel-control prev"> <i class="fas fa-chevron-left"></i> </div> <div class="carousel-control next"> <i class="fas fa-chevron-right"></i> </div> <div class="like-animation"> <i class="fas fa-heart"></i> </div> </div> </div> <div class="post-actions"> <div class="action-group"> <div class="action like-btn"> <i class="far fa-heart"></i> <span>208</span> </div> <div class="action"> <i class="far fa-comment"></i> <span>34</span> </div> <div class="action"> <i class="far fa-share-square"></i> <span>12</span> </div> </div> <div class="action bookmark-btn"> <i class="far fa-bookmark"></i> </div> </div> </div> </div> </div> <div class="notification"> New post from Interaction Lab </div> <div class="modal" id="storyModal"> <div class="modal-content"> <div class="progress-bar"> <div class="progress-fill"></div> </div> <div class="modal-header"> <div class="post-header" style="padding: 0;"> <div class="profile-pic"> <img src="https://i.pravatar.cc/150?img=3" alt="Maya"> </div> <div class="post-info"> <div class="post-author">Maya</div> <div class="post-time">35 minutes ago</div> </div> </div> <button class="modal-close">×</button> </div> <div class="modal-body"> <img src="https://images.unsplash.com/photo-1629752187687-3d3c7ea3a5b5?w=800&auto=format&fit=crop&q=80" alt="Story" style="width: 100%; border-radius: 8px;"> </div> </div> </div> <script src="https://kit.fontawesome.com/f1c3d63647.js" crossorigin="anonymous"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Post reveal animation on scroll const posts = document.querySelectorAll('.post'); const options = { root: document.querySelector('.container'), rootMargin: '0px', threshold: 0.1 }; const observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { setTimeout(() => { entry.target.classList.add('visible'); }, 100); observer.unobserve(entry.target); } }); }, options); posts.forEach(post => { observer.observe(post); }); // Carousel functionality const carousels = document.querySelectorAll('.carousel'); carousels.forEach(carousel => { const inner = carousel.querySelector('.carousel-inner'); const items = carousel.querySelectorAll('.carousel-item');
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SaaS Onboarding Animation Library</title> <style> :root { --primary: #6366f1; --primary-dark: #4f46e5; --secondary: #ec4899; --tertiary: #0ea5e9; --background: #f8fafc; --text: #0f172a; --text-light: #64748b; --white: #ffffff; --gray-100: #f1f5f9; --gray-200: #e2e8f0; --radius: 12px; --shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: var(--background); color: var(--text); display: flex; justify-content: center; align-items: center; min-height: 700px; max-width: 700px; margin: 0 auto; padding: 20px; overflow-x: hidden; position: relative; } .container { width: 100%; max-width: 660px; border-radius: var(--radius); background-color: var(--white); box-shadow: var(--shadow); overflow: hidden; position: relative; } header { background: linear-gradient(135deg, var(--primary), var(--primary-dark)); padding: 24px; color: var(--white); text-align: center; position: relative; overflow: hidden; } header h1 { font-size: 1.75rem; font-weight: 700; margin-bottom: 8px; position: relative; z-index: 2; } header p { font-size: 1rem; opacity: 0.9; max-width: 500px; margin: 0 auto; position: relative; z-index: 2; } .bubble { position: absolute; border-radius: 50%; background: rgba(255, 255, 255, 0.1); } .main-content { padding: 30px; } .library-showcase { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 20px; } @media (max-width: 580px) { .library-showcase { grid-template-columns: 1fr; } } .showcase-item { background-color: var(--gray-100); border-radius: var(--radius); padding: 15px; display: flex; flex-direction: column; align-items: center; cursor: pointer; transition: transform 0.3s ease, box-shadow 0.3s ease; position: relative; overflow: hidden; } .showcase-item:hover { transform: translateY(-3px); box-shadow: 0 12px 30px -10px rgba(0, 0, 0, 0.12); } .showcase-item .icon { width: 60px; height: 60px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin-bottom: 12px; position: relative; } .showcase-item h3 { font-size: 1rem; font-weight: 600; margin-bottom: 6px; text-align: center; } .showcase-item p { font-size: 0.875rem; color: var(--text-light); text-align: center; line-height: 1.4; } .tooltip-example .icon { background-color: rgba(236, 72, 153, 0.1); color: var(--secondary); } .progress-example .icon { background-color: rgba(14, 165, 233, 0.1); color: var(--tertiary); } .spotlight-example .icon { background-color: rgba(99, 102, 241, 0.1); color: var(--primary); } .walkthrough-example .icon { background-color: rgba(245, 158, 11, 0.1); color: #f59e0b; } .demo-container { width: 100%; margin-top: 20px; height: 280px; background-color: var(--gray-100); border-radius: var(--radius); padding: 20px; position: relative; overflow: hidden; display: none; } .demo-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; } .demo-title { font-size: 1.125rem; font-weight: 600; } .demo-close { background-color: var(--gray-200); border: none; border-radius: 8px; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background-color 0.2s; } .demo-close:hover { background-color: var(--gray-300); } .demo-content { height: calc(100% - 45px); background-color: var(--white); border-radius: 8px; padding: 15px; position: relative; } /* Tooltip Demo */ .tooltip-demo-content { display: flex; flex-direction: column; gap: 15px; align-items: center; justify-content: center; height: 100%; } .tooltip-example-feature { width: 100%; padding: 12px; border-radius: 8px; background-color: var(--gray-100); display: flex; align-items: center; position: relative; } .tooltip-example-feature:nth-child(2) { opacity: 0.7; } .tooltip-example-feature:nth-child(3) { opacity: 0.5; } .feature-icon { width: 36px; height: 36px; border-radius: 8px; background-color: var(--primary); display: flex; align-items: center; justify-content: center; color: white; margin-right: 12px; flex-shrink: 0; } .feature-text { flex-grow: 1; } .feature-title { font-size: 0.875rem; font-weight: 600; margin-bottom: 2px; } .feature-description { font-size: 0.75rem; color: var(--text-light); } .tooltip { position: absolute; width: 200px; background: var(--text); color: white; padding: 10px 12px; border-radius: 8px; font-size: 0.75rem; top: -15px; left: 55%; transform: translateY(-100%); opacity: 0; visibility: hidden; transition: opacity 0.3s, visibility 0.3s, transform 0.3s; z-index: 5; box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); } .tooltip::after { content: ''; position: absolute; bottom: -6px; left: 20px; width: 12px; height: 12px; background: var(--text); transform: rotate(45deg); } .tooltip.show { opacity: 1; visibility: visible; transform: translateY(-105%); } /* Progress Demo */ .progress-demo-content { display: flex; flex-direction: column; height: 100%; } .progress-steps { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; position: relative; } .progress-line { position: absolute; top: 15px; left: 0; width: 0%; height: 2px; background-color: var(--tertiary); transition: width 0.8s ease; } .progress-step { display: flex; flex-direction: column; align-items: center; position: relative; z-index: 2; } .step-circle { width: 32px; height: 32px; border-radius: 50%; border: 2px solid var(--gray-200); display: flex; align-items: center; justify-content: center; background-color: var(--white); color: var(--text-light); font-size: 0.875rem; font-weight: 600; margin-bottom: 8px; transition: all 0.3s ease; } .step-label { font-size: 0.75rem; color: var(--text-light); transition: color 0.3s ease; } .progress-step.active .step-circle { border-color: var(--tertiary); background-color: var(--tertiary); color: white; } .progress-step.active .step-label { color: var(--tertiary); font-weight: 600; } .progress-step.completed .step-circle { border-color: var(--tertiary); background-color: var(--tertiary); color: white; } .progress-content { flex-grow: 1; display: flex; align-items: center; justify-content: center; } .progress-screen { text-align: center; display: none; opacity: 0; transform: translateY(20px); transition: opacity 0.5s, transform 0.5s; } .progress-screen.active { display: block; opacity: 1; transform: translateY(0); } .progress-controls { display: flex; justify-content: space-between; margin-top: 20px; } .progress-btn { padding: 8px 16px; border-radius: 8px; font-size: 0.875rem; font-weight: 600; cursor: pointer; transition: all 0.2s; } .btn-next { background-color: var(--tertiary); color: white; border: none; } .btn-next:hover { background-color: #0284c7; } .btn-back { background-color: transparent; color: var(--text-light); border: 1px solid var(--gray-200); } .btn-back:hover { background-color: var(--gray-100); } /* Spotlight Demo */ .spotlight-demo-content { display: flex; flex-direction: column; height: 100%; } .app-mockup { display: grid; grid-template-columns: 120px 1fr; gap: 15px; height: 100%; } .sidebar { background-color: var(--gray-100); border-radius: 8px; padding: 12px; display: flex; flex-direction: column; gap: 10px; } .sidebar-item { width: 100%; height: 32px; border-radius: 6px; background-color: var(--white); display: flex; align-items: center; justify-content: center; position: relative; cursor: pointer; } .sidebar-item.active { background-color: var(--primary); color: white; } .content-area { background-color: var(--gray-100); border-radius: 8px; padding: 15px; position: relative; } .content-block { height: 24px; background-color: var(--white); border-radius: 6px; margin-bottom: 8px; } .content-block:nth-child(1) { width: 100%; } .content-block:nth-child(2) { width: 85%; } .content-block:nth-child(3) { width: 70%; } .spotlight-container { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 10; display: none; } .spotlight-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.7); transition: opacity 0.3s; } .spotlight-highlight { position: absolute; background-color: transparent; border-radius: 8px; box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.7); pointer-events: none; transition: all 0.3s ease; } .spotlight-tooltip { position: absolute; background-color: var(--white); color: var(--text); padding: 12px 16px; border-radius: 8px; font-size: 0.875rem; box-shadow: var(--shadow); z-index: 11; width: 200px; pointer-events: auto; } .spotlight-title { font-weight: 600; margin-bottom: 5px; } .spotlight-desc { font-size: 0.75rem; color: var(--text-light); margin-bottom: 10px; } .spotlight-nav { display: flex; justify-content: space-between; align-items: center; } .spotlight-button { background-color: var(--primary); color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 0.75rem; font-weight: 600; cursor: pointer; } .spotlight-skip { background: none; border: none; color: var(--text-light); font-size: 0.75rem; cursor: pointer; } /* Walkthrough Demo */ .walkthrough-demo-content { display: flex; flex-direction: column; height: 100%; position: relative; } .app-screen { display: grid; grid-template-rows: auto 1fr; height: 100%; } .app-header { display: flex; justify-content: space-between; align-items: center; padding-bottom: 10px; border-bottom: 1px solid var(--gray-200); margin-bottom: 15px; } .app-title { font-size: 1rem; font-weight: 600; } .app-actions { display: flex; gap: 8px; } .app-button { width: 24px; height: 24px; border-radius: 6px; background-color: var(--gray-100); display: flex; align-items: center; justify-content: center; } .canvas-area { background-color: var(--gray-100); border-radius: 8px; position: relative; overflow: hidden; height: 100%; } .canvas-object { position: absolute; background-color: var(--white); border-radius: 6px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.06); } .obj-1 { width: 100px; height: 60px; top: 20px; left: 30px; } .obj-2 { width: 80px; height: 80px; top: 60px; right: 40px; } .obj-3 { width: 120px; height: 40px; bottom: 30px; left: 50%; transform: translateX(-50%); } .motion-trail { position: absolute; border-radius: 50%; background-color: var(--primary); opacity: 0; transform: scale(0); } .walkthrough-tooltip { position: absolute; background-color: var(--white); border-radius: 8px; box-shadow: var(--shadow); padding: 12px; z-index: 5; width: 180px; opacity: 0; transform: translateY(10px); transition: opacity 0.3s, transform 0.3s; } .walkthrough-tooltip.show { opacity: 1; transform: translateY(0); } .walkthrough-title { font-size: 0.875rem; font-weight: 600; margin-bottom: 5px; } .walkthrough-desc { font-size: 0.75rem; color: var(--text-light); margin-bottom: 10px; } .walkthrough-button { background-color: var(--primary); color: white; border: none; padding: 5px 10px; border-radius: 6px; font-size: 0.75rem; font-weight: 500; cursor: pointer; width: 100%; } /* Loading animation */ @keyframes pulse { 0% { transform: scale(0.95); opacity: 0.7; } 50% { transform: scale(1); opacity: 1; } 100% { transform: scale(0.95); opacity: 0.7; } } .loading { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.9); display: flex; align-items: center; justify-content: center; z-index: 100; opacity: 0; visibility: hidden; transition: opacity 0.3s, visibility 0.3s; } .loading.show { opacity: 1; visibility: visible; } .loading-spinner { width: 40px; height: 40px; border-radius: 50%; border: 3px solid var(--gray-200); border-top-color: var(--primary); animation: spin 1s infinite linear; } @keyframes spin { to { transform: rotate(360deg); } } .cta { margin-top: 28px; background: linear-gradient(135deg, var(--primary), var(--primary-dark)); border-radius: var(--radius); padding: 16px 20px; display: flex; align-items: center; justify-content: space-between; color: white; } .cta-content h3 { font-size: 1.125rem; font-weight: 700; margin-bottom: 6px; } .cta-content p { font-size: 0.875rem; opacity: 0.9; line-height: 1.4; } .cta-button { background-color: white; color: var(--primary); border: none; border-radius: 8px; padding: 10px 16px; font-size: 0.875rem; font-weight: 600; cursor: pointer; transition: all 0.2s; flex-shrink: 0; } .cta-button:hover { transform: translateY(-2px); box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15); } @media (max-width: 480px) { .cta { flex-direction: column; text-align: center; gap: 16px; } header h1 { font-size: 1.5rem; } .main-content { padding: 20px; } } </style> </head> <body> <div class="container"> <header> <h1>Motion.io</h1> <p>Streamlined SaaS onboarding animation library to boost user adoption</p> <!-- Visual bubbles --> <div class="bubble" style="width: 100px; height: 100px; top: -30px; right: -30px;"></div> <div class="bubble" style="width: 60px; height: 60px; bottom: 20px; left: 10%;"></div> <div class="bubble" style="width: 30px; height: 30px; top: 40%; left: 20%;"></div> </header> <div class="main-content"> <div class="library-showcase"> <div class="showcase-item tooltip-example" id="tooltipExample"> <div class="icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="10"></circle> <line x1="12" y1="16" x2="12" y2="12"></line> <line x1="12" y1="8" x2="12.01" y2="8"></line> </svg> </div> <h3>Smart Tooltips</h3> <p>Contextual help tips that appear when users need guidance</p> </div> <div class="showcase-item progress-example" id="progressExample"> <div class="icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline> </svg> </div> <h3>Progress Trackers</h3> <p>Visual step-by-step guidance through complex workflows</p> </div> <div class="showcase-item spotlight-example" id="spotlightExample"> <div class="icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </div> <h3>Feature Spotlight</h3> <p>Highlight key features with focused overlay tutorials</p> </div> <div class="showcase-item walkthrough-example" id="walkthroughExample"> <div class="icon"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path> <circle cx="8.5" cy="7" r="4"></circle> <line x1="20" y1="8" x2="20" y2="14"></line> <line x1="23" y1="11" x2="17" y2="11"></line> </svg> </div> <h3>Motion Trails</h3> <p>Visual cues that guide users through interactions</p> </div> </div> <div class="demo-container" id="tooltipDemo"> <div class="demo-header"> <div class="demo-title">Smart Tooltips Demo</div> <button class="demo-close" id="tooltipDemoClose"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line> </svg> </button> </div> <div class="demo-content"> <div class="tooltip-demo-content"> <div class="tooltip-example-feature"> <div class="feature-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path> </svg> </div> <div class="feature-text"> <div class="feature-title">Smart notifications</div> <div class="feature-description">Contextual alerts based on user behavior</div> </div> <div class="tooltip" id="firstTooltip"> Tooltips automatically detect when users need help and display relevant information at the exact moment it's needed. </div> </div> <div class="tooltip-example-feature"> <div class="feature-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect> <line x1="3" y1="9" x2="21" y2="9"></line> <line x1="9" y1="21" x2="9" y2="9"></line> </svg> </div> <div class="feature-text"> <div class="feature-title">Dashboard widgets</div> <div class="feature-description">Customizable interface components</div> </div> </div> <div class="tooltip-example-feature"> <div class="feature-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path> </svg> </div> <div class="feature-text"> <div class="feature-title">File management</div> <div class="feature-description">Organize and access documents easily</div> </div> </div> </div> </div> </div> <div class="demo-container" id="progressDemo"> <div class="demo-header"> <div class="demo-title">Progress Tracker Demo</div> <button class="demo-close" id="progressDemoClose"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <line x1="18" y1="6" x2="6" y2="18"></line> <line x1="6" y1="6" x2="18" y2="18"></line> </svg> </button> </div> <div class="demo-content"> <div class="progress-demo-content"> <div class="progress-steps"> <div class="progress-line" id="progressLine"></div> <div class="progress-step active" data-step="1"> <div class="step-circle">1</div> <div class="step-label">Connect</div> </div> <div class="progress-step" data-step="2"> <div class="step-circle">2</div> <div class="step-label">Configure</div> </div> <div class="progress-step" data-step="3"> <div class="step-circle">3</div> <div class="step-label">Customize</div> </div> <div class="progress-step" data-step="4"> <div class="step-circle">4</div> <div class="step-label">Launch</div> </div> </div> <div class="progress-content"> <div class="progress-screen active" data-screen="1"> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#0ea5e9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M5 12h14"></path> <path d="M12 5v14"></path> </svg> <h3 style="margin-top: 10px; margin-bottom: 5px;">Connect your data</h3> <p style="font-size: 0.875rem; color: var(--text-light);">Link your existing data sources to get started</p> </div> <div class="progress-screen" data-screen="2"> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#0ea5e9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="3"></circle> <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path> </svg> <h3 style="margin-top: 10px; margin-bottom: 5px;">Configure settings</h3> <p style="font-size: 0.875rem; color: var(--text-light);">Set up your preferences and parameters</p> </div> <div class="progress-screen" data-screen="3"> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#0ea5e9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M12 20h9"></path> <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path> </svg> <h3 style="margin-top: 10px; margin-bottom: 5px;">Customize appearance</h3> <p style="font-size: 0.875rem; color: var(--text-light);">Personalize your dashboard look and feel</p> </div> <div class="progress-screen" data-screen="4"> <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24"
<html> <head> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Chakra Petch', sans-serif; } body { background-color: #0a0a1a; color: #e6f7ff; overflow: hidden; width: 100%; height: 100vh; display: flex; flex-direction: column; justify-content: center; align-items: center; } @font-face { font-family: 'Chakra Petch'; src: url('https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@400;600;700&display=swap'); } .container { width: 700px; height: 700px; display: flex; flex-direction: column; justify-content: flex-start; align-items: center; position: relative; overflow: hidden; } .background { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, #0a0a1a 0%, #1a1a3a 100%); z-index: -2; } .grid { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(80, 80, 255, 0.05) 1px, transparent 1px), linear-gradient(0deg, rgba(80, 80, 255, 0.05) 1px, transparent 1px); background-size: 20px 20px; z-index: -1; transform: perspective(500px) rotateX(30deg); transform-origin: top; } .particles { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: -1; } .particle { position: absolute; border-radius: 50%; background-color: rgba(255, 255, 255, 0.3); animation: float 8s infinite ease-in-out; } @keyframes float { 0%, 100% { transform: translateY(0) translateX(0); } 50% { transform: translateY(-20px) translateX(10px); } } header { margin-top: 40px; margin-bottom: 20px; text-align: center; } h1 { font-size: 2.8rem; font-weight: 700; margin-bottom: 10px; text-transform: uppercase; letter-spacing: 2px; color: #ff5fa2; text-shadow: 0 0 10px rgba(255, 95, 162, 0.5), 0 0 20px rgba(255, 95, 162, 0.3); animation: pulse 3s infinite; } @keyframes pulse { 0%, 100% { text-shadow: 0 0 10px rgba(255, 95, 162, 0.5), 0 0 20px rgba(255, 95, 162, 0.3); } 50% { text-shadow: 0 0 15px rgba(255, 95, 162, 0.7), 0 0 30px rgba(255, 95, 162, 0.5); } } .tagline { font-size: 1.1rem; font-weight: 400; color: #8af7ff; margin-bottom: 40px; } .menu-container { width: 85%; display: flex; flex-direction: column; gap: 15px; z-index: 1; } .menu-button { position: relative; padding: 15px 20px; background: rgba(30, 30, 80, 0.7); border: 2px solid rgba(80, 80, 255, 0.3); border-radius: 8px; color: #ffffff; font-size: 1.1rem; text-align: left; cursor: pointer; overflow: hidden; transition: all 0.3s ease; display: flex; justify-content: space-between; align-items: center; } .menu-button::before { content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%; background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent); transition: all 0.6s ease; } .menu-button:hover { background: rgba(60, 60, 180, 0.7); border-color: #8af7ff; transform: translateY(-3px); box-shadow: 0 5px 15px rgba(0, 240, 255, 0.3); } .menu-button:hover::before { left: 100%; } .button-label { position: relative; z-index: 1; } .button-icon { width: 24px; height: 24px; display: flex; justify-content: center; align-items: center; color: #8af7ff; transition: transform 0.3s ease; } .menu-button:hover .button-icon { transform: scale(1.2) rotate(90deg); color: #ff5fa2; } .showcase-area { width: 85%; height: 200px; background: rgba(30, 30, 80, 0.5); border: 2px solid rgba(80, 80, 255, 0.3); border-radius: 12px; margin-top: 20px; overflow: hidden; position: relative; display: flex; justify-content: center; align-items: center; z-index: 1; } .showcase-content { text-align: center; } .showcase-title { font-size: 1.4rem; color: #ff5fa2; margin-bottom: 10px; } .showcase-description { color: #8af7ff; font-size: 0.9rem; max-width: 80%; margin: 0 auto; } .effect-dot { position: absolute; background: radial-gradient(circle, #ff5fa2 0%, transparent 70%); border-radius: 50%; pointer-events: none; opacity: 0; transition: opacity 0.8s ease-out; z-index: 0; } footer { position: absolute; bottom: 15px; font-size: 0.8rem; color: rgba(255, 255, 255, 0.5); text-align: center; } .version { margin-top: 5px; font-size: 0.7rem; } @media (max-width: 700px) { h1 { font-size: 2.3rem; } .tagline { font-size: 0.9rem; } .menu-button { padding: 12px 15px; font-size: 1rem; } .showcase-area { height: 180px; } .showcase-title { font-size: 1.2rem; } .showcase-description { font-size: 0.8rem; } } @media (max-width: 480px) { h1 { font-size: 2rem; } .menu-container { width: 90%; } .showcase-area { width: 90%; height: 160px; } } .glitch { animation: glitch 0.3s infinite; display: inline-block; } @keyframes glitch { 0% { transform: translate(0); } 20% { transform: translate(-2px, 2px); } 40% { transform: translate(-2px, -2px); } 60% { transform: translate(2px, 2px); } 80% { transform: translate(2px, -2px); } 100% { transform: translate(0); } } /* Pixelate effect */ .pixelate { animation: pixelate 0.2s ease-out forwards; } @keyframes pixelate { 0% { filter: blur(0); } 50% { filter: blur(1px); } 100% { filter: blur(0); } } </style> </head> <body> <div class="container"> <div class="background"></div> <div class="grid"></div> <div class="particles" id="particles"></div> <header> <h1>ARCADE <span class="glitch">FX</span> PORTAL</h1> <div class="tagline">Level up your UI with retro-inspired animation magic</div> </header> <div class="menu-container"> <button class="menu-button" data-effect="particle-burst"> <span class="button-label">Particle Burst Transitions</span> <span class="button-icon">→</span> </button> <button class="menu-button" data-effect="pixel-dissolve"> <span class="button-label">Pixel Dissolve Effects</span> <span class="button-icon">→</span> </button> <button class="menu-button" data-effect="neon-pulse"> <span class="button-label">Neon Pulse Animations</span> <span class="button-icon">→</span> </button> <button class="menu-button" data-effect="glitch-warp"> <span class="button-label">Glitch Warp Sequences</span> <span class="button-icon">→</span> </button> </div> <div class="showcase-area" id="showcase"> <div class="showcase-content"> <h3 class="showcase-title">Interactive Animation Library</h3> <p class="showcase-description">Select an effect above to preview real-time physics-inspired transitions designed for immersive game menus.</p> </div> </div> <footer> ARCADE FX PORTAL — Your source for game-changing UI animations <div class="version">v1.2.8 | Hover anywhere for particle magic</div> </footer> </div> <script> // Create particles const particlesContainer = document.getElementById('particles'); const particleCount = 15; for (let i = 0; i < particleCount; i++) { const particle = document.createElement('div'); particle.className = 'particle'; // Random size between 3 and 8 const size = Math.floor(Math.random() * 6) + 3; particle.style.width = `${size}px`; particle.style.height = `${size}px`; // Random position const posX = Math.floor(Math.random() * 100); const posY = Math.floor(Math.random() * 100); particle.style.left = `${posX}%`; particle.style.top = `${posY}%`; // Random color const colors = ['#ff5fa2', '#8af7ff', '#ffdb58', '#a17cff']; const randomColor = colors[Math.floor(Math.random() * colors.length)]; particle.style.backgroundColor = randomColor; // Random animation delay const delay = Math.random() * 8; particle.style.animationDelay = `${delay}s`; // Random opacity const opacity = (Math.random() * 0.4) + 0.1; particle.style.opacity = opacity; particlesContainer.appendChild(particle); } // Interactive hover effect document.addEventListener('mousemove', (e) => { // Create dot effect if (Math.random() > 0.85) { // Throttle effect creation const dot = document.createElement('div'); dot.className = 'effect-dot'; // Position at cursor const x = e.clientX; const y = e.clientY; // Adjust position relative to container const container = document.querySelector('.container'); const rect = container.getBoundingClientRect(); dot.style.left = `${x - rect.left}px`; dot.style.top = `${y - rect.top}px`; // Random size const size = Math.floor(Math.random() * 50) + 20; dot.style.width = `${size}px`; dot.style.height = `${size}px`; // Random color const colors = ['rgba(255, 95, 162, 0.3)', 'rgba(138, 247, 255, 0.3)', 'rgba(161, 124, 255, 0.3)']; const randomColor = colors[Math.floor(Math.random() * colors.length)]; dot.style.background = `radial-gradient(circle, ${randomColor} 0%, transparent 70%)`; // Add to container container.appendChild(dot); // Fade in setTimeout(() => { dot.style.opacity = 0.6; }, 10); // Remove after animation setTimeout(() => { dot.style.opacity = 0; setTimeout(() => { container.removeChild(dot); }, 800); }, 800); } }); // Button effects const showcase = document.getElementById('showcase'); const showcaseContent = document.querySelector('.showcase-content'); const buttons = document.querySelectorAll('.menu-button'); buttons.forEach(button => { button.addEventListener('click', () => { // Get effect type const effectType = button.getAttribute('data-effect'); // Apply button animation button.classList.add('pixelate'); setTimeout(() => { button.classList.remove('pixelate'); }, 200); // Update showcase based on effect type updateShowcase(effectType); }); }); function updateShowcase(effectType) { showcase.classList.add('pixelate'); // Content for each effect type const effectContent = { 'particle-burst': { title: 'Particle Burst Transitions', description: 'Dynamic particle explosions for dramatic scene changes. Perfect for level transitions and item reveals.' }, 'pixel-dissolve': { title: 'Pixel Dissolve Effects', description: 'Retro-inspired dissolve effects that transform UI elements with 8-bit precision and nostalgic flair.' }, 'neon-pulse': { title: 'Neon Pulse Animations', description: 'Vibrant, pulsating glow effects that bring arcade energy to buttons, borders, and interactive elements.' }, 'glitch-warp': { title: 'Glitch Warp Sequences', description: 'Cyberpunk-inspired distortion effects that create tension and visual interest during loading states.' } }; // Apply visual effect based on type switch(effectType) { case 'particle-burst': createParticleBurst(); break; case 'pixel-dissolve': createPixelDissolve(); break; case 'neon-pulse': createNeonPulse(); break; case 'glitch-warp': createGlitchEffect(); break; } // Update content setTimeout(() => { showcase.classList.remove('pixelate'); showcaseContent.querySelector('.showcase-title').textContent = effectContent[effectType].title; showcaseContent.querySelector('.showcase-description').textContent = effectContent[effectType].description; }, 200); } function createParticleBurst() { for (let i = 0; i < 30; i++) { const particle = document.createElement('div'); particle.style.position = 'absolute'; particle.style.width = '8px'; particle.style.height = '8px'; particle.style.borderRadius = '50%'; particle.style.backgroundColor = '#ff5fa2'; particle.style.opacity = Math.random() * 0.7 + 0.3; // Center position const x = showcase.offsetWidth / 2; const y = showcase.offsetHeight / 2; particle.style.left = `${x}px`; particle.style.top = `${y}px`; // Random direction const angle = Math.random() * Math.PI * 2; const speed = Math.random() * 80 + 20; const vx = Math.cos(angle) * speed; const vy = Math.sin(angle) * speed; showcase.appendChild(particle); // Animate let startTime = Date.now(); function animate() { const elapsed = (Date.now() - startTime) / 1000; const x_new = x + vx * elapsed; const y_new = y + vy * elapsed; particle.style.left = `${x_new}px`; particle.style.top = `${y_new}px`; particle.style.opacity = Math.max(0, 1 - elapsed); if (elapsed < 1) { requestAnimationFrame(animate); } else { showcase.removeChild(particle); } } requestAnimationFrame(animate); } } function createPixelDissolve() { // Create grid of pixels const pixelSize = 10; const cols = Math.ceil(showcase.offsetWidth / pixelSize); const rows = Math.ceil(showcase.offsetHeight / pixelSize); for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { if (Math.random() > 0.7) { // Only create some pixels for performance const pixel = document.createElement('div'); pixel.style.position = 'absolute'; pixel.style.width = `${pixelSize}px`; pixel.style.height = `${pixelSize}px`; pixel.style.left = `${j * pixelSize}px`; pixel.style.top = `${i * pixelSize}px`; pixel.style.backgroundColor = '#8af7ff'; pixel.style.opacity = Math.random() * 0.7; pixel.style.transition = 'all 0.5s ease'; showcase.appendChild(pixel); // Random disappear time setTimeout(() => { pixel.style.opacity = 0; setTimeout(() => { showcase.removeChild(pixel); }, 500); }, Math.random() * 500); } } } } function createNeonPulse() { // Create neon ring const ring = document.createElement('div'); ring.style.position = 'absolute'; ring.style.width = '10px'; ring.style.height = '10px'; ring.style.borderRadius = '50%'; ring.style.border = '2px solid #8af7ff'; ring.style.boxShadow = '0 0 10px #8af7ff, 0 0 20px #8af7ff'; ring.style.opacity = 0.8; ring.style.left = `${showcase.offsetWidth / 2 - 5}px`; ring.style.top = `${showcase.offsetHeight / 2 - 5}px`; ring.style.transition = 'all 0.8s ease'; showcase.appendChild(ring); // Animate expansion setTimeout(() => { ring.style.width = '200px'; ring.style.height = '200px'; ring.style.left = `${showcase.offsetWidth / 2 - 100}px`; ring.style.top = `${showcase.offsetHeight / 2 - 100}px`; ring.style.opacity = 0; setTimeout(() => { showcase.removeChild(ring); }, 800); }, 10); } function createGlitchEffect() { // Create glitch elements for (let i = 0; i < 10; i++) { const glitchElement = document.createElement('div'); glitchElement.style.position = 'absolute'; glitchElement.style.width = `${Math.random() * 100 + 50}px`; glitchElement.style.height = `${Math.random() * 10 + 2}px`; glitchElement.style.backgroundColor = Math.random() > 0.5 ? '#ff5fa2' : '#8af7ff'; glitchElement.style.left = `${Math.random() * showcase.offsetWidth}px`; glitchElement.style.top = `${Math.random() * showcase.offsetHeight}px`; glitchElement.style.opacity = Math.random() * 0.7 + 0.3; glitchElement.style.transform = `skewX(${Math.random() * 20 - 10}deg)`; glitchElement.style.pointerEvents = 'none'; showcase.appendChild(glitchElement); // Random disappear time setTimeout(() => { showcase.removeChild(glitchElement); }, Math.random() * 400 + 100); } } </script> </body> </html>