Images are a powerful tool in web design, capable of transforming a simple layout into a visually engaging experience. With the right effects, you can make your images stand out and captivate your audience.
In this article, we'll explore 10 image effect examples that can elevate your design and enhance user interaction. From subtle shadows to dynamic animations, these effects will inspire your next 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 image effects effortlessly.
Start for free and elevate your design game 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 design game? With Subframe, you can create stunning, pixel-perfect UIs and image effects in minutes. Our drag-and-drop editor ensures efficiency and precision.
Don't wait—start for free and begin designing immediately. Transform your ideas into reality with Subframe today!
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>E-commerce Product Showcase</title> <style> :root { --primary-color: #2a2a72; --secondary-color: #009ffd; --bg-color: #f8f9fa; --text-color: #333; --light-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; --hover-shadow: rgba(17, 12, 46, 0.15) 0px 48px 100px 0px; --hover-glow: 0 0 15px rgba(0, 159, 253, 0.5); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', 'Helvetica Neue', sans-serif; } body { background-color: var(--bg-color); color: var(--text-color); display: flex; justify-content: center; align-items: center; min-height: 700px; padding: 20px; overflow-x: hidden; } .product-showcase { max-width: 700px; width: 100%; display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 30px; padding: 20px; } .product-card { position: relative; background: white; border-radius: 12px; overflow: hidden; box-shadow: var(--light-shadow); transition: var(--transition); transform: translateY(0); height: 100%; max-height: 500px; display: flex; flex-direction: column; } .product-card:hover { transform: translateY(-10px); box-shadow: var(--hover-shadow); } .product-image-container { position: relative; overflow: hidden; height: 250px; } .product-image { width: 100%; height: 100%; object-fit: cover; transition: var(--transition); } .product-card:hover .product-image { transform: scale(1.05); } .product-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to bottom, transparent 70%, rgba(0, 0, 0, 0.5)); opacity: 0; transition: var(--transition); } .product-card:hover .product-overlay { opacity: 1; } .quick-view-btn { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.8); background: rgba(255, 255, 255, 0.9); color: var(--primary-color); border: none; border-radius: 30px; padding: 10px 20px; font-weight: 600; cursor: pointer; opacity: 0; transition: var(--transition); z-index: 2; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } .product-card:hover .quick-view-btn { opacity: 1; transform: translate(-50%, -50%) scale(1); } .quick-view-btn:hover { background: var(--primary-color); color: white; box-shadow: var(--hover-glow); } .product-info { padding: 20px; flex-grow: 1; display: flex; flex-direction: column; } .product-name { font-size: 1.2rem; font-weight: 600; margin-bottom: 8px; color: var(--text-color); } .product-price { font-size: 1.4rem; font-weight: 700; color: var(--primary-color); margin-bottom: 12px; } .product-description { font-size: 0.9rem; line-height: 1.5; color: #666; margin-bottom: 15px; flex-grow: 1; } .product-features { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 15px; } .feature-tag { background: #f0f0f0; color: #555; font-size: 0.8rem; padding: 4px 8px; border-radius: 4px; display: flex; align-items: center; gap: 4px; transition: var(--transition); } .feature-tag:hover { background: var(--secondary-color); color: white; transform: translateY(-2px); } .feature-tag i { font-size: 0.7rem; } .product-actions { display: flex; justify-content: space-between; align-items: center; } .add-to-cart, .add-to-wishlist { background: none; border: none; cursor: pointer; display: flex; align-items: center; gap: 5px; transition: var(--transition); font-size: 0.9rem; padding: 8px 12px; border-radius: 6px; } .add-to-cart { background: var(--primary-color); color: white; font-weight: 600; } .add-to-cart:hover { background: var(--secondary-color); box-shadow: var(--hover-glow); transform: translateY(-2px); } .add-to-wishlist { color: #666; } .add-to-wishlist:hover { color: #ff3860; } .add-to-wishlist i { transition: var(--transition); } .add-to-wishlist:hover i { transform: scale(1.2); } .color-options { display: flex; gap: 8px; margin-bottom: 15px; } .color-option { width: 20px; height: 20px; border-radius: 50%; border: 2px solid white; box-shadow: 0 0 0 1px #ddd; cursor: pointer; transition: var(--transition); } .color-option:hover { transform: scale(1.2); box-shadow: 0 0 0 1px #999; } .color-option.active { box-shadow: 0 0 0 2px var(--primary-color); } @media (max-width: 600px) { .product-showcase { grid-template-columns: 1fr; } } /* Modal Styles */ .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); display: flex; justify-content: center; align-items: center; z-index: 1000; opacity: 0; visibility: hidden; transition: all 0.3s ease; } .modal.active { opacity: 1; visibility: visible; } .modal-content { background: white; border-radius: 12px; max-width: 90%; width: 600px; max-height: 90vh; overflow-y: auto; transform: scale(0.9); transition: transform 0.3s ease; position: relative; } .modal.active .modal-content { transform: scale(1); } .modal-close { position: absolute; top: 15px; right: 15px; background: none; border: none; font-size: 1.5rem; cursor: pointer; color: #666; z-index: 10; } .modal-body { padding: 30px; } .quick-view-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; } .quick-view-image { width: 100%; height: auto; border-radius: 8px; box-shadow: var(--light-shadow); } .quick-view-details h2 { margin-bottom: 10px; color: var(--primary-color); } .quick-view-price { font-size: 1.4rem; font-weight: 700; color: var(--primary-color); margin-bottom: 15px; } .quick-view-desc { margin-bottom: 20px; line-height: 1.6; } .quantity-selector { display: flex; align-items: center; margin-bottom: 20px; } .quantity-btn { width: 30px; height: 30px; background: #f0f0f0; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; } .quantity-value { width: 40px; height: 30px; text-align: center; border: 1px solid #ddd; margin: 0 5px; } @media (max-width: 768px) { .quick-view-grid { grid-template-columns: 1fr; } } /* Animation for Product Card Entrance */ @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .product-card { animation: fadeInUp 0.6s ease forwards; opacity: 0; } .product-card:nth-child(2) { animation-delay: 0.2s; } .product-card:nth-child(3) { animation-delay: 0.4s; } /* Floating badge animation */ @keyframes float { 0% { transform: translateY(0px); } 50% { transform: translateY(-5px); } 100% { transform: translateY(0px); } } .badge { position: absolute; top: 10px; left: 10px; background: var(--secondary-color); color: white; padding: 5px 10px; border-radius: 4px; font-size: 0.8rem; font-weight: 600; z-index: 2; animation: float 3s ease-in-out infinite; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } /* Loading indicator for add to cart */ .loading-indicator { display: none; width: 16px; height: 16px; border: 2px solid rgba(255,255,255,0.3); border-radius: 50%; border-top-color: white; animation: spin 1s ease infinite; margin-right: 8px; } @keyframes spin { to { transform: rotate(360deg); } } /* 3D tilt effect */ .tilt-effect { transform-style: preserve-3d; perspective: 1000px; } </style> </head> <body> <div class="product-showcase"> <div class="product-card tilt-effect" data-index="1"> <div class="badge">New Arrival</div> <div class="product-image-container"> <img src="https://images.unsplash.com/photo-1599669454699-248893623440?q=80&w=800&auto=format&fit=crop" alt="Minimalist Desk Lamp" class="product-image"> <div class="product-overlay"></div> <button class="quick-view-btn">Quick View</button> </div> <div class="product-info"> <h3 class="product-name">Scandinavian Desk Lamp</h3> <div class="product-price">$89.99</div> <div class="color-options"> <div class="color-option active" style="background-color: #e0e0e0;" data-color="Silver"></div> <div class="color-option" style="background-color: #222222;" data-color="Black"></div> <div class="color-option" style="background-color: #d4a373;" data-color="Walnut"></div> </div> <p class="product-description">Handcrafted adjustable desk lamp with energy-efficient LED bulb. Smooth dimming function with touch control.</p> <div class="product-features"> <span class="feature-tag"><i>⚡</i> Energy Efficient</span> <span class="feature-tag"><i>🔆</i> Adjustable Brightness</span> <span class="feature-tag"><i>🌙</i> Night Mode</span> </div> <div class="product-actions"> <button class="add-to-cart"> <span class="loading-indicator"></span> <span>Add to Cart</span> </button> <button class="add-to-wishlist"> <i>♡</i> </button> </div> </div> </div> <div class="product-card tilt-effect" data-index="2"> <div class="badge">Best Seller</div> <div class="product-image-container"> <img src="https://images.unsplash.com/photo-1618354691373-d851c5c3a990?q=80&w=800&auto=format&fit=crop" alt="Wireless Headphones" class="product-image"> <div class="product-overlay"></div> <button class="quick-view-btn">Quick View</button> </div> <div class="product-info"> <h3 class="product-name">Studio Pro Headphones</h3> <div class="product-price">$149.99</div> <div class="color-options"> <div class="color-option active" style="background-color: #222222;" data-color="Black"></div> <div class="color-option" style="background-color: #ffffff;" data-color="White"></div> <div class="color-option" style="background-color: #6d28d9;" data-color="Purple"></div> </div> <p class="product-description">40mm dynamic drivers with active noise cancellation. 30-hour battery life with quick charge feature.</p> <div class="product-features"> <span class="feature-tag"><i>🔋</i> 30hr Battery</span> <span class="feature-tag"><i>🔇</i> Noise Cancellation</span> <span class="feature-tag"><i>🎙️</i> HD Microphone</span> </div> <div class="product-actions"> <button class="add-to-cart"> <span class="loading-indicator"></span> <span>Add to Cart</span> </button> <button class="add-to-wishlist"> <i>♡</i> </button> </div> </div> </div> </div> <!-- Quick View Modal --> <div class="modal" id="quickViewModal"> <div class="modal-content"> <button class="modal-close">✕</button> <div class="modal-body"> <div class="quick-view-grid"> <img src="" alt="" class="quick-view-image" id="modalImage"> <div class="quick-view-details"> <h2 id="modalTitle"></h2> <div class="quick-view-price" id="modalPrice"></div> <p class="quick-view-desc" id="modalDesc"></p> <div class="quantity-selector"> <button class="quantity-btn" id="decreaseQuantity">-</button> <input type="text" class="quantity-value" id="quantityValue" value="1" readonly> <button class="quantity-btn" id="increaseQuantity">+</button> </div> <button class="add-to-cart">Add to Cart</button> </div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Product data const products = [ { name: "Scandinavian Desk Lamp", price: "$89.99", description: "Handcrafted adjustable desk lamp with energy-efficient LED bulb. The minimalist design features touch dimming control and a USB charging port for your devices. Made with sustainable materials and designed to complement any modern workspace.", image: "https://images.unsplash.com/photo-1599669454699-248893623440?q=80&w=800&auto=format&fit=crop" }, { name: "Studio Pro Headphones", price: "$149.99", description: "Premium wireless headphones with 40mm dynamic drivers and active noise cancellation. Featuring memory foam ear cushions, voice assistant support, and touch controls. The built-in EQ lets you customize your sound profile for the perfect listening experience.", image: "https://images.unsplash.com/photo-1618354691373-d851c5c3a990?q=80&w=800&auto=format&fit=crop" } ]; // Quick View Button Functionality const quickViewBtns = document.querySelectorAll('.quick-view-btn'); const modal = document.getElementById('quickViewModal'); const modalClose = document.querySelector('.modal-close'); const modalImage = document.getElementById('modalImage'); const modalTitle = document.getElementById('modalTitle'); const modalPrice = document.getElementById('modalPrice'); const modalDesc = document.getElementById('modalDesc'); quickViewBtns.forEach((btn, index) => { btn.addEventListener('click', (e) => { e.preventDefault(); const product = products[index]; modalImage.src = product.image; modalImage.alt = product.name; modalTitle.textContent = product.name; modalPrice.textContent = product.price; modalDesc.textContent = product.description; modal.classList.add('active'); document.body.style.overflow = 'hidden'; }); }); modalClose.addEventListener('click', () => { modal.classList.remove('active'); document.body.style.overflow = ''; }); modal.addEventListener('click', (e) => { if (e.target === modal) { modal.classList.remove('active'); document.body.style.overflow = ''; } }); // Color Options Functionality const colorOptions = document.querySelectorAll('.color-option'); colorOptions.forEach(option => { option.addEventListener('click', function() { // Remove active class from all options in this product card const parentCard = this.closest('.product-info'); parentCard.querySelectorAll('.color-option').forEach(opt => { opt.classList.remove('active'); }); // Add active class to clicked option this.classList.add('active'); // Show selected color in toast notification showToast(`Selected: ${this.getAttribute('data-color')}`); }); }); // Quantity Selector Functionality const decreaseBtn = document.getElementById('decreaseQuantity'); const increaseBtn = document.getElementById('increaseQuantity'); const quantityValue = document.getElementById('quantityValue'); decreaseBtn.addEventListener('click', () => { let value = parseInt(quantityValue.value); if (value > 1) { quantityValue.value = value - 1; } }); increaseBtn.addEventListener('click', () => { let value = parseInt(quantityValue.value); quantityValue.value = value + 1; }); // Add to Cart Animation const addToCartBtns = document.querySelectorAll('.add-to-cart'); addToCartBtns.forEach(btn => { btn.addEventListener('click', function() { const loadingIndicator = this.querySelector('.loading-indicator'); const btnText = this.querySelector('span:not(.loading-indicator)'); // Only animate if we have the indicator (main product cards) if (loadingIndicator) { // Show loading loadingIndicator.style.display = 'inline-block'; btnText.textContent = 'Adding...'; // Simulate API call setTimeout(() => { loadingIndicator.style.display = 'none'; btnText.textContent = 'Added ✓'; // Show toast notification showToast('Product added to cart!'); // Reset button after delay setTimeout(() => { btnText.textContent = 'Add to Cart'; }, 2000); }, 1000); } else { // For the modal button this.textContent = 'Added ✓'; showToast('Product added to cart!'); setTimeout(() => { this.textContent = 'Add to Cart'; }, 2000); } }); }); // Wishlist Toggle Functionality const wishlistBtns = document.querySelectorAll('.add-to-wishlist'); wishlistBtns.forEach(btn => { btn.addEventListener('click', function() { const icon = this.querySelector('i'); if (icon.textContent === '♡') { icon.textContent = '♥'; icon.style.color = '#ff3860'; showToast('Added to wishlist!'); } else { icon.textContent = '♡'; icon.style.color = ''; showToast('Removed from wishlist'); } }); }); // Toast Notification Function function showToast(message) { // Remove existing toast if any const existingToast = document.querySelector('.toast'); if (existingToast) { existingToast.remove(); } // Create new toast const toast = document.createElement('div'); toast.className = 'toast'; toast.textContent = message; // Style the toast Object.assign(toast.style, { position: 'fixed', bottom: '20px', left: '50%', transform: 'translateX(-50%)', background: 'rgba(0, 0, 0, 0.8)', color: 'white', padding: '10px 20px', borderRadius: '4px', zIndex: '2000', opacity: '0', transition: 'opacity 0.3s ease' }); // Add toast to DOM document.body.appendChild(toast); // Trigger animation setTimeout(() => { toast.style.opacity = '1'; }, 10); // Remove toast after 3 seconds setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => { toast.remove(); }, 300); }, 3000); } // 3D Tilt Effect on Product Cards const tiltCards = document.querySelectorAll('.tilt-effect'); tiltCards.forEach(card => { card.addEventListener('mousemove', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; const centerX = rect.width / 2; const centerY = rect.height / 2; const angleX = (y - centerY) / 20; const angleY = (centerX - x) / 20; this.style.transform = `rotateX(${angleX}deg) rotateY(${angleY}deg)`; }); card.addEventListener('mouseleave', function() { this.style.transform = 'rotateX(0) rotateY(0)'; }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>SnapFizz - Dynamic Image Effects</title> <style> :root { --primary: #6c5ce7; --secondary: #fd79a8; --accent: #00cec9; --dark: #2d3436; --light: #f9f9f9; --gradient-1: linear-gradient(45deg, #6c5ce7, #fd79a8); --gradient-2: linear-gradient(45deg, #00cec9, #0984e3); --shadow: 0 10px 30px rgba(0, 0, 0, 0.15); --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Poppins', sans-serif; } body { background-color: var(--light); color: var(--dark); overflow: hidden; height: 700px; max-width: 700px; margin: 0 auto; } .app-container { display: flex; flex-direction: column; height: 100%; max-width: 700px; overflow: hidden; position: relative; } .header { padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; background: var(--gradient-1); color: white; border-radius: 0 0 20px 20px; box-shadow: var(--shadow); z-index: 10; height: 70px; } .logo { font-weight: 700; font-size: 24px; display: flex; align-items: center; } .logo span { color: var(--accent); margin-left: 3px; } .main-content { flex: 1; display: flex; flex-direction: column; padding: 20px; overflow-y: auto; gap: 20px; } .intro { text-align: center; margin-bottom: 10px; } .intro h2 { font-size: 1.5rem; margin-bottom: 8px; background: var(--gradient-1); -webkit-background-clip: text; background-clip: text; color: transparent; display: inline-block; } .intro p { color: #666; font-size: 0.9rem; line-height: 1.5; } .canvas-container { position: relative; flex: 1; background: white; border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; display: flex; justify-content: center; align-items: center; min-height: 300px; } #image-canvas { width: 100%; height: 100%; object-fit: contain; position: absolute; top: 0; left: 0; } .upload-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 15px; padding: 20px; text-align: center; color: #888; } .upload-placeholder i { font-size: 40px; color: var(--primary); opacity: 0.5; } .tools-container { display: flex; flex-direction: column; gap: 10px; } .tool-section { background: white; padding: 15px; border-radius: 12px; box-shadow: var(--shadow); } .tool-header { font-weight: 600; margin-bottom: 15px; display: flex; justify-content: space-between; align-items: center; } .tool-header h3 { font-size: 1rem; color: var(--dark); } .stickers-container { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; } .sticker { width: 60px; height: 60px; border-radius: 8px; cursor: pointer; background-size: contain; background-position: center; background-repeat: no-repeat; background-color: #f5f5f5; transition: var(--transition); border: 2px solid transparent; } .sticker:hover { transform: scale(1.05); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); border-color: var(--secondary); } .typography-container { display: flex; gap: 10px; overflow-x: auto; padding: 5px; margin-top: 10px; } .typography-style { padding: 8px 15px; border-radius: 20px; white-space: nowrap; cursor: pointer; transition: var(--transition); background: #f5f5f5; font-size: 14px; } .typography-style:hover { background: var(--gradient-1); color: white; transform: translateY(-2px); } .color-container { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; } .color-option { width: 30px; height: 30px; border-radius: 50%; cursor: pointer; transition: var(--transition); border: 2px solid #eee; } .color-option:hover { transform: scale(1.15); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .action-buttons { display: flex; gap: 10px; margin-top: 20px; } button { padding: 12px 20px; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; transition: var(--transition); display: flex; align-items: center; justify-content: center; gap: 8px; } .btn-primary { background: var(--gradient-1); color: white; flex: 1; } .btn-secondary { background: var(--light); color: var(--dark); border: 1px solid #ddd; } button:hover { transform: translateY(-3px); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); } .btn-reset { background: #ff7675; color: white; } .sticker-element { position: absolute; background-size: contain; background-position: center; background-repeat: no-repeat; cursor: move; z-index: 10; width: 100px; height: 100px; } .text-element { position: absolute; cursor: move; z-index: 20; padding: 10px; min-width: 50px; text-align: center; } .text-element:hover::after, .sticker-element:hover::after { content: '×'; position: absolute; top: -15px; right: -15px; width: 25px; height: 25px; background: #ff7675; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 18px; cursor: pointer; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); } .mobile-scroll-hint { display: none; text-align: center; color: #888; font-size: 0.8rem; padding: 5px; } .confetti { position: absolute; width: 10px; height: 10px; background: var(--primary); border-radius: 50%; animation: fall 3s ease-in-out infinite; pointer-events: none; opacity: 0; } @keyframes fall { 0% { transform: translateY(-100px) rotate(0deg); opacity: 1; } 100% { transform: translateY(500px) rotate(360deg); opacity: 0; } } .text-input { display: flex; margin-top: 10px; gap: 10px; } .text-input input { flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; } .text-input button { padding: 10px 15px; } @media (max-width: 600px) { .header { padding: 10px 15px; height: 60px; } .logo { font-size: 20px; } .main-content { padding: 15px; } .intro h2 { font-size: 1.3rem; } .intro p { font-size: 0.8rem; } .sticker { width: 50px; height: 50px; } .tool-section { padding: 12px; } .tool-header h3 { font-size: 0.9rem; } .mobile-scroll-hint { display: block; } button { padding: 10px 15px; font-size: 0.9rem; } } /* Animated loading indicator */ .loader { display: none; width: 48px; height: 48px; border: 5px solid #FFF; border-bottom-color: var(--primary); border-radius: 50%; box-sizing: border-box; animation: rotation 1s linear infinite; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } @keyframes rotation { 0% { transform: translate(-50%, -50%) rotate(0deg); } 100% { transform: translate(-50%, -50%) rotate(360deg); } } /* Pulse animation for CTA */ @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(108, 92, 231, 0); } 100% { box-shadow: 0 0 0 0 rgba(108, 92, 231, 0); } } .pulse { animation: pulse 2s infinite; } </style> </head> <body> <div class="app-container"> <header class="header"> <div class="logo">Snap<span>Fizz</span></div> <div class="user-info"> <span id="username">Creative Mode</span> </div> </header> <div class="main-content"> <div class="intro"> <h2>Express Your Creativity</h2> <p>Upload a photo and jazz it up with animated stickers, stylish text, and vibrant effects</p> </div> <div class="canvas-container" id="canvas-container"> <div class="upload-placeholder" id="upload-placeholder"> <i>📷</i> <p>Tap to upload an image</p> <small>or drag and drop</small> </div> <img id="image-canvas" style="display: none;"> <div class="loader" id="loader"></div> </div> <div class="tools-container"> <div class="tool-section"> <div class="tool-header"> <h3>Stickers</h3> <small>Drag to position</small> </div> <div class="stickers-container"> <div class="sticker" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUwIDkwQzcyLjA5MTQgOTAgOTAgNzIuMDkxNCA5MCA1MEM5MCAyNy45MDg2IDcyLjA5MTQgMTAgNTAgMTBDMjcuOTA4NiAxMCAxMCAyNy45MDg2IDEwIDUwQzEwIDcyLjA5MTQgMjcuOTA4NiA5MCA1MCA5MFoiIGZpbGw9IiNGRkQ5M0EiLz48Y2lyY2xlIGN4PSIzNiIgY3k9IjQwIiByPSI2IiBmaWxsPSJibGFjayIvPjxjaXJjbGUgY3g9IjY0IiBjeT0iNDAiIHI9IjYiIGZpbGw9ImJsYWNrIi8+PHBhdGggZD0iTTM1IDYwQzM1IDYwIDQyIDcwIDUwIDcwQzU4IDcwIDY1IDYwIDY1IDYwIiBzdHJva2U9ImJsYWNrIiBzdHJva2Utd2lkdGg9IjMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPjwvc3ZnPg==');"></div> <div class="sticker" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUwIDkwQzcyLjA5MTQgOTAgOTAgNzIuMDkxNCA5MCA1MEM5MCAyNy45MDg2IDcyLjA5MTQgMTAgNTAgMTBDMjcuOTA4NiAxMCAxMCAyNy45MDg2IDEwIDUwQzEwIDcyLjA5MTQgMjcuOTA4NiA5MCA1MCA5MFoiIGZpbGw9IiNGRjZCNkIiLz48cGF0aCBkPSJNMzAgNTBMNDAgNjBMNjAgNDBMNzAgNTAiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PC9zdmc+');"></div> <div class="sticker" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTcwIDIwSDMwQzI0LjQ3NzIgMjAgMjAgMjQuNDc3MiAyMCAzMFY3MEMyMCA3NS41MjI4IDI0LjQ3NzIgODAgMzAgODBINzBDNzUuNTIyOCA4MCA4MCA3NS41MjI4IDgwIDcwVjMwQzgwIDI0LjQ3NzIgNzUuNTIyOCAyMCA3MCAyMFoiIGZpbGw9IiM2QzkwRkYiLz48cGF0aCBkPSJNNjUgNDVINTVWMzVINDVWNDVIMzVWNTVINDVWNjVINTVWNTVINjVWNDVaIiBmaWxsPSJ3aGl0ZSIvPjwvc3ZnPg==');"></div> <div class="sticker" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUwIDkwQzcyLjA5MTQgOTAgOTAgNzIuMDkxNCA5MCA1MEM5MCAyNy45MDg2IDcyLjA5MTQgMTAgNTAgMTBDMjcuOTA4NiAxMCAxMCAyNy45MDg2IDEwIDUwQzEwIDcyLjA5MTQgMjcuOTA4NiA5MCA1MCA5MFoiIGZpbGw9IiM5QzI3QjAiLz48cGF0aCBkPSJNMzYgNTBMMjYgNjBMNDAgNzRMNjUgNDlMNTUgMzlMNDAgNTRMMzYgNTBaIiBmaWxsPSJ3aGl0ZSIvPjwvc3ZnPg==');"></div> <div class="sticker" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTI1IDIwTDEwIDUwTDI1IDgwTDc1IDgwTDkwIDUwTDc1IDIwTDI1IDIwWiIgZmlsbD0iIzRDQUY1MCIvPjxwYXRoIGQ9Ik01MCAzMEw2NSA1MEw1MCA3MEwzNSA1MEw1MCAzMFoiIGZpbGw9IndoaXRlIi8+PC9zdmc+');"></div> <div class="sticker" style="background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTUwIDEwTDg3LjU1NyAzMC41NDlMODcuNTU3IDY5LjQ1MUw1MCA5MEwxMi40NDMgNjkuNDUxTDEyLjQ0MyAzMC41NDlMNTAgMTBaIiBmaWxsPSIjRkYzRDAwIi8+PHBhdGggZD0iTTUwIDMwTDU4LjY2IDQyLjk0MUw3MiA0NS42MTJMNjEgNTUuNTU5TDYzLjQxNiA2OUw1MCA2Mi41TDM2LjU4NCA2OUwzOSA1NS41NTlMMjggNDUuNjEyTDQxLjM0IDQyLjk0MUw1MCAzMFoiIGZpbGw9IndoaXRlIi8+PC9zdmc+');"></div> </div> </div> <div class="tool-section"> <div class="tool-header"> <h3>Typography</h3> </div> <div class="text-input"> <input type="text" id="text-input" placeholder="Type your text here..."> <button id="add-text" class="btn-secondary">Add</button> </div> <div class="typography-container"> <div class="typography-style" data-font="'Pacifico', cursive" data-style="text-shadow: 2px 2px 4px rgba(0,0,0,0.3);">Handwritten</div> <div class="typography-style" data-font="'Bebas Neue', sans-serif" data-style="letter-spacing: 2px; text-transform: uppercase;">BOLD</div> <div class="typography-style" data-font="'Dancing Script', cursive" data-style="font-style: italic;">Elegant</div> <div class="typography-style" data-font="monospace" data-style="background: black; color: #0f0; padding: 5px 10px; border-radius: 4px;">Code</div> <div class="typography-style" data-font="'Comic Sans MS', cursive" data-style="transform: rotate(-5deg); display: inline-block;">Fun</div> </div> <div class="mobile-scroll-hint">← Scroll for more options →</div> </div> <div class="tool-section"> <div class="tool-header"> <h3>Color Effects</h3> </div> <div class="color-container"> <div class="color-option" style="background: linear-gradient(45deg, #ff9a9e, #fad0c4);" data-color="linear-gradient(45deg, #ff9a9e, #fad0c4)"></div> <div class="color-option" style="background: linear-gradient(45deg, #a1c4fd, #c2e9fb);" data-color="linear-gradient(45deg, #a1c4fd, #c2e9fb)"></div> <div class="color-option" style="background: linear-gradient(45deg, #d4fc79, #96e6a1);" data-color="linear-gradient(45deg, #d4fc79, #96e6a1)"></div> <div class="color-option" style="background: linear-gradient(45deg, #84fab0, #8fd3f4);" data-color="linear-gradient(45deg, #84fab0, #8fd3f4)"></div> <div class="color-option" style="background: linear-gradient(45deg, #a6c0fe, #f68084);" data-color="linear-gradient(45deg, #a6c0fe, #f68084)"></div> <div class="color-option" style="background: linear-gradient(45deg, #fccb90, #d57eeb);" data-color="linear-gradient(45deg, #fccb90, #d57eeb)"></div> <div class="color-option" style="background: #ff0000;" data-color="#ff0000"></div> <div class="color-option" style="background: #2d88ff;" data-color="#2d88ff"></div> </div> </div> <div class="action-buttons"> <button class="btn-secondary btn-reset" id="reset-button">Reset</button> <input type="file" id="file-input" accept="image/*" style="display: none;"> <button class="btn-primary pulse" id="upload-button">Upload Image</button> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // DOM Elements const canvasContainer = document.getElementById('canvas-container'); const uploadPlaceholder = document.getElementById('upload-placeholder'); const imageCanvas = document.getElementById('image-canvas'); const fileInput = document.getElementById('file-input'); const uploadButton = document.getElementById('upload-button'); const resetButton = document.getElementById('reset-button'); const addTextButton = document.getElementById('add-text'); const textInput = document.getElementById('text-input'); const loader = document.getElementById('loader'); let currentColor = 'transparent'; let currentTypography = { font: 'inherit', style: '' }; let elementCounter = 0; // Event Listeners uploadButton.addEventListener('click', () => fileInput.click()); uploadPlaceholder.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', handleImageUpload); // Handle drag and drop canvasContainer.addEventListener('dragover', (e) => { e.preventDefault(); canvasContainer.style.border = '2px dashed var(--primary)'; }); canvasContainer.addEventListener('dragleave', (e) => { e.preventDefault(); canvasContainer.style.border = 'none'; }); canvasContainer.addEventListener('drop', (e) => { e.preventDefault(); canvasContainer.style.border = 'none'; if (e.dataTransfer.files && e.dataTransfer.files[0]) { handleFile(e.dataTransfer.files[0]); } }); // Reset button event resetButton.addEventListener('click', () => { // Remove all stickers and text elements document.querySelectorAll('.sticker-element, .text-element').forEach(el => el.remove()); // Reset the image if it's present if (imageCanvas.style.display !== 'none') { imageCanvas.style.display = 'none'; uploadPlaceholder.style.display = 'flex'; } // Reset the file input fileInput.value = ''; // Create confetti effect createConfetti(10); }); // Add stickers functionality document.querySelectorAll('.sticker').forEach(sticker => { sticker.addEventListener('click', () => { // Only allow adding stickers when an image is uploaded if (imageCanvas.style.display === 'none') { showNotification('Please upload an image first!'); return; } const stickerId = 'sticker-' + elementCounter++; const stickerElement = document.createElement('div'); stickerElement.className = 'sticker-element'; stickerElement.id = stickerId; stickerElement.style.backgroundImage = sticker.style.backgroundImage; // Position at center stickerElement.style.left = '50%'; stickerElement.style.top = '50%'; stickerElement.style.transform = 'translate(-50%, -50%)'; canvasContainer.appendChild(stickerElement); makeElementDraggable(stickerElement); // Add removal functionality stickerElement.addEventListener('click', (e) => { const deleteBtn = e.target.querySelector('.delete-btn'); if (deleteBtn && e.target === deleteBtn) { stickerElement.remove(); } }); // Create confetti effect createConfetti(5); }); }); // Add text functionality addTextButton.addEventListener('click', () => { const text = textInput.value.trim(); if (!text) { showNotification('Please enter some text!'); return; } // Only allow adding text when an image is uploaded if (imageCanvas.style.display === 'none') { showNotification('Please upload an image first!'); return; } const textId = 'text-' + elementCounter++; const textElement = document.createElement('div'); textElement.className = 'text-element'; textElement.id = textId; textElement.innerText = text; // Apply current typography textElement.style.fontFamily = currentTypography.font; textElement.style.cssText += currentTypography.style; // Apply current color if (currentColor !== 'transparent') { if (currentColor.includes('gradient')) { textElement.style.background = currentColor; textElement.style.webkitBackgroundClip = 'text'; textElement.style.backgroundClip = 'text'; textElement.style.color = 'transparent'; } else { textElement.style.color = currentColor; } } // Position at center textElement.style.left = '50%'; textElement.style.top = '50%'; textElement.style.transform = 'translate(-50%, -50%)'; canvasContainer.appendChild(textElement); makeElementDraggable(textElement); // Clear input textInput.value = ''; // Create confetti effect createConfetti(5); }); // Typography styles document.querySelectorAll('.typography-style').forEach(style => { style.addEventListener('click', () => { // Update current typography currentTypography = { font: style.dataset.font, style: style.dataset.style }; // Show selected style document.querySelectorAll('.typography-style').forEach(s => { s.style.fontWeight = 'normal'; s.style.boxShadow = 'none'; }); style.style.fontWeight = 'bold'; style.style.boxShadow = '0 0 0 2px var(--primary)'; showNotification('Typography style selected!'); }); }); // Color options document.querySelectorAll('.color-option').forEach(option => { option.addEventListener('click', () => { currentColor = option.dataset.color; // Show selected color document.querySelectorAll('.color-option').forEach(o => { o.style.transform = 'scale(1)'; o.style.boxShadow = 'none'; }); option.style.transform = 'scale(1.15)'; option.style.boxShadow = '0 0 0 2px white, 0 0 0 4px var(--primary)'; showNotification('Color selected!'); }); }); // Helper Functions function handleImageUpload(event) { if (event.target.files && event.target.files[0]) { handleFile(event.target.files[0]); } } function handleFile(file) { if (!file.type.match('image.*')) { showNotification('Please select an image file!'); return; } // Show loader loader.style.display = 'block'; const reader = new FileReader(); reader.onload = function(e) { // Hide loader loader.style.display = 'none'; imageCanvas.src = e.target.result; imageCanvas.style.display = 'block'; uploadPlaceholder.style.display = 'none'; // Create confetti effect createConfetti(15); }; reader.readAsDataURL(file); } function makeElementDraggable(element) { let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; element.onmousedown = dragMouseDown; element.ontouchstart = dragTouchStart; function dragMouseDown(e) { e.preventDefault(); // Get the mouse cursor position pos3 = e.clientX; pos4 = e.clientY; document.onmouseup = closeDragElement; document.onmousemove = elementDrag; } function dragTouchStart(e) { e.preventDefault(); // Get the touch position pos3 = e.touches[0].clientX; pos4 = e.touches[0].clientY; document.ontouchend = closeTouchDragElement; document.ontouchmove = elementTouchDrag; } function elementDrag(e) { e.preventDefault(); // Calculate the new cursor position pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY; pos3 = e.clientX; pos4 = e.clientY; // Set the element's new position element.style.top = (element.offsetTop - pos2) + "px"; element.style.left = (element.offsetLeft - pos1) + "px"; // Remove the transform that was initially set element.style.transform = 'none'; } function elementTouchDrag(e) { e.preventDefault(); // Calculate the new touch position pos1 = pos3 - e.touches[0].clientX; pos2 = pos4 - e.touches[0].clientY; pos3 = e.touches[0].clientX; pos4 = e.touches[0].clientY; // Set the element's new position element.style.top = (element.offsetTop - pos2) + "px"; element.style.left = (element.offsetLeft - pos1) + "px"; // Remove the transform that was initially set element.style.transform = 'none'; } function closeDragElement() { // Stop moving when mouse button is released document.onmouseup = null; document.onmousemove = null; } function closeTouchDragElement() { // Stop moving when touch is released document.ontouchend = null; document.ontouchmove = null; } // Add removal functionality element.addEventListener('click', function(e) { // Check if user clicked the after pseudo-element (delete button) const rect = element.getBoundingClientRect(); const deleteButtonX = rect.right - 15; const deleteButtonY = rect.top + 15; // Approximate the click position on the delete button if (Math.abs(e.clientX - deleteButtonX) < 15 && Math.abs(e.clientY - deleteButtonY) < 15) { element.remove(); } }); }
<html> <head> <style> :root { --primary-color: #2c3e50; --accent-color: #e74c3c; --sepia-filter: sepia(0.7) saturate(1.4) brightness(0.95); --cool-filter: hue-rotate(180deg) saturate(1.3) brightness(0.9); --dramatic-filter: contrast(1.3) brightness(0.8) saturate(1.1); --vintage-filter: sepia(0.3) hue-rotate(-30deg) saturate(1.1); --noir-filter: grayscale(1) contrast(1.2); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; } body { background-color: #121212; color: #f5f5f5; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; min-height: 100vh; padding: 20px; overflow-x: hidden; } .platform-header { text-align: center; margin-bottom: 20px; width: 100%; } .platform-header h1 { font-size: 28px; font-weight: 700; margin-bottom: 8px; background: linear-gradient(to right, #ff7e5f, #feb47b); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; letter-spacing: -0.5px; } .platform-header p { font-size: 14px; opacity: 0.8; max-width: 600px; margin: 0 auto; line-height: 1.5; } .thumbnails-container { width: 100%; max-width: 660px; display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px; margin-bottom: 25px; } .thumbnail-wrapper { position: relative; border-radius: 8px; overflow: hidden; cursor: pointer; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); transition: transform 0.3s ease, box-shadow 0.3s ease; } .thumbnail-wrapper:hover { transform: translateY(-5px) scale(1.03); box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3); } .thumbnail-wrapper.selected { outline: 3px solid var(--accent-color); transform: translateY(-5px) scale(1.03); } .thumbnail-wrapper.selected::after { content: "✓"; position: absolute; top: 8px; right: 8px; width: 24px; height: 24px; background-color: var(--accent-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 14px; z-index: 2; } .thumbnail { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; transition: transform 0.5s ease; } .thumbnail-wrapper:hover .thumbnail { transform: scale(1.08); } .thumbnail-info { position: absolute; bottom: 0; left: 0; right: 0; padding: 12px; background: linear-gradient(to top, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0)); transition: opacity 0.3s ease; } .thumbnail-title { font-size: 14px; font-weight: 600; margin-bottom: 4px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .thumbnail-duration { font-size: 12px; opacity: 0.7; } .filters-panel { width: 100%; max-width: 660px; background-color: #1e1e1e; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15); } .filters-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px; } .filters-header h2 { font-size: 18px; font-weight: 600; } .filters-container { display: flex; flex-wrap: wrap; gap: 12px; } .filter-option { display: flex; flex-direction: column; align-items: center; cursor: pointer; transition: transform 0.2s ease; } .filter-option:hover { transform: translateY(-2px); } .filter-option.selected { position: relative; } .filter-option.selected::after { content: ""; position: absolute; bottom: -5px; left: 50%; transform: translateX(-50%); width: 20px; height: 3px; background-color: var(--accent-color); border-radius: 3px; } .filter-preview { width: 80px; height: 45px; border-radius: 4px; overflow: hidden; margin-bottom: 6px; border: 1px solid rgba(255, 255, 255, 0.1); } .filter-preview img { width: 100%; height: 100%; object-fit: cover; } .filter-name { font-size: 12px; opacity: 0.9; } .preview-section { width: 100%; max-width: 660px; background-color: #1e1e1e; border-radius: 12px; padding: 20px; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15); } .preview-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 15px; } .preview-header h2 { font-size: 18px; font-weight: 600; } .preview-image-container { width: 100%; aspect-ratio: 16 / 9; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); } .preview-image { width: 100%; height: 100%; object-fit: cover; transition: filter 0.5s ease; } .apply-button { margin-top: 20px; padding: 12px 24px; background: linear-gradient(to right, #e74c3c, #e83e8c); border: none; border-radius: 6px; color: white; font-weight: 600; cursor: pointer; transition: transform 0.2s ease, box-shadow 0.2s ease; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 10px rgba(232, 62, 140, 0.3); } .apply-button:hover { transform: translateY(-2px); box-shadow: 0 6px 15px rgba(232, 62, 140, 0.4); } .apply-button:active { transform: translateY(0); } .apply-button svg { margin-right: 8px; } .pulse-animation { animation: pulse 1.5s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0.7); } 70% { box-shadow: 0 0 0 10px rgba(231, 76, 60, 0); } 100% { box-shadow: 0 0 0 0 rgba(231, 76, 60, 0); } } .feedback-message { position: fixed; top: 20px; left: 50%; transform: translateX(-50%) translateY(-100px); background-color: #2ecc71; color: white; padding: 12px 24px; border-radius: 8px; font-weight: 500; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; z-index: 1000; } .feedback-message.show { transform: translateX(-50%) translateY(0); opacity: 1; } @media (max-width: 700px) { .thumbnails-container { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; } .filters-container { gap: 8px; } .filter-preview { width: 60px; height: 34px; } .filter-name { font-size: 10px; } .platform-header h1 { font-size: 24px; } .platform-header p { font-size: 12px; } } </style> </head> <body> <div class="platform-header"> <h1>CinemaFX Thumbnail Studio</h1> <p>Transform your content with cinematic filters that enhance visual storytelling and increase viewer engagement.</p> </div> <div class="filters-panel"> <div class="filters-header"> <h2>Cinematic Filters</h2> </div> <div class="filters-container"> <div class="filter-option" data-filter="none"> <div class="filter-preview"> <img src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=150&q=80" alt="Original filter preview"> </div> <span class="filter-name">Original</span> </div> <div class="filter-option selected" data-filter="sepia"> <div class="filter-preview"> <img src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=150&q=80" alt="Sepia filter preview" style="filter: var(--sepia-filter);"> </div> <span class="filter-name">Warm Sepia</span> </div> <div class="filter-option" data-filter="cool"> <div class="filter-preview"> <img src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=150&q=80" alt="Cool filter preview" style="filter: var(--cool-filter);"> </div> <span class="filter-name">Cool Blue</span> </div> <div class="filter-option" data-filter="dramatic"> <div class="filter-preview"> <img src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=150&q=80" alt="Dramatic filter preview" style="filter: var(--dramatic-filter);"> </div> <span class="filter-name">Dramatic</span> </div> <div class="filter-option" data-filter="vintage"> <div class="filter-preview"> <img src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=150&q=80" alt="Vintage filter preview" style="filter: var(--vintage-filter);"> </div> <span class="filter-name">Vintage</span> </div> <div class="filter-option" data-filter="noir"> <div class="filter-preview"> <img src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=150&q=80" alt="Noir filter preview" style="filter: var(--noir-filter);"> </div> <span class="filter-name">Film Noir</span> </div> </div> </div> <div class="thumbnails-container"> <div class="thumbnail-wrapper" data-id="1"> <img class="thumbnail" src="https://images.unsplash.com/photo-1594909122845-11baa439b7bf?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="Surreal desert landscape" style="filter: var(--sepia-filter);"> <div class="thumbnail-info"> <div class="thumbnail-title">Desert Odyssey</div> <div class="thumbnail-duration">12:45</div> </div> </div> <div class="thumbnail-wrapper" data-id="2"> <img class="thumbnail" src="https://images.unsplash.com/photo-1534447677768-be436bb09401?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="Neon city streets" style="filter: var(--sepia-filter);"> <div class="thumbnail-info"> <div class="thumbnail-title">Neon Nights</div> <div class="thumbnail-duration">18:32</div> </div> </div> <div class="thumbnail-wrapper selected" data-id="3"> <img class="thumbnail" src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="Mountain adventure" style="filter: var(--sepia-filter);"> <div class="thumbnail-info"> <div class="thumbnail-title">Summit Seekers</div> <div class="thumbnail-duration">24:17</div> </div> </div> <div class="thumbnail-wrapper" data-id="4"> <img class="thumbnail" src="https://images.unsplash.com/photo-1551018612-9715965c6742?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="Underwater exploration" style="filter: var(--sepia-filter);"> <div class="thumbnail-info"> <div class="thumbnail-title">Deep Blue</div> <div class="thumbnail-duration">15:09</div> </div> </div> <div class="thumbnail-wrapper" data-id="5"> <img class="thumbnail" src="https://images.unsplash.com/photo-1518331647614-7a1f04cd34cf?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="City skyline" style="filter: var(--sepia-filter);"> <div class="thumbnail-info"> <div class="thumbnail-title">Metropolitan</div> <div class="thumbnail-duration">21:38</div> </div> </div> <div class="thumbnail-wrapper" data-id="6"> <img class="thumbnail" src="https://images.unsplash.com/photo-1509316785289-025f5b846b35?ixlib=rb-1.2.1&auto=format&fit=crop&w=400&q=80" alt="Starry night sky" style="filter: var(--sepia-filter);"> <div class="thumbnail-info"> <div class="thumbnail-title">Cosmic Wonders</div> <div class="thumbnail-duration">19:56</div> </div> </div> </div> <div class="preview-section"> <div class="preview-header"> <h2>Live Preview</h2> </div> <div class="preview-image-container"> <img class="preview-image" src="https://images.unsplash.com/photo-1536440136628-849c177e76a1?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Preview of selected thumbnail" style="filter: var(--sepia-filter);"> </div> <button class="apply-button"> <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M20.71 7.04C21.1 6.65 21.1 6.01 20.71 5.63L18.37 3.29C17.99 2.9 17.35 2.9 16.96 3.29L15.13 5.12L18.88 8.87L20.71 7.04ZM3 17.25V21H6.75L17.81 9.94L14.06 6.19L3 17.25Z" fill="white"/> </svg> Apply to Selected </button> </div> <div class="feedback-message">Filter applied successfully!</div> <script> document.addEventListener('DOMContentLoaded', function() { const filterOptions = document.querySelectorAll('.filter-option'); const thumbnails = document.querySelectorAll('.thumbnail'); const thumbnailWrappers = document.querySelectorAll('.thumbnail-wrapper'); const previewImage = document.querySelector('.preview-image'); const applyButton = document.querySelector('.apply-button'); const feedbackMessage = document.querySelector('.feedback-message'); let currentFilter = 'sepia'; let selectedThumbnailId = '3'; // Default selected // Set filters for all thumbnails function applyFilterToAll(filterName) { const filterValue = getFilterValue(filterName); thumbnails.forEach(thumbnail => { thumbnail.style.filter = filterValue; }); previewImage.style.filter = filterValue; } // Get CSS filter value based on filter name function getFilterValue(filterName) { switch(filterName) { case 'none': return 'none'; case 'sepia': return 'var(--sepia-filter)'; case 'cool': return 'var(--cool-filter)'; case 'dramatic': return 'var(--dramatic-filter)'; case 'vintage': return 'var(--vintage-filter)'; case 'noir': return 'var(--noir-filter)'; default: return 'none'; } } // Update preview when thumbnail is selected thumbnailWrappers.forEach(wrapper => { wrapper.addEventListener('click', function() { // Remove selected class from all wrappers thumbnailWrappers.forEach(w => w.classList.remove('selected')); // Add selected class to clicked wrapper this.classList.add('selected'); // Update selected thumbnail ID selectedThumbnailId = this.getAttribute('data-id'); // Update preview image previewImage.src = this.querySelector('.thumbnail').src; previewImage.style.filter = getFilterValue(currentFilter); }); }); // Filter selection filterOptions.forEach(option => { option.addEventListener('click', function() { // Remove selected class from all options filterOptions.forEach(opt => opt.classList.remove('selected')); // Add selected class to clicked option this.classList.add('selected'); // Update current filter currentFilter = this.getAttribute('data-filter'); // Apply selected filter to preview previewImage.style.filter = getFilterValue(currentFilter); }); }); // Apply filter button applyButton.addEventListener('click', function() { // Find the selected thumbnail const selectedThumbnail = document.querySelector(`.thumbnail-wrapper[data-id="${selectedThumbnailId}"]`); if (selectedThumbnail) { // Apply filter to selected thumbnail const thumbnail = selectedThumbnail.querySelector('.thumbnail'); thumbnail.style.filter = getFilterValue(currentFilter); // Show feedback message feedbackMessage.classList.add('show'); // Add pulse animation to selected thumbnail selectedThumbnail.classList.add('pulse-animation'); // Hide feedback message after 2 seconds setTimeout(() => { feedbackMessage.classList.remove('show'); }, 2000); // Remove pulse animation after animation completes setTimeout(() => { selectedThumbnail.classList.remove('pulse-animation'); }, 1500); } }); // Initialize with default filter applyFilterToAll(currentFilter); }); </script> </body> </html>
<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: 'Montserrat', sans-serif; } @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700;800&display=swap'); body { background-color: #121212; color: white; overflow-x: hidden; height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; } .container { width: 100%; max-width: 700px; height: 700px; padding: 20px; overflow: hidden; position: relative; display: flex; flex-direction: column; } .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; z-index: 10; } .logo { font-weight: 800; font-size: 24px; background: linear-gradient(135deg, #FF4D4D, #FF7676); -webkit-background-clip: text; -webkit-text-fill-color: transparent; letter-spacing: 1px; } .menu-btn { width: 40px; height: 40px; background: rgba(255, 255, 255, 0.1); border-radius: 50%; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.3s ease; } .menu-btn:hover { background: rgba(255, 77, 77, 0.3); } .menu-btn span { width: 20px; height: 2px; background-color: white; position: relative; transition: all 0.3s ease; } .menu-btn span:before, .menu-btn span:after { content: ''; position: absolute; width: 20px; height: 2px; background-color: white; transition: all 0.3s ease; } .menu-btn span:before { transform: translateY(-6px); } .menu-btn span:after { transform: translateY(6px); } .menu-btn.active span { background-color: transparent; } .menu-btn.active span:before { transform: rotate(45deg); } .menu-btn.active span:after { transform: rotate(-45deg); } .main-content { flex: 1; display: flex; flex-direction: column; position: relative; z-index: 2; } .effect-showcase { flex: 1; position: relative; border-radius: 20px; overflow: hidden; margin-bottom: 20px; display: flex; align-items: center; justify-content: center; background: #1a1a1a; } .blur-container { width: 100%; height: 100%; position: relative; overflow: hidden; } .main-image, .blur-image { position: absolute; width: 100%; height: 100%; object-fit: cover; transition: opacity 0.5s ease; } .blur-image { filter: blur(8px) brightness(1.3); opacity: 0; transform: scale(1.05); } .controls { position: absolute; bottom: 20px; width: 100%; display: flex; justify-content: center; gap: 15px; z-index: 5; } .control-btn { background: rgba(255, 255, 255, 0.15); border: none; color: white; width: 50px; height: 50px; border-radius: 50%; font-size: 18px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.3s ease; backdrop-filter: blur(5px); } .control-btn:hover { background: rgba(255, 77, 77, 0.6); transform: scale(1.1); } .control-btn.active { background: linear-gradient(135deg, #FF4D4D, #FF7676); box-shadow: 0 0 15px rgba(255, 77, 77, 0.5); } .effect-options { display: flex; gap: 15px; justify-content: center; margin-bottom: 20px; } .effect-btn { padding: 10px 20px; background: rgba(255, 255, 255, 0.1); border: none; color: white; border-radius: 30px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; font-size: 14px; display: flex; align-items: center; gap: 8px; } .effect-btn:hover { background: rgba(255, 77, 77, 0.2); transform: translateY(-2px); } .effect-btn.active { background: linear-gradient(135deg, #FF4D4D, #FF7676); box-shadow: 0 0 15px rgba(255, 77, 77, 0.3); } .effect-btn i { font-size: 16px; } .intensity-slider { width: 100%; max-width: 300px; margin: 0 auto 20px; display: flex; flex-direction: column; align-items: center; gap: 10px; } .intensity-slider label { font-weight: 600; font-size: 14px; color: rgba(255, 255, 255, 0.7); } .slider { -webkit-appearance: none; width: 100%; height: 6px; border-radius: 3px; background: rgba(255, 255, 255, 0.2); outline: none; } .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 20px; height: 20px; border-radius: 50%; background: linear-gradient(135deg, #FF4D4D, #FF7676); cursor: pointer; transition: all 0.2s ease; } .slider::-webkit-slider-thumb:hover { transform: scale(1.2); box-shadow: 0 0 10px rgba(255, 77, 77, 0.5); } .slider::-moz-range-thumb { width: 20px; height: 20px; border-radius: 50%; background: linear-gradient(135deg, #FF4D4D, #FF7676); cursor: pointer; border: none; transition: all 0.2s ease; } .slider::-moz-range-thumb:hover { transform: scale(1.2); box-shadow: 0 0 10px rgba(255, 77, 77, 0.5); } .information { position: absolute; bottom: 0; left: 0; width: 100%; background: linear-gradient(to top, rgba(0, 0, 0, 0.8), transparent); padding: 20px; transform: translateY(100%); transition: transform 0.4s ease; z-index: 4; } .information h3 { font-size: 20px; margin-bottom: 10px; font-weight: 700; color: #FF7676; } .information p { font-size: 14px; margin-bottom: 10px; line-height: 1.5; color: rgba(255, 255, 255, 0.8); } .effect-showcase:hover .information { transform: translateY(0); } .pulse { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 70px; height: 70px; border-radius: 50%; background: rgba(255, 77, 77, 0.5); z-index: 3; display: flex; align-items: center; justify-content: center; animation: pulse 2s infinite; opacity: 0; transition: opacity 0.3s ease; } .play-icon { color: white; font-size: 24px; } @keyframes pulse { 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.7; } 70% { transform: translate(-50%, -50%) scale(1.5); opacity: 0; } 100% { transform: translate(-50%, -50%) scale(1); opacity: 0; } } .effect-showcase:hover .pulse { opacity: 1; } .exercise-tag { position: absolute; top: 20px; left: 20px; background: linear-gradient(135deg, #FF4D4D, #FF7676); color: white; padding: 8px 15px; border-radius: 20px; font-weight: 600; font-size: 12px; box-shadow: 0 5px 15px rgba(255, 77, 77, 0.3); z-index: 4; transform: translateY(-5px); opacity: 0; animation: slideDown 0.5s forwards 0.3s; } @keyframes slideDown { to { transform: translateY(0); opacity: 1; } } .focus-point { position: absolute; width: 100px; height: 100px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.5); box-shadow: 0 0 20px rgba(255, 77, 77, 0.5); z-index: 3; display: none; pointer-events: none; transition: all 0.3s ease; } .motion-path { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 2; pointer-events: none; } .motion-path path { stroke: rgba(255, 77, 77, 0.7); stroke-width: 3; fill: none; stroke-dasharray: 10; stroke-linecap: round; opacity: 0; transition: opacity 0.5s ease; } .effect-showcase:hover .motion-path path { opacity: 0.7; animation: dashMove 3s linear infinite; } @keyframes dashMove { to { stroke-dashoffset: -30; } } .feedback-toast { position: fixed; top: 20px; left: 50%; transform: translateX(-50%) translateY(-100px); background: rgba(0, 0, 0, 0.8); color: white; padding: 15px 30px; border-radius: 30px; font-weight: 600; font-size: 14px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3); z-index: 100; transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); display: flex; align-items: center; gap: 10px; } .feedback-toast.show { transform: translateX(-50%) translateY(0); } .feedback-toast i { color: #FF7676; font-size: 18px; } @media (max-width: 600px) { .effect-options { flex-wrap: wrap; } .effect-btn { font-size: 12px; padding: 8px 16px; } .controls { gap: 10px; } .control-btn { width: 40px; height: 40px; font-size: 16px; } .exercise-tag { top: 10px; left: 10px; font-size: 10px; padding: 6px 12px; } .information h3 { font-size: 18px; } .information p { font-size: 12px; } } /* Animation KeyFrames */ @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideInUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } /* Apply animations to elements */ .header, .effect-options, .intensity-slider { animation: fadeIn 0.5s ease forwards; } .effect-showcase { animation: slideInUp 0.5s ease forwards; } /* Menu styles */ .menu { position: fixed; top: 0; right: -300px; width: 300px; height: 100vh; background: #1a1a1a; z-index: 20; padding: 60px 30px 30px; transition: right 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); box-shadow: -5px 0 30px rgba(0, 0, 0, 0.3); } .menu.open { right: 0; } .menu-close { position: absolute; top: 20px; right: 20px; width: 40px; height: 40px; border-radius: 50%; background: rgba(255, 255, 255, 0.1); display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.3s ease; } .menu-close:hover { background: rgba(255, 77, 77, 0.3); } .menu-close:before, .menu-close:after { content: ''; position: absolute; width: 20px; height: 2px; background: white; } .menu-close:before { transform: rotate(45deg); } .menu-close:after { transform: rotate(-45deg); } .menu-item { padding: 15px 0; border-bottom: 1px solid rgba(255, 255, 255, 0.1); display: flex; align-items: center; gap: 15px; cursor: pointer; transition: all 0.3s ease; } .menu-item:hover { color: #FF7676; transform: translateX(10px); } .menu-item i { font-size: 20px; width: 25px; text-align: center; } .menu-item span { font-weight: 600; } /* Overlay */ .overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 15; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; } .overlay.show { opacity: 1; pointer-events: auto; } </style> </head> <body> <div class="container"> <div class="header"> <div class="logo">FLEXMOTION</div> <div class="menu-btn"> <span></span> </div> </div> <div class="main-content"> <div class="effect-options"> <button class="effect-btn active" data-effect="slowmo"> <i class="fas fa-stopwatch"></i> Slow Motion </button> <button class="effect-btn" data-effect="focus"> <i class="fas fa-bullseye"></i> Focus Shift </button> <button class="effect-btn" data-effect="trail"> <i class="fas fa-fire"></i> Motion Trail </button> </div> <div class="intensity-slider"> <label>Effect Intensity</label> <input type="range" min="1" max="10" value="5" class="slider" id="intensitySlider"> </div> <div class="effect-showcase"> <div class="exercise-tag">Squat Form</div> <div class="blur-container"> <img src="https://images.unsplash.com/photo-1574680178050-55c6a6a96e0a?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80" alt="Squat exercise" class="main-image"> <img src="https://images.unsplash.com/photo-1574680178050-55c6a6a96e0a?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80" alt="Squat exercise blurred" class="blur-image"> </div> <div class="pulse"> <i class="fas fa-play play-icon"></i> </div> <div class="information"> <h3>Perfect Your Squat Form</h3> <p>This dynamic visualization highlights key movement patterns in your squat. Notice how the proper form maintains a neutral spine while driving through the heels.</p> <p>Try performing the movement at 50% speed to master your technique.</p> </div> <div class="focus-point"></div> <svg class="motion-path" viewBox="0 0 400 400"> <path d="M200,300 Q200,150 200,100" /> </svg> <div class="controls"> <button class="control-btn" id="prevBtn"> <i class="fas fa-step-backward"></i> </button> <button class="control-btn active" id="playBtn"> <i class="fas fa-play"></i> </button> <button class="control-btn" id="nextBtn"> <i class="fas fa-step-forward"></i> </button> </div> </div> </div> </div> <div class="menu"> <div class="menu-close"></div> <div class="menu-item"> <i class="fas fa-home"></i> <span>Dashboard</span> </div> <div class="menu-item"> <i class="fas fa-camera"></i> <span>Record Workout</span> </div> <div class="menu-item"> <i class="fas fa-film"></i> <span>My Videos</span> </div> <div class="menu-item"> <i class="fas fa-magic"></i> <span>Effect Library</span> </div> <div class="menu-item"> <i class="fas fa-user"></i> <span>Profile</span> </div> <div class="menu-item"> <i class="fas fa-cog"></i> <span>Settings</span> </div> </div> <div class="overlay"></div> <div class="feedback-toast"> <i class="fas fa-check-circle"></i> <span>Effect applied successfully!</span> </div> <script src="https://kit.fontawesome.com/a076d05399.js" crossorigin="anonymous"></script> <script> document.addEventListener('DOMContentLoaded', function() { // Elements const menuBtn = document.querySelector('.menu-btn'); const menu = document.querySelector('.menu'); const menuClose = document.querySelector('.menu-close'); const overlay = document.querySelector('.overlay'); const effectBtns = document.querySelectorAll('.effect-btn'); const intensitySlider = document.getElementById('intensitySlider'); const playBtn = document.getElementById('playBtn'); const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const feedbackToast = document.querySelector('.feedback-toast'); const blurImage = document.querySelector('.blur-image'); const focusPoint = document.querySelector('.focus-point'); const motionPath = document.querySelector('.motion-path path'); const mainImage = document.querySelector('.main-image'); const exerciseTag = document.querySelector('.exercise-tag'); // Exercise data const exercises = [ { name: 'Squat Form', image: 'https://images.unsplash.com/photo-1574680178050-55c6a6a96e0a?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80', title: 'Perfect Your Squat Form', description: 'This dynamic visualization highlights key movement patterns in your squat. Notice how the proper form maintains a neutral spine while driving through the heels.', tip: 'Try performing the movement at 50% speed to master your technique.', focusX: 200, focusY: 200, path: 'M200,300 Q200,150 200,100' }, { name: 'Deadlift Technique', image: 'https://images.unsplash.com/photo-1534438327276-14e5300c3a48?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80', title: 'Deadlift Power Mechanics', description: 'The visualization emphasizes proper hip hinge and back position during deadlifts to prevent injury and maximize power.', tip: 'Focus on pushing the ground away rather than pulling the weight up.', focusX: 180, focusY: 220, path: 'M200,300 Q200,200 200,100' }, { name: 'Plank Stability', image: 'https://images.unsplash.com/photo-1566241440091-ec10de8db2e1?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80', title: 'Core Engagement in Planks', description: 'See how proper muscle activation distributes tension evenly throughout your core, preventing lower back strain.', tip: 'Pull your belly button toward your spine to maximize core engagement.', focusX: 220, focusY: 180, path: 'M100,200 Q250,200 400,200' } ]; let currentExercise = 0; let currentEffect = 'slowmo'; let isPlaying = false; // Initialize updateExerciseDisplay(); // Menu Toggle menuBtn.addEventListener('click', function() { menuBtn.classList.toggle('active'); menu.classList.toggle('open'); overlay.classList.toggle('show'); }); menuClose.addEventListener('click', function() { menu.classList.remove('open'); overlay.classList.remove('show'); menuBtn.classList.remove('active'); }); overlay.addEventListener('click', function() { menu.classList.remove('open'); overlay.classList.remove('show'); menuBtn.classList.remove('active'); }); // Effect Buttons effectBtns.forEach(btn => { btn.addEventListener('click', function() { // Remove active class from all buttons effectBtns.forEach(b => b.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); // Get effect type currentEffect = this.dataset.effect; // Show toast showToast(`${this.textContent.trim()} effect applied`); // Apply effect applyEffect(); }); }); // Intensity Slider intensitySlider.addEventListener('input', function() { applyEffect(); }); // Play Button playBtn.addEventListener('click', function() { isPlaying = !isPlaying; if (isPlaying) { this.innerHTML = '<i class="fas fa-pause"></i>'; this.classList.add('active'); playEffect(); } else { this.innerHTML = '<i class="fas fa-play"></i>'; this.classList.remove('active'); stopEffect(); } }); // Navigation Buttons prevBtn.addEventListener('click', function() { currentExercise = (currentExercise - 1 + exercises.length) % exercises.length; updateExerciseDisplay(); stopEffect(); resetPlayButton(); }); nextBtn.addEventListener('click', function() { currentExercise = (currentExercise + 1) % exercises.length; updateExerciseDisplay(); stopEffect(); resetPlayButton(); }); // Effect Showcase Interaction document.querySelector('.effect-showcase').addEventListener('mousemove', function(e) { if (currentEffect === 'focus') { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; focusPoint.style.left = `${x - 50}px`; focusPoint.style.top = `${y - 50}px`; } }); // Functions function updateExerciseDisplay() { const exercise = exercises[currentExercise]; // Update images mainImage.src = exercise.image; blurImage.src = exercise.image; // Update text exerciseTag.textContent = exercise.name; document.querySelector('.information h3').textContent = exercise.title; const paragraphs = document.querySelectorAll('.information p'); paragraphs[0].textContent = exercise.description; paragraphs[1].textContent = exercise.tip; // Update focus point and motion path focusPoint.style.left = `${exercise.focusX - 50}px`; focusPoint.style.top = `${exercise.focusY - 50}px`; motionPath.setAttribute('d', exercise.path); // Reset effect applyEffect(); } function applyEffect() { // Hide all effect elements first focusPoint.style.display = 'none'; motionPath.style.opacity = '0'; blurImage.style.opacity = '0'; const intensity = intensitySlider.value / 10; switch (currentEffect) { case 'slowmo': blurImage.style.opacity = intensity.toString(); blurImage.style.filter = `blur(${intensity * 12}px) brightness(1.${Math.round(intensity * 5)})`; break; case 'focus': focusPoint.style.display = 'block'; focusPoint.style.width = `${100 + (intensity * 100)}px`; focusPoint.style.height = `${100 + (intensity * 100)}px`; focusPoint.style.border = `${Math.max(2, Math.round(intensity * 6))}px solid rgba(255, 255, 255, 0.5)`; break; case 'trail': motionPath.style.opacity = '0.7'; motionPath.style.strokeWidth = `${Math.max(2, Math.round(intensity * 8))}`; motionPath.style.strokeDasharray = `${Math.round(intensity * 20)}`; break; } } function playEffect() { switch (currentEffect) { case 'slowmo': animateSlowMo(); break; case 'focus': animateFocusShift(); break; case 'trail': animateMotionTrail(); break; } } function stopEffect() { // Stop all animations isPlaying = false; } function resetPlayButton() { playBtn.innerHTML = '<i class="fas fa-play"></i>'; playBtn.classList.remove('active'); isPlaying = false; } function showToast(message) { const toast = document.querySelector('.feedback-toast'); toast.querySelector('span').textContent = message; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 3000); } // Effect Animations function animateSlowMo() { if (!isPlaying) return; const intensity = intensitySlider.value / 10; let opacity = 0; let increasing = true; const animation = setInterval(() => { if (!isPlaying) { clearInterval(animation); return; } if (increasing) { opacity += 0.01; if (opacity >= intensity) increasing = false; } else { opacity -= 0.01; if (opacity <= 0) increasing = true; } blurImage.style.opacity = opacity.toString(); }, 30); } function animateFocusShift() { if (!isPlaying) return; const exercise = exercises[currentExercise]; const intensity = intensitySlider.value / 10; let t = 0; const animation = setInterval(() => { if (!isPlaying) { clearInterval(animation); return; } t += 0.01; if (t > 1) t = 0; // Move focus point along a path const x = exercise.focusX + Math.sin(t * Math.PI * 2) * 100 * intensity; const y = exercise.focusY + Math.cos(t * Math.PI * 2) * 50 * intensity; focusPoint.style.left = `${x - 50}px`; focusPoint.style.top = `${y - 50}px`; }, 30); } function animateMotionTrail() { if (!isPlaying) return; let dashOffset = 0; const intensity = intensitySlider.value / 10; const animation = setInterval(() => { if (!isPlaying) { clearInterval(animation); return; } dashOffset -= intensity; motionPath.style.strokeDashoffset = dashOffset.toString(); }, 30); } // Initialize first effect applyEffect(); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Wanderlux Effects - Travel Photo Enhancer</title> <style> :root { --primary: #ff7e5f; --secondary: #feb47b; --accent: #ffcc70; --dark: #2a2a2a; --light: #f9f9f9; --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Montserrat', sans-serif; } body { background-color: var(--light); color: var(--dark); height: 100%; width: 100%; overflow-x: hidden; } .container { max-width: 700px; height: 700px; margin: 0 auto; padding: 20px; display: flex; flex-direction: column; overflow: hidden; } .header { text-align: center; margin-bottom: 15px; } h1 { font-size: 28px; background: linear-gradient(to right, var(--primary), var(--secondary)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 5px; letter-spacing: 1px; } p.tagline { font-size: 14px; color: #666; font-style: italic; margin-bottom: 10px; } .image-container { position: relative; width: 100%; height: 350px; overflow: hidden; border-radius: 12px; box-shadow: 0 15px 30px rgba(0, 0, 0, 0.15); transition: transform 0.5s ease; } .image-container:hover { transform: scale(1.02); } #image-preview { width: 100%; height: 100%; object-fit: cover; transition: var(--transition); } .lens-flare { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle at 70% 20%, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0) 25%); mix-blend-mode: screen; opacity: 0; pointer-events: none; transition: var(--transition); } .light-leak { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(45deg, rgba(255, 126, 95, 0.4) 0%, rgba(255, 204, 112, 0) 70%); mix-blend-mode: screen; opacity: 0; pointer-events: none; transition: var(--transition); } .light-leak-2 { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, rgba(254, 180, 123, 0) 30%, rgba(254, 180, 123, 0.3) 100%); mix-blend-mode: screen; opacity: 0; pointer-events: none; transition: var(--transition); } .dust-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFEmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMC0wNy0wNlQxMToxOTozOCswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjAtMDctMDZUMTE6MzE6NDErMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjAtMDctMDZUMTE6MzE6NDErMDg6MDAiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YzI0MGRmNzQtY2FmMy00MjQxLWFiYTYtYWQ5MjdmM2VlNzczIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOmMyNDBkZjc0LWNhZjMtNDI0MS1hYmE2LWFkOTI3ZjNlZTc3MyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOmMyNDBkZjc0LWNhZjMtNDI0MS1hYmE2LWFkOTI3ZjNlZTc3MyI+IDx4bXBNTTpIaXN0b3J5PiA8cmRmOlNlcT4gPHJkZjpsaSBzdEV2dDphY3Rpb249ImNyZWF0ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6YzI0MGRmNzQtY2FmMy00MjQxLWFiYTYtYWQ5MjdmM2VlNzczIiBzdEV2dDp3aGVuPSIyMDIwLTA3LTA2VDExOjE5OjM4KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgKFdpbmRvd3MpIi8+IDwvcmRmOlNlcT4gPC94bXBNTTpIaXN0b3J5PiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrrP240AAAXxSURBVGiBzdpdiF1XFQfw3zr33sw0M2kySWZMJvEjCY1JbBMSMUUhNdra+liqlSKCD32oCEXBUqiCD4IvCj744oMIFUEqIlRFfPBFoQSxRUyamoKfTaxNzEfTJM5kJp259+xx4Zx7750kk5l7Zjr1wM6559y9/mf/z1n/vc4+O8UBf86OXsEDP8G6PLp5hYldk8PryVht30bgxhPLBcmOHMX4s7Rwdm56ZFPt6cU9Mxnf/IO6+z/+5dqNYUxta1m4sK2F0N7X2qE7ix8tjmz+nCW9qe6t9fTGf+6qmenRsdPnDpVfurRn8crpL9unv5Q3//Trq6fV2hzZbuHcXPzmybmpPXo3i8/fdLNNq9PMLg8h93xmGD89VONP02jn1rLwyT9KEHDFS2AjtFmKfS1LJfvKtjy6ccXXC9yw5dgLZX3EWLCj6IKAtsulwKFVW8yt0DNvetO27adHx3a90NbF9squh7e5K59iULwW+OiqbWW7v6jOHcwbTgxveWZ2tHcez7YaYKfkt6VD2BDwYBGwljm70yPLb3nNYt0YNEueeOmJzze/TDnndBGaI4FQqAmlVvouVXE1FqsiCZ2wG7PTmzefu7LZXCa1yXR+Vg8H/K3AGNY3Pnema2x3a+Ps18Y2GZp5ML2Dc6qJZyK8rCjC8fSVhfavCKhIhYoiDqsYyhg8HR7OnNMR2xXtiBKpRMHD5MihbP6h7hT+TQN2KlkP7GjTPkDlcNBoK/YHx8icF0SGai+LOH/u7nzHtv39s+nwnyMf4qMaRlk9KozYz3CuYQHTGJYV7dSuUOUi1W9CHCqHlbmu8EchfLLvZP5G1dRMN/sBRYxoOhKTiuG4mcnC0WKK8O9+Ss8GqTXFj0KoQkxqcVXtDIJ/UapNeMk4kstC9S0hHdNZy3nCeH5YWfnzQTqXcbDpKG0Tevkll5KsXRHv6kvDTnHICg8ixiQ3IUKVR8KGQ8HugWlDJ1MfjHYjSI1Y+MWEmVBeK6DBVVZSlqtdV1CXGlIUuGidTR5ZB8slYhPqGnrBFI6k4OtlUT8cJZH11dWCXBxR+ApfkNVmGJNdkQzHawQu1wa5CqEP2G5gGttr1++OZeVo6CSlN9oqhCJ0wq5YuxY8gFwl/TZWW66Qep8yCKXacKeR3uUh+Gc4MHCIhHFrqU3TaKVvoeqXDRIZBg8B3/Vu9jo/7IMtmprNrqw9iDDzXozCXUYnv5Jvubo1hNDJVMbNNzXXfuEPRK27tUhUGTcSxkBHphv80U+35gYf0lVLMEBqZSZRkKpCKXvMkip+DIbwcPTWYVzSesC85okaV57UIzSPSJbHG/GqJfqDCFe7M60sZKTXy5buRdipCbGgFV1Nh+3GYeA1xKjdytIxJEGCW6IV0ZXdiiJ9aMVvXs+E5Na0DtleFgJDzdecZWPMylLdrG/6XYrRKh3l6sV9oDjuCvlFYlJt4EwdrbOXJBgpNFqZhTYEIisZ15iPLnxYLVh73Zj2zG33QpXyN7Sg9cuJaDW8xSy9NSc+Nca1GHMi/9JVWRqfUaeObYRKoZXihaQu+ZCQKSaFmv6z1y2wGrUVA4cDTIWKlFt3hEJNy7UVo6W2+e+VS8NF5lQj0f9zcehIVnDjjR75O+JqbTXbEtdKnJ12xJAjCadhRsGMVibRnajTi6WO1ycZ/nkwnzvqxJRWfXq4VroyCZHH2njtUuNXVdlrYLlDsSSLRjbEe+NOSfCF4F2tFnysavKGI6OlnTpUo+3VIHCWuzgd0k1JVvhpVI26SMXuqFrEwWTmSsYU8X4ztDlmPB3Icp3D5Ta0M5n78mvmCj6UyvzPYtxT3OHFa6DxFP6YLjvHF1beWt/2W1wWm4awGPtlbRkndsdMQyc14OciThU1/qG2lS5fVJMnBe0I03RjGGO9GvtrA5CuhNqd8DfgWQ9Ac71K1axoNTXJ1qfuBJcuRvoP4NUk+E/AAx5m/j+Oe16+hn3LzwAAAABJRU5ErkJggg=='); background-size: 200px; opacity: 0; mix-blend-mode: overlay; pointer-events: none; transition: var(--transition); } .image-gallery { display: flex; gap: 10px; margin-top: 15px; overflow-x: auto; padding-bottom: 10px; -ms-overflow-style: none; scrollbar-width: none; } .image-gallery::-webkit-scrollbar { display: none; } .gallery-item { min-width: 80px; height: 60px; border-radius: 6px; overflow: hidden; cursor: pointer; position: relative; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); transition: transform 0.3s ease; } .gallery-item:hover { transform: translateY(-3px); } .gallery-item img { width: 100%; height: 100%; object-fit: cover; } .gallery-item.active { border: 2px solid var(--primary); } .controls { margin-top: 15px; } .sliders { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px; } .slider-container { display: flex; flex-direction: column; } .slider-label { display: flex; justify-content: space-between; font-size: 12px; margin-bottom: 5px; color: #555; } .slider-label span:last-child { color: var(--primary); font-weight: 600; } input[type="range"] { -webkit-appearance: none; width: 100%; height: 6px; background: #e0e0e0; border-radius: 3px; outline: none; } input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 18px; height: 18px; background: linear-gradient(to right, var(--primary), var(--secondary)); border-radius: 50%; cursor: pointer; transition: all 0.2s ease; } input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.1); } .preset-buttons { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; } .preset-btn { padding: 8px 14px; background: #fff; color: var(--dark); border: 1px solid #ddd; border-radius: 20px; cursor: pointer; font-size: 12px; transition: all 0.2s ease; flex-grow: 1; text-align: center; } .preset-btn:hover { background: #f0f0f0; transform: translateY(-2px); } .preset-btn.active { background: linear-gradient(to right, var(--primary), var(--secondary)); color: white; border: none; } .save-btn { display: block; width: 100%; padding: 12px; background: linear-gradient(to right, var(--primary), var(--secondary)); color: white; border: none; border-radius: 6px; font-size: 16px; font-weight: 600; cursor: pointer; margin-top: 15px; transition: all 0.3s ease; box-shadow: 0 4px 15px rgba(255, 126, 95, 0.3); } .save-btn:hover { transform: translateY(-3px); box-shadow: 0 6px 20px rgba(255, 126, 95, 0.4); } .notification { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%) translateY(100px); background: rgba(42, 42, 42, 0.9); color: white; padding: 12px 20px; border-radius: 30px; font-size: 14px; opacity: 0; transition: all 0.5s ease; z-index: 1000; } .notification.show { transform: translateX(-50%) translateY(0); opacity: 1; } @media (max-width: 500px) { .container { padding: 15px; } h1 { font-size: 24px; } .image-container { height: 250px; } .sliders { grid-template-columns: 1fr; } } /* Animate pulse effect on load */ @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.03); } 100% { transform: scale(1); } } .pulse { animation: pulse 1.5s ease-in-out; } /* Mouse move light effect */ .cursor-light { position: absolute; width: 150px; height: 150px; border-radius: 50%; background: radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0) 70%); pointer-events: none; mix-blend-mode: screen; opacity: 0; transition: opacity 0.3s ease; } </style> </head> <body> <div class="container"> <div class="header"> <h1>Wanderlux Effects</h1> <p class="tagline">Transform your travel memories with nostalgic light effects</p> </div> <div class="image-container" id="image-container"> <img id="image-preview" src="https://images.unsplash.com/photo-1520466809213-7b9a56adcd45?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80" alt="Bali Beach Sunset"> <div class="lens-flare" id="lens-flare"></div> <div class="light-leak" id="light-leak"></div> <div class="light-leak-2" id="light-leak-2"></div> <div class="dust-overlay" id="dust-overlay"></div> <div class="cursor-light" id="cursor-light"></div> </div> <div class="image-gallery" id="image-gallery"> <div class="gallery-item active" data-img="https://images.unsplash.com/photo-1520466809213-7b9a56adcd45?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80"> <img src="https://images.unsplash.com/photo-1520466809213-7b9a56adcd45?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80" alt="Bali Beach"> </div> <div class="gallery-item" data-img="https://images.unsplash.com/photo-1533105079780-92b9be482077?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80"> <img src="https://images.unsplash.com/photo-1533105079780-92b9be482077?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1287&q=80" alt="Beach Sunset"> </div> <div class="gallery-item" data-img="https://images.unsplash.com/photo-1530789253388-582c481c54b0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80"> <img src="https://images.unsplash.com/photo-1530789253388-582c481c54b0?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80" alt="Desert Road"> </div> <div class="gallery-item" data-img="https://images.unsplash.com/photo-1611043714658-af3e56bc5299?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80"> <img src="https://images.unsplash.com/photo-1611043714658-af3e56bc5299?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80" alt="Mountains"> </div> <div class="gallery-item" data-img="https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80"> <img src="https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1170&q=80" alt="Coast Highway"> </div> </div> <div class="controls"> <div class="sliders"> <div class="slider-container"> <div class="slider-label"> <span>Light Leak</span> <span id="light-leak-value">35%</span> </div> <input type="range" id="light-leak-slider" min="0" max="100" value="35"> </div> <div class="slider-container"> <div class="slider-label"> <span>Lens Flare</span> <span id="lens-flare-value">40%</span> </div> <input type="range" id="lens-flare-slider" min="0" max="100" value="40"> </div> <div class="slider-container"> <div class="slider-label"> <span>Warmth</span> <span id="warmth-value">25%</span> </div> <input type="range" id="warmth-slider" min="0" max="100" value="25"> </div> <div class="slider-container"> <div class="slider-label"> <span>Vintage Dust</span> <span id="dust-value">20%</span> </div> <input type="range" id="dust-slider" min="0" max="100" value="20"> </div> </div> <div class="preset-buttons"> <div class="preset-btn active" data-preset="sunset">Bali Sunset</div> <div class="preset-btn" data-preset="vintage">Vintage Film</div> <div class="preset-btn" data-preset="golden">Golden Hour</div> <div class="preset-btn" data-preset="dream">Dreamscape</div> </div> <button class="save-btn" id="save-btn">Save Wanderlux Photo</button> </div> </div> <div class="notification" id="notification">Photo effects applied! Ready to share your adventure.</div> <script> document.addEventListener('DOMContentLoaded', function() { // Elements const imagePreview = document.getElementById('image-preview'); const imageContainer = document.getElementById('image-container'); const lensFlare = document.getElementById('lens-flare'); const lightLeak = document.getElementById('light-leak'); const lightLeak2 = document.getElementById('light-leak-2'); const dustOverlay = document.getElementById('dust-overlay'); const cursorLight = document.getElementById('cursor-light'); const gallery = document.getElementById('image-gallery'); const galleryItems = document.querySelectorAll('.gallery-item'); const saveBtn = document.getElementById('save-btn'); const notification = document.getElementById('notification'); // Sliders const lightLeakSlider = document.getElementById('light-leak-slider'); const lensFlareSlider = document.getElementById('lens-flare-slider'); const warmthSlider = document.getElementById('warmth-slider'); const dustSlider = document.getElementById('dust-slider'); // Values displays const lightLeakValue = document.getElementById('light-leak-value'); const lensFlareValue = document.getElementById('lens-flare-value'); const warmthValue = document.getElementById('warmth-value'); const dustValue = document.getElementById('dust-value'); // Preset buttons const presetButtons = document.querySelectorAll('.preset-btn'); // Initial animation setTimeout(() => { imageContainer.classList.add('pulse'); updateEffects(); }, 300); // Apply initial effects updateEffects(); // Update effects based on sliders function updateEffects() { const lightLeakOpacity = lightLeakSlider.value / 100; const lensFlareOpacity = lensFlareSlider.value / 100; const warmthFilter = warmthSlider.value / 100; const dustOpacity = dustSlider.value / 100; lightLeak.style.opacity = lightLeakOpacity; lightLeak2.style.opacity = lightLeakOpacity * 0.8; lensFlare.style.opacity = lensFlareOpacity; dustOverlay.style.opacity = dustOpacity; // Update the warmth with a filter const warmthAmount = 1 + warmthFilter; imagePreview.style.filter = `sepia(${warmthFilter * 0.3}) contrast(1.05) saturate(${warmthAmount})`; // Update value displays lightLeakValue.textContent = `${lightLeakSlider.value}%`; lensFlareValue.textContent = `${lensFlareSlider.value}%`; warmthValue.textContent = `${warmthSlider.value}%`; dustValue.textContent = `${dustSlider.value}%`; } // Slider event listeners lightLeakSlider.addEventListener('input', updateEffects); lensFlareSlider.addEventListener('input', updateEffects); warmthSlider.addEventListener('input', updateEffects); dustSlider.addEventListener('input', updateEffects); // Gallery image selection galleryItems.forEach(item => { item.addEventListener('click', function() { // Remove active class from all items galleryItems.forEach(i => i.classList.remove('active')); // Add active class to clicked item this.classList.add('active'); // Change the preview image const newImgSrc = this.getAttribute('data-img'); imagePreview.src = newImgSrc; // Apply a pulse animation imageContainer.classList.remove('pulse'); setTimeout(() => { imageContainer.classList.add('pulse'); }, 10); // Apply effects updateEffects(); }); }); // Preset configurations const presets = { sunset: { lightLeak: 35, lensFlare: 40, warmth: 25, dust: 20 }, vintage: { lightLeak: 60, lensFlare: 15, warmth: 45, dust: 70 }, golden: { lightLeak: 50, lensFlare: 60, warmth: 70, dust: 10 }, dream: { lightLeak: 30, lensFlare: 80, warmth: 20, dust: 40 } }; // Apply presets presetButtons.forEach(btn => { btn.addEventListener('click', function() { // Remove active class from all buttons presetButtons.forEach(b => b.classList.remove('active')); // Add active class to clicked button this.classList.add('active'); // Get preset values const preset = presets[this.getAttribute('data-preset')]; // Animate the change animateSlider(lightLeakSlider, preset.lightLeak); animateSlider(lensFlareSlider, preset.lensFlare); animateSlider(warmthSlider, preset.warmth); animateSlider(dustSlider, preset.dust); }); }); // Animate slider change function animateSlider(slider, targetValue) { const currentValue = parseInt(slider.value); const diff = targetValue - currentValue; const steps = 15; const increment = diff / steps; let step = 0; const interval = setInterval(() => { step++; slider.value = Math.round(currentValue + (increment * step)); updateEffects(); if (step >= steps) { clearInterval(interval); slider.value = targetValue; updateEffects(); } }, 20); } // Save button functionality saveBtn.addEventListener('click', function() { // Add a button press effect this.style.transform = 'scale(0.95)'; setTimeout(() => { this.style.transform = ''; }, 150); // Show notification notification.classList.add('show'); setTimeout(() => { notification.classList.remove('show'); }, 3000); }); // Interactive light effect following mouse imageContainer.addEventListener('mousemove', function(e) { const rect = this.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; cursorLight.style.opacity = '0.4'; cursorLight.style.left = `${x - 75}px`; cursorLight.style.top = `${y - 75}px`; }); imageContainer.addEventListener('mouseleave', function() { cursorLight.style.opacity = '0'; }); // Remove pulse class after animation completes imageContainer.addEventListener('animationend', function() { this.classList.remove('pulse'); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>NeoVision AR Interface</title> <style> :root { --neon-blue: #00c2ff; --neon-purple: #9d00ff; --neon-green: #00ff9d; --bg-dark: #080818; --overlay-dark: rgba(8, 8, 24, 0.75); --grid-color: rgba(0, 194, 255, 0.2); --ui-glow: 0 0 10px var(--neon-blue), 0 0 20px rgba(0, 194, 255, 0.4); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { width: 100%; height: 100vh; background-color: var(--bg-dark); color: white; overflow: hidden; display: flex; justify-content: center; align-items: center; } .ar-container { position: relative; width: 100%; max-width: 700px; height: 700px; overflow: hidden; border-radius: 12px; box-shadow: 0 0 30px rgba(0, 0, 0, 0.8); } #cameraFeed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; } #gridOverlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to right, var(--grid-color) 1px, transparent 1px) 0 0 / 50px 50px, linear-gradient(to bottom, var(--grid-color) 1px, transparent 1px) 0 0 / 50px 50px; opacity: 0.5; pointer-events: none; } #scanLine { position: absolute; top: 0; left: 0; width: 100%; height: 4px; background: linear-gradient(90deg, transparent, var(--neon-blue), transparent); box-shadow: var(--ui-glow); animation: scanAnimation 3s ease-in-out infinite; opacity: 0.7; z-index: 5; } .ar-interface { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 10; } .header { position: absolute; top: 20px; left: 20px; right: 20px; display: flex; justify-content: space-between; align-items: center; } .logo { font-size: 1.5rem; font-weight: 700; color: white; text-shadow: 0 0 5px var(--neon-blue); letter-spacing: 1px; } .battery { display: flex; align-items: center; font-size: 0.9rem; } .battery-icon { width: 30px; height: 15px; border: 2px solid var(--neon-blue); border-radius: 3px; margin-right: 5px; position: relative; box-shadow: var(--ui-glow); } .battery-level { position: absolute; left: 2px; top: 2px; bottom: 2px; width: calc(85% - 4px); background-color: var(--neon-blue); border-radius: 1px; } .battery-cap { position: absolute; height: 8px; width: 3px; background-color: var(--neon-blue); right: -5px; top: 50%; transform: translateY(-50%); border-radius: 0 2px 2px 0; box-shadow: var(--ui-glow); } .ar-pointer { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100px; height: 100px; pointer-events: none; } .target-box { position: absolute; width: 80px; height: 80px; border: 2px solid var(--neon-green); box-shadow: 0 0 15px rgba(0, 255, 157, 0.5); border-radius: 4px; top: 50%; left: 50%; transform: translate(-50%, -50%); opacity: 0; transition: opacity 0.3s ease; } .target-box.active { opacity: 1; } .target-corner { position: absolute; width: 14px; height: 14px; } .top-left { top: -2px; left: -2px; border-top: 2px solid var(--neon-green); border-left: 2px solid var(--neon-green); } .top-right { top: -2px; right: -2px; border-top: 2px solid var(--neon-green); border-right: 2px solid var(--neon-green); } .bottom-left { bottom: -2px; left: -2px; border-bottom: 2px solid var(--neon-green); border-left: 2px solid var(--neon-green); } .bottom-right { bottom: -2px; right: -2px; border-bottom: 2px solid var(--neon-green); border-right: 2px solid var(--neon-green); } .info-card { position: absolute; background-color: var(--overlay-dark); border: 1px solid var(--neon-blue); border-radius: 8px; padding: 15px; backdrop-filter: blur(4px); max-width: 280px; opacity: 0; transition: all 0.3s ease; box-shadow: var(--ui-glow); } .info-card.active { opacity: 1; } .info-card h3 { font-size: 1.1rem; margin-bottom: 8px; color: var(--neon-blue); font-weight: 600; } .info-card p { font-size: 0.9rem; line-height: 1.4; margin-bottom: 10px; } .info-card .meta { display: flex; justify-content: space-between; font-size: 0.8rem; color: rgba(255, 255, 255, 0.7); } .footer { position: absolute; bottom: 20px; left: 20px; right: 20px; display: flex; justify-content: space-between; } .action-buttons { display: flex; gap: 15px; pointer-events: auto; } .action-btn { background-color: rgba(0, 0, 0, 0.5); border: 1px solid var(--neon-blue); color: white; border-radius: 50%; width: 50px; height: 50px; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: all 0.2s ease; position: relative; overflow: hidden; } .action-btn:before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient(circle, var(--neon-blue) 0%, transparent 70%); opacity: 0; transition: opacity 0.3s ease; } .action-btn:hover:before { opacity: 0.2; } .action-btn:active { transform: scale(0.95); } .action-btn i { font-size: 1.2rem; position: relative; z-index: 1; } .status { position: absolute; bottom: 85px; left: 20px; padding: 8px 15px; background-color: var(--overlay-dark); border-left: 3px solid var(--neon-blue); border-radius: 4px; font-size: 0.9rem; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; } .status.active { opacity: 1; transform: translateY(0); } .data-points { position: absolute; width: 100%; height: 100%; pointer-events: none; } .data-point { position: absolute; width: 10px; height: 10px; background-color: var(--neon-blue); border-radius: 50%; transform: translate(-50%, -50%); box-shadow: var(--ui-glow); opacity: 0; transition: all 0.3s ease; } .data-point:before { content: ''; position: absolute; width: 20px; height: 20px; border: 2px solid var(--neon-blue); border-radius: 50%; top: 50%; left: 50%; transform: translate(-50%, -50%); animation: pulseRing 2s infinite; } .data-point.active { opacity: 1; } .data-point-alpha { top: 30%; left: 30%; } .data-point-beta { top: 60%; left: 70%; } .mode-indicator { position: absolute; top: 20px; right: 20px; display: flex; align-items: center; padding: 8px 15px; background-color: var(--overlay-dark); border-radius: 20px; box-shadow: var(--ui-glow); } .mode-indicator .dot { width: 10px; height: 10px; background-color: var(--neon-blue); border-radius: 50%; margin-right: 8px; animation: blink 2s infinite; } .mode-indicator span { font-size: 0.9rem; font-weight: 500; } .coordinates { position: absolute; bottom: 20px; right: 20px; font-family: monospace; font-size: 0.9rem; color: var(--neon-green); background-color: rgba(0, 0, 0, 0.5); padding: 8px; border-radius: 4px; border-left: 2px solid var(--neon-green); } .no-camera { position: absolute; top: 0; left: 0; width: 100%; height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; background-color: var(--bg-dark); gap: 20px; padding: 20px; text-align: center; } .no-camera h2 { color: var(--neon-blue); font-size: 1.8rem; margin-bottom: 10px; text-shadow: var(--ui-glow); } .no-camera p { max-width: 80%; line-height: 1.5; } .demo-btn { background-color: transparent; border: 2px solid var(--neon-blue); color: white; padding: 12px 24px; border-radius: 24px; cursor: pointer; font-weight: 600; letter-spacing: 1px; margin-top: 20px; transition: all 0.3s ease; position: relative; overflow: hidden; text-transform: uppercase; pointer-events: auto; } .demo-btn:hover { background-color: rgba(0, 194, 255, 0.2); box-shadow: var(--ui-glow); } .demo-btn:active { transform: scale(0.98); } @keyframes scanAnimation { 0% { top: 0; opacity: 0.7; } 45% { top: 100%; opacity: 0.7; } 46% { opacity: 0; } 47% { top: 0; opacity: 0; } 50% { opacity: 0.7; } 95% { top: 100%; opacity: 0.7; } 96% { opacity: 0; } 97% { top: 0; opacity: 0; } 100% { top: 0; opacity: 0.7; } } @keyframes pulseRing { 0% { width: 20px; height: 20px; opacity: 0.6; } 70% { width: 30px; height: 30px; opacity: 0; } 100% { width: 20px; height: 20px; opacity: 0; } } @keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } /* Fonts for icons */ .icon { display: inline-block; width: 24px; height: 24px; background-size: contain; background-repeat: no-repeat; background-position: center; } .icon-camera { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2300c2ff' viewBox='0 0 24 24'%3E%3Cpath d='M12 15a3 3 0 100-6 3 3 0 000 6z'/%3E%3Cpath d='M20 4h-3.17l-1.24-1.35A1.99 1.99 0 0014.12 2H9.88c-.56 0-1.1.24-1.48.65L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 13c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z'/%3E%3C/svg%3E"); } .icon-scan { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2300c2ff' viewBox='0 0 24 24'%3E%3Cpath d='M7 3H4v3H2V1h5v2zm15 3V1h-5v2h3v3h2zM7 21H4v-3H2v5h5v-2zm13-3v3h-3v2h5v-5h-2zM17 6H7v12h10V6zm2 12c0 1.1-.9 2-2 2H7c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2v12z'/%3E%3C/svg%3E"); } .icon-data { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%2300c2ff' viewBox='0 0 24 24'%3E%3Cpath d='M21 8c-1.45 0-2.26 1.44-1.93 2.51l-3.55 3.56c-.3-.09-.74-.09-1.04 0l-2.55-2.55C12.27 10.45 11.46 9 10 9c-1.45 0-2.27 1.44-1.93 2.52l-4.56 4.55C2.44 15.74 1 16.55 1 18c0 1.1.9 2 2 2 1.45 0 2.26-1.44 1.93-2.51l4.55-4.56c.3.09.74.09 1.04 0l2.55 2.55C12.73 16.55 13.54 18 15 18c1.45 0 2.27-1.44 1.93-2.52l3.56-3.55c1.07.33 2.51-.48 2.51-1.93 0-1.1-.9-2-2-2z'/%3E%3C/svg%3E"); } /* Responsive adjustments */ @media (max-width: 600px) { .header, .footer { left: 10px; right: 10px; } .action-btn { width: 45px; height: 45px; } .info-card { max-width: 220px; padding: 10px; } .info-card h3 { font-size: 1rem; } .info-card p { font-size: 0.8rem; } .logo { font-size: 1.2rem; } .action-buttons { gap: 10px; } } </style> </head> <body> <div class="ar-container"> <video id="cameraFeed" autoplay playsinline muted></video> <div id="gridOverlay"></div> <div id="scanLine"></div> <div class="ar-interface"> <div class="header"> <div class="logo">NEOVISION AR</div> <div class="battery"> <div class="battery-icon"> <div class="battery-level"></div> <div class="battery-cap"></div> </div> <span>85%</span> </div> </div> <div class="mode-indicator"> <div class="dot"></div> <span>SCAN MODE</span> </div> <div class="ar-pointer"> <div class="target-box"> <div class="target-corner top-left"></div> <div class="target-corner top-right"></div> <div class="target-corner bottom-left"></div> <div class="target-corner bottom-right"></div> </div> </div> <div class="data-points"> <div class="data-point data-point-alpha" id="dataPoint1"></div> <div class="data-point data-point-beta" id="dataPoint2"></div> </div> <div class="info-card" id="infoCard1" style="top: 25%; left: 35%;"> <h3>Energy Converter M7</h3> <p>Quantum flux capacitor. Operates at 98.7% efficiency with adaptive neural synchronization.</p> <div class="meta"> <span>SECURITY: HIGH</span> <span>HEAT: 37.2°C</span> </div> </div> <div class="info-card" id="infoCard2" style="top: 55%; left: 75%;"> <h3>BioScan Results</h3> <p>Organic matter detected. Composition analysis shows 73% compound XR-21, commonly used in experimental pharmaceuticals.</p> <div class="meta"> <span>POTENCY: MEDIUM</span> <span>HALF-LIFE: 4.3h</span> </div> </div> <div class="status" id="statusMessage"> Object analysis complete. Displaying data overlays. </div> <div class="coordinates"> <div>LAT: 37.7749° N</div> <div>LON: 122.4194° W</div> <div>ALT: 12M</div> </div> <div class="footer"> <div class="action-buttons"> <button class="action-btn" id="captureBtn"> <i class="icon icon-camera"></i> </button> <button class="action-btn" id="scanBtn"> <i class="icon icon-scan"></i> </button> <button class="action-btn" id="dataBtn"> <i class="icon icon-data"></i> </button> </div> </div> </div> <div class="no-camera" id="noCameraView"> <h2>Augmented Reality Interface</h2> <p>This interface requires camera access to overlay digital information on live feeds. Experience cutting-edge AR with real-time analysis, object recognition, and environmental data interpretation.</p> <p>Our system provides instantaneous feedback with optimized performance, even in challenging lighting conditions.</p> <button class="demo-btn" id="demoBtn">Launch Demo Mode</button> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const video = document.getElementById('cameraFeed'); const noCameraView = document.getElementById('noCameraView'); const scanBtn = document.getElementById('scanBtn'); const captureBtn = document.getElementById('captureBtn'); const dataBtn = document.getElementById('dataBtn'); const demoBtn = document.getElementById('demoBtn'); const statusMessage = document.getElementById('statusMessage'); const targetBox = document.querySelector('.target-box'); const infoCard1 = document.getElementById('infoCard1'); const infoCard2 = document.getElementById('infoCard2'); const dataPoint1 = document.getElementById('dataPoint1'); const dataPoint2 = document.getElementById('dataPoint2'); let currentMode = 'scan'; let dataPointsActive = false; // Try to access the camera if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia({ video: true }) .then(function(stream) { video.srcObject = stream; noCameraView.style.display = 'none'; }) .catch(function(error) { console.error('Camera access error:', error); // Keep the "no camera" view visible }); } // Demo mode (when camera is not available) demoBtn.addEventListener('click', function() { noCameraView.style.display = 'none'; // Use a static image as fallback video.style.backgroundColor = '#0a0a20'; // Create a temporary overlay pattern to simulate an environment const gridOverlay = document.getElementById('gridOverlay'); gridOverlay.style.backgroundImage = 'radial-gradient(circle at 30% 40%, rgba(0, 194, 255, 0.1) 0%, transparent 30%), radial-gradient(circle at 70% 60%, rgba(157, 0, 255, 0.1) 0%, transparent 40%)'; setTimeout(() => { scanTrigger(); }, 1000); }); // Scan button scanBtn.addEventListener('click', function() { scanTrigger(); }); function scanTrigger() { currentMode = 'scan'; updateModeIndicator('SCAN MODE'); // Show target box animation targetBox.classList.add('active'); // Show status message showStatus('Scanning environment. Please hold steady...'); // Simulate scanning process setTimeout(() => { showStatus('Object identified. Retrieving data...'); setTimeout(() => { showStatus('Object analysis complete. Displaying data overlays.'); // Show data points and info cards dataPoint1.classList.add('active'); infoCard1.classList.add('active'); setTimeout(() => { dataPoint2.classList.add('active'); infoCard2.classList.add('active'); dataPointsActive = true; }, 700); // Hide target box after scan completes setTimeout(() => { targetBox.classList.remove('active'); }, 1000); }, 1500); }, 2000); } // Capture button captureBtn.addEventListener('click', function() { currentMode = 'capture'; updateModeIndicator('CAPTURE MODE'); // Simulate capture flash const flash = document.createElement('div'); flash.style.position = 'absolute'; flash.style.top = '0'; flash.style.left = '0'; flash.style.width = '100%'; flash.style.height = '100%'; flash.style.backgroundColor = 'white'; flash.style.opacity = '0'; flash.style.transition = 'opacity 0.2s ease'; flash.style.zIndex = '100'; document.querySelector('.ar-container').appendChild(flash); setTimeout(() => { flash.style.opacity = '0.7'; showStatus('Image captured. Processing enhancement filters...'); setTimeout(() => { flash.style.opacity = '0'; setTimeout(() => { flash.remove(); showStatus('Capture complete. Spatial mapping data saved.'); }, 200); }, 100); }, 10); // Reset info cards and data points resetOverlays(); }); // Data button dataBtn.addEventListener('click', function() { currentMode = 'data'; updateModeIndicator('DATA MODE'); // Toggle data points and info cards if (dataPointsActive) { resetOverlays(); showStatus('Data overlays hidden. Returning to clean view.'); } else { dataPoint1.classList.add('active'); dataPoint2.classList.add('active'); infoCard1.classList.add('active'); infoCard2.classList.add('active'); dataPointsActive = true; showStatus('Environmental data activated. Displaying all known data points.'); } }); function resetOverlays() { dataPoint1.classList.remove('active'); dataPoint2.classList.remove('active'); infoCard1.classList.remove('active'); infoCard2.classList.remove('active'); targetBox.classList.remove('active'); dataPointsActive = false; } function showStatus(message) { statusMessage.textContent = message; statusMessage.classList.add('active'); setTimeout(() => { statusMessage.classList.remove('active'); }, 4000); } function updateModeIndicator(mode) { document.querySelector('.mode-indicator span').textContent = mode; } // Track mouse movement to create interactive effect document.addEventListener('mousemove', function(e) { const container = document.querySelector('.ar-container'); const rect = container.getBoundingClientRect(); // Get position relative to container const x = e.clientX - rect.left; const y = e.clientY - rect.top; // Only track if mouse is within container if (x >= 0 && x <= rect.width && y >= 0 && y <= rect.height) { // Update target box position slightly with mouse movement (for subtle following effect) const targetBox = document.querySelector('.target-box'); const centerX = rect.width / 2; const centerY = rect.height / 2; // Calculate offset from center (limited range for subtle movement) const offsetX = (x - centerX) / 20; const offsetY = (y - centerY) / 20; // Apply subtle parallax to the target box targetBox.style.transform = `translate(calc(-50% + ${offsetX}px), calc(-50% + ${offsetY}px))`; // Update grid overlay with slight parallax effect const gridOverlay = document.getElementById('gridOverlay'); gridOverlay.style.backgroundPosition = `${offsetX * 2}px ${offsetY * 2}px`; } }); // For demo purposes, auto-trigger scan after loading setTimeout(() => { if (noCameraView.style.display !== 'none') { // Don't auto-scan if camera permission was denied (demo button will be shown) return; } scanTrigger(); }, 2000); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>DiagramDive - Interactive Learning Tool</title> <style> :root { --primary: #3498db; --secondary: #e74c3c; --accent: #f39c12; --dark: #2c3e50; --light: #ecf0f1; --success: #2ecc71; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f8f9fa; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; height: 700px; width: 700px; overflow: hidden; position: relative; } .container { width: 100%; max-width: 700px; padding: 20px; height: 100%; display: flex; flex-direction: column; } header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 15px; border-bottom: 2px solid var(--light); } .logo { display: flex; align-items: center; gap: 10px; } .logo-text { font-weight: 700; font-size: 1.5rem; color: var(--dark); } .logo-icon { width: 40px; height: 40px; background-color: var(--primary); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 18px; position: relative; overflow: hidden; } .logo-icon::before { content: ""; position: absolute; width: 100%; height: 100%; background: radial-gradient(circle at 70% 30%, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 70%); } .controls { display: flex; gap: 12px; } .btn { padding: 8px 15px; border-radius: 6px; border: none; cursor: pointer; font-weight: 600; font-size: 0.85rem; transition: all 0.3s ease; display: flex; align-items: center; gap: 6px; } .btn-primary { background-color: var(--primary); color: white; } .btn-primary:hover { background-color: #2980b9; transform: translateY(-2px); box-shadow: 0 4px 8px var(--shadow); } .btn-outline { background-color: transparent; border: 1.5px solid var(--primary); color: var(--primary); } .btn-outline:hover { background-color: rgba(52, 152, 219, 0.1); } .main-content { flex: 1; display: flex; flex-direction: column; gap: 20px; } .intro { background-color: white; padding: 20px; border-radius: 10px; box-shadow: 0 4px 15px var(--shadow); } h1 { font-size: 1.3rem; color: var(--dark); margin-bottom: 10px; } p { color: #555; line-height: 1.5; font-size: 0.95rem; } .interactive-diagram { flex: 1; background-color: white; border-radius: 10px; box-shadow: 0 4px 15px var(--shadow); padding: 20px; position: relative; overflow: hidden; display: flex; flex-direction: column; } .diagram-container { position: relative; flex: 1; display: flex; align-items: center; justify-content: center; margin-top: 15px; } .cell-diagram { width: 90%; max-width: 450px; position: relative; } .diagram-base { width: 100%; height: auto; border-radius: 8px; filter: drop-shadow(0 4px 6px var(--shadow)); } .hotspot { position: absolute; width: 30px; height: 30px; border-radius: 50%; background-color: var(--primary); display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; cursor: pointer; transform: scale(1); transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); z-index: 10; } .hotspot::after { content: ''; position: absolute; width: 100%; height: 100%; border-radius: 50%; background-color: var(--primary); opacity: 0.3; z-index: -1; animation: pulse 2s infinite; } @keyframes pulse { 0% { transform: scale(1); opacity: 0.3; } 70% { transform: scale(1.5); opacity: 0; } 100% { transform: scale(1.5); opacity: 0; } } .hotspot:hover { transform: scale(1.1); } .hotspot-1 { top: 25%; left: 30%; background-color: var(--secondary); } .hotspot-1::after { background-color: var(--secondary); } .hotspot-2 { top: 40%; left: 65%; background-color: var(--accent); } .hotspot-2::after { background-color: var(--accent); } .hotspot-3 { top: 70%; left: 45%; background-color: var(--success); } .hotspot-3::after { background-color: var(--success); } .tooltip { position: absolute; width: 250px; background-color: white; border-radius: 8px; padding: 15px; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15); opacity: 0; visibility: hidden; transition: all 0.3s ease; z-index: 20; transform: translateY(10px); border-left: 4px solid var(--primary); } .tooltip-title { font-weight: 600; font-size: 1rem; margin-bottom: 6px; color: var(--dark); } .tooltip-content { font-size: 0.9rem; color: #555; line-height: 1.4; } .tooltip-1 { top: 10%; left: 10%; border-left-color: var(--secondary); } .tooltip-2 { top: 30%; right: 10%; border-left-color: var(--accent); } .tooltip-3 { bottom: 10%; left: 25%; border-left-color: var(--success); } .tooltip.visible { opacity: 1; visibility: visible; transform: translateY(0); } .tooltip::before { content: ''; position: absolute; width: 12px; height: 12px; background-color: white; transform: rotate(45deg); } .tooltip-1::before { bottom: -6px; left: 20px; } .tooltip-2::before { bottom: -6px; right: 20px; } .tooltip-3::before { top: -6px; left: 20px; } .tab-controls { display: flex; gap: 2px; margin-bottom: 10px; } .tab-button { padding: 8px 15px; background-color: #e9ecef; border: none; border-radius: 6px 6px 0 0; font-weight: 500; font-size: 0.9rem; color: #6c757d; cursor: pointer; transition: all 0.2s ease; } .tab-button:hover { background-color: #dee2e6; } .tab-button.active { background-color: white; color: var(--primary); font-weight: 600; border-bottom: 2px solid var(--primary); } .diagram-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .diagram-title { font-weight: 600; font-size: 1.1rem; color: var(--dark); } .zoom-controls { display: flex; gap: 5px; } .zoom-btn { width: 30px; height: 30px; border-radius: 50%; background-color: #e9ecef; border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; color: #6c757d; font-weight: bold; transition: all 0.2s ease; } .zoom-btn:hover { background-color: #dee2e6; color: var(--dark); } .progress-bar { height: 6px; width: 100%; background-color: #e9ecef; border-radius: 3px; overflow: hidden; margin-top: 15px; } .progress { height: 100%; width: 35%; background-color: var(--success); border-radius: 3px; transition: width 0.5s ease; } .status { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; font-size: 0.85rem; color: #6c757d; } .status-text { display: flex; align-items: center; gap: 6px; } .status-icon { width: 8px; height: 8px; border-radius: 50%; background-color: var(--success); } .badge { padding: 4px 8px; border-radius: 12px; font-size: 0.75rem; font-weight: 600; background-color: rgba(46, 204, 113, 0.15); color: var(--success); } @media (max-width: 600px) { .container { padding: 15px; } .logo-text { font-size: 1.3rem; } .btn { padding: 6px 12px; font-size: 0.8rem; } h1 { font-size: 1.1rem; } p { font-size: 0.9rem; } .tooltip { width: 200px; } .cell-diagram { width: 100%; } } /* Animation for content entry */ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .intro, .interactive-diagram { animation: fadeIn 0.6s ease forwards; } .interactive-diagram { animation-delay: 0.2s; } /* Loading animation */ .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; align-items: center; justify-content: center; z-index: 100; transition: opacity 0.5s ease, visibility 0.5s ease; } .loading-spinner { width: 50px; height: 50px; border: 4px solid rgba(52, 152, 219, 0.3); border-radius: 50%; border-top-color: var(--primary); animation: spin 1s linear infinite; margin-bottom: 15px; } @keyframes spin { to { transform: rotate(360deg); } } .loading-text { font-size: 1rem; color: var(--dark); font-weight: 500; } .hide { opacity: 0; visibility: hidden; } </style> </head> <body> <div class="loading-overlay"> <div class="loading-spinner"></div> <div class="loading-text">Loading interactive diagram...</div> </div> <div class="container"> <header> <div class="logo"> <div class="logo-icon">D</div> <div class="logo-text">DiagramDive</div> </div> <div class="controls"> <button class="btn btn-outline"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"/> <path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"/> </svg> Settings </button> <button class="btn btn-primary"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16"> <path d="M5 3.5h6A1.5 1.5 0 0 1 12.5 5v6a1.5 1.5 0 0 1-1.5 1.5H5A1.5 1.5 0 0 1 3.5 11V5A1.5 1.5 0 0 1 5 3.5z"/> </svg> Save </button> </div> </header> <div class="main-content"> <div class="intro"> <h1>Transform Static Diagrams into Interactive Learning Assets</h1> <p>Upload your diagrams and enhance them with interactive hotspots. Add annotations, explanations, and custom tooltips to create engaging educational content.</p> </div> <div class="interactive-diagram"> <div class="diagram-info"> <div class="diagram-title">Cell Structure Interactive</div> <div class="zoom-controls"> <button class="zoom-btn" id="zoom-out">-</button> <button class="zoom-btn" id="zoom-in">+</button> </div> </div> <div class="tab-controls"> <button class="tab-button active">Basic View</button> <button class="tab-button">Advanced View</button> <button class="tab-button">Quiz Mode</button> </div> <div class="diagram-container"> <div class="cell-diagram"> <svg class="diagram-base" viewBox="0 0 500 400" xmlns="http://www.w3.org/2000/svg"> <!-- Cell membrane --> <ellipse cx="250" cy="200" rx="200" ry="150" fill="#f0f5fa" stroke="#2c3e50" stroke-width="3"/> <!-- Nucleus --> <ellipse cx="250" cy="200" rx="70" ry="60" fill="#e8f4fc" stroke="#e74c3c" stroke-width="2.5"/> <ellipse cx="250" cy="200" rx="60" ry="50" fill="#f8d9d5" stroke="#e74c3c" stroke-width="2"/> <!-- Nucleolus --> <circle cx="265" cy="190" r="15" fill="#c0392b"/> <!-- Mitochondria --> <ellipse cx="350" cy="220" rx="40" ry="25" fill="#f39c12" stroke="#e67e22" stroke-width="2"/> <path d="M310 220 Q330 205 350 220 Q370 235 390 220" fill="none" stroke="#e67e22" stroke-width="2"/> <!-- Golgi Apparatus --> <path d="M140 180 Q160 160 180 180 Q200 200 220 180" fill="none" stroke="#3498db" stroke-width="3"/> <path d="M135 190 Q155 170 175 190 Q195 210 215 190" fill="none" stroke="#3498db" stroke-width="3"/> <path d="M130 200 Q150 180 170 200 Q190 220 210 200" fill="none" stroke="#3498db" stroke-width="3"/> <!-- Endoplasmic Reticulum --> <path d="M250 260 Q270 280 290 260 Q310 240 330 260 Q350 280 370 260" fill="none" stroke="#2ecc71" stroke-width="2.5"/> <path d="M245 280 Q265 300 285 280 Q305 260 325 280 Q345 300 365 280" fill="none" stroke="#2ecc71" stroke-width="2.5"/> <!-- Ribosomes --> <circle cx="260" cy="260" r="4" fill="#16a085"/> <circle cx="285" cy="260" r="4" fill="#16a085"/> <circle cx="320" cy="260" r="4" fill="#16a085"/> <circle cx="350" cy="260" r="4" fill="#16a085"/> <circle cx="270" cy="280" r="4" fill="#16a085"/> <circle cx="305" cy="280" r="4" fill="#16a085"/> <circle cx="330" cy="280" r="4" fill="#16a085"/> <!-- Lysosomes --> <circle cx="180" cy="240" r="12" fill="#9b59b6" stroke="#8e44ad" stroke-width="2"/> <circle cx="210" cy="260" r="10" fill="#9b59b6" stroke="#8e44ad" stroke-width="2"/> </svg> <div class="hotspot hotspot-1">1</div> <div class="hotspot hotspot-2">2</div> <div class="hotspot hotspot-3">3</div> <div class="tooltip tooltip-1"> <div class="tooltip-title">Nucleus</div> <div class="tooltip-content">The control center of the cell containing genetic material (DNA). It regulates cell metabolism, growth, and reproduction through RNA and protein synthesis.</div> </div> <div class="tooltip tooltip-2"> <div class="tooltip-title">Mitochondria</div> <div class="tooltip-content">The powerhouse of the cell. These organelles generate ATP through cellular respiration, providing energy for all cellular activities.</div> </div> <div class="tooltip tooltip-3"> <div class="tooltip-title">Endoplasmic Reticulum</div> <div class="tooltip-content">An extensive network of membranes that synthesizes proteins and lipids. The rough ER (with ribosomes) manufactures proteins, while smooth ER produces lipids.</div> </div> </div> </div> <div class="progress-bar"> <div class="progress"></div> </div> <div class="status"> <div class="status-text"> <div class="status-icon"></div> <span>Discovered: 1 of 3 components</span> </div> <div class="badge">Biology - Cell Structure</div> </div> </div> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Simulate loading setTimeout(function() { document.querySelector('.loading-overlay').classList.add('hide'); }, 1500); // Hotspot interaction const hotspots = document.querySelectorAll('.hotspot'); const tooltips = document.querySelectorAll('.tooltip'); let activeTooltip = null; let progress = 0; const progressBar = document.querySelector('.progress'); const statusText = document.querySelector('.status-text span'); hotspots.forEach((hotspot, index) => { hotspot.addEventListener('click', function() { const tooltipId = `.tooltip-${index + 1}`; const tooltip = document.querySelector(tooltipId); // Close any open tooltip if (activeTooltip && activeTooltip !== tooltip) { activeTooltip.classList.remove('visible'); } // Toggle current tooltip tooltip.classList.toggle('visible'); if (tooltip.classList.contains('visible')) { activeTooltip = tooltip; // Update progress if this is a new discovery if (!hotspot.classList.contains('discovered')) { hotspot.classList.add('discovered'); progress++; updateProgress(); } } else { activeTooltip = null; } }); }); // Close tooltip when clicking elsewhere document.addEventListener('click', function(event) { if (!event.target.closest('.hotspot') && !event.target.closest('.tooltip')) { tooltips.forEach(tooltip => { tooltip.classList.remove('visible'); }); activeTooltip = null; } }); // Tab switching const tabButtons = document.querySelectorAll('.tab-button'); tabButtons.forEach(button => { button.addEventListener('click', function() { tabButtons.forEach(btn => btn.classList.remove('active')); this.classList.add('active'); }); }); // Zoom functionality const zoomIn = document.getElementById('zoom-in'); const zoomOut = document.getElementById('zoom-out'); const cellDiagram = document.querySelector('.cell-diagram'); let scale = 1; zoomIn.addEventListener('click', function() { if (scale < 1.5) { scale += 0.1; cellDiagram.style.transform = `scale(${scale})`; } }); zoomOut.addEventListener('click', function() { if (scale > 0.7) { scale -= 0.1; cellDiagram.style.transform = `scale(${scale})`; } }); function updateProgress() { const percentage = (progress / 3) * 100; progressBar.style.width = `${percentage}%`; statusText.textContent = `Discovered: ${progress} of 3 components`; } // Initial setup - mark first hotspot as discovered document.querySelector('.hotspot-1').classList.add('discovered'); progress = 1; updateProgress(); // Add pulse animation to undiscovered hotspots setInterval(() => { document.querySelectorAll('.hotspot:not(.discovered)').forEach(hotspot => { hotspot.style.transform = 'scale(1.1)'; setTimeout(() => { hotspot.style.transform = 'scale(1)'; }, 500); }); }, 3000); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Ambrosía - Where Each Dish Tells a Story</title> <style> @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Lora:ital@0;1&display=swap'); :root { --primary-color: #b3763e; --secondary-color: #f5efe0; --accent-color: #5c3c24; --text-color: #2a2a2a; --light-text: #f8f5f1; --transition: all 0.5s cubic-bezier(0.25, 1, 0.5, 1); } * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Lora', serif; background-color: var(--secondary-color); color: var(--text-color); line-height: 1.6; overflow-x: hidden; height: 100vh; width: 100%; } .container { max-width: 700px; height: 700px; margin: 0 auto; padding: 1rem; display: flex; flex-direction: column; overflow-y: auto; scroll-behavior: smooth; scrollbar-width: thin; scrollbar-color: var(--primary-color) var(--secondary-color); position: relative; } .container::-webkit-scrollbar { width: 8px; } .container::-webkit-scrollbar-track { background: var(--secondary-color); } .container::-webkit-scrollbar-thumb { background-color: var(--primary-color); border-radius: 20px; } header { padding: 1rem 0; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid rgba(179, 118, 62, 0.3); margin-bottom: 1.5rem; position: sticky; top: 0; background-color: var(--secondary-color); z-index: 10; } .logo { font-family: 'Playfair Display', serif; font-size: 1.8rem; font-weight: 700; color: var(--primary-color); letter-spacing: 1px; position: relative; } .logo::after { content: ''; position: absolute; width: 50%; height: 2px; background-color: var(--primary-color); bottom: -5px; left: 0; transform-origin: left; transform: scaleX(1); transition: var(--transition); } .logo:hover::after { transform: scaleX(1.5); } nav { display: flex; gap: 1.5rem; } nav a { text-decoration: none; color: var(--text-color); font-family: 'Playfair Display', serif; position: relative; padding: 0.25rem 0; font-size: 0.9rem; transition: var(--transition); } nav a::after { content: ''; position: absolute; width: 100%; height: 1px; background-color: var(--primary-color); bottom: 0; left: 0; transform: scaleX(0); transform-origin: right; transition: var(--transition); } nav a:hover { color: var(--primary-color); } nav a:hover::after { transform: scaleX(1); transform-origin: left; } .hero { margin-bottom: 2rem; position: relative; height: 300px; overflow: hidden; border-radius: 8px; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12); } .hero img { width: 100%; height: 100%; object-fit: cover; transition: var(--transition); filter: brightness(0.9) contrast(1.1); } .hero:hover img { transform: scale(1.05); } .hero-content { position: absolute; bottom: 0; left: 0; width: 100%; padding: 2rem; background: linear-gradient(0deg, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0) 100%); color: var(--light-text); } h1, h2, h3 { font-family: 'Playfair Display', serif; line-height: 1.2; } h1 { font-size: 2rem; margin-bottom: 0.5rem; font-weight: 700; } h2 { font-size: 1.6rem; margin-bottom: 1rem; font-weight: 400; letter-spacing: 0.5px; } h3 { font-size: 1.2rem; margin-bottom: 0.5rem; font-weight: 400; color: var(--primary-color); } p { margin-bottom: 1rem; font-size: 0.95rem; } .section { margin-bottom: 2rem; } .photo-grid { display: grid; grid-template-columns: repeat(2, 1fr); grid-gap: 1rem; margin-bottom: 2rem; } .photo-card { position: relative; overflow: hidden; border-radius: 8px; height: 200px; cursor: pointer; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); } .photo-card::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(92, 60, 36, 0.2); z-index: 1; opacity: 0; transition: var(--transition); } .photo-card:hover::before { opacity: 1; } .photo-card img { width: 100%; height: 100%; object-fit: cover; transition: var(--transition); filter: brightness(0.95); } .photo-card:hover img { transform: scale(1.1); } .photo-card .caption { position: absolute; bottom: -60px; left: 0; width: 100%; padding: 1rem; background: rgba(255, 255, 255, 0.9); backdrop-filter: blur(5px); color: var(--text-color); transition: var(--transition); z-index: 2; } .photo-card:hover .caption { bottom: 0; } .caption h3 { font-size: 1rem; margin-bottom: 0.25rem; } .caption p { font-size: 0.8rem; margin-bottom: 0; font-style: italic; } .cta { background-color: var(--primary-color); color: var(--light-text); text-decoration: none; padding: 0.75rem 1.5rem; border-radius: 4px; display: inline-block; font-family: 'Playfair Display', serif; letter-spacing: 0.5px; transition: var(--transition); border: none; cursor: pointer; font-size: 0.9rem; position: relative; overflow: hidden; } .cta::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.1); transform: translateX(-100%); transition: var(--transition); } .cta:hover { background-color: var(--accent-color); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .cta:hover::before { transform: translateX(0); } .newsletter { background-color: var(--primary-color); padding: 1.5rem; border-radius: 8px; color: var(--light-text); margin-top: 1rem; } .newsletter h3 { color: var(--light-text); margin-bottom: 1rem; } .newsletter-form { display: flex; gap: 0.5rem; } .newsletter-form input { flex: 1; padding: 0.75rem; border: none; border-radius: 4px; font-family: 'Lora', serif; outline: none; } .newsletter-form button { background-color: var(--accent-color); color: var(--light-text); border: none; border-radius: 4px; padding: 0 1rem; cursor: pointer; transition: var(--transition); } .newsletter-form button:hover { background-color: #432b19; } footer { margin-top: auto; padding-top: 1rem; border-top: 1px solid rgba(179, 118, 62, 0.3); font-size: 0.85rem; color: var(--primary-color); text-align: center; } .modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.8); display: flex; justify-content: center; align-items: center; z-index: 100; opacity: 0; visibility: hidden; transition: var(--transition); } .modal.active { opacity: 1; visibility: visible; } .modal-content { max-width: 80%; max-height: 80%; position: relative; border-radius: 8px; overflow: hidden; transform: scale(0.8); transition: var(--transition); } .modal.active .modal-content { transform: scale(1); } .modal img { width: 100%; height: auto; display: block; border-radius: 8px; } .close-modal { position: absolute; top: 10px; right: 10px; background-color: rgba(255, 255, 255, 0.3); color: white; border: none; width: 30px; height: 30px; border-radius: 50%; font-size: 1rem; display: flex; justify-content: center; align-items: center; cursor: pointer; transition: var(--transition); } .close-modal:hover { background-color: rgba(255, 255, 255, 0.5); } #bokeh-toggle { position: absolute; top: 10px; right: 55px; background-color: rgba(255, 255, 255, 0.3); color: white; border: none; border-radius: 20px; padding: 5px 15px; font-size: 0.8rem; cursor: pointer; transition: var(--transition); display: flex; align-items: center; gap: 5px; } #bokeh-toggle:hover { background-color: rgba(255, 255, 255, 0.5); } .bokeh-effect { filter: contrast(1.1) brightness(1.05) saturate(1.1); transition: filter 0.5s ease; } .bokeh-effect::before { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: radial-gradient( circle at 70% 30%, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 40% ), radial-gradient( circle at 30% 70%, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 30% ); mix-blend-mode: overlay; pointer-events: none; } .soft-focus { filter: blur(1px) brightness(1.05) contrast(1.05); transition: filter 0.5s ease; } @media (max-width: 600px) { nav { gap: 1rem; } .photo-grid { grid-template-columns: 1fr; } .logo { font-size: 1.5rem; } h1 { font-size: 1.5rem; } h2 { font-size: 1.3rem; } .newsletter-form { flex-direction: column; } } .booking-form { margin-top: 1rem; } .form-row { margin-bottom: 1rem; display: flex; gap: 1rem; } .form-field { flex: 1; } label { display: block; margin-bottom: 0.25rem; font-size: 0.9rem; color: var(--accent-color); } input, select, textarea { width: 100%; padding: 0.75rem; border: 1px solid rgba(179, 118, 62, 0.3); border-radius: 4px; font-family: 'Lora', serif; background-color: var(--light-text); transition: var(--transition); } input:focus, select:focus, textarea:focus { border-color: var(--primary-color); outline: none; box-shadow: 0 0 0 2px rgba(179, 118, 62, 0.2); } textarea { resize: vertical; min-height: 100px; } /* Bokeh cursor effect */ .bokeh-cursor { position: fixed; width: 150px; height: 150px; border-radius: 50%; pointer-events: none; background: radial-gradient( circle at center, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0) 70% ); mix-blend-mode: overlay; z-index: 1000; opacity: 0; transition: opacity 0.3s ease; transform: translate(-50%, -50%); } .bokeh-cursor.active { opacity: 1; } /* Floating decoration elements */ .decoration { position: absolute; opacity: 0.1; z-index: -1; } .decoration-1 { top: 20%; left: 5%; width: 60px; height: 60px; background-color: var(--primary-color); border-radius: 50%; } .decoration-2 { bottom: 10%; right: 5%; width: 80px; height: 80px; border: 2px solid var(--primary-color); border-radius: 50%; } .decoration-3 { top: 60%; right: 15%; width: 40px; height: 40px; background-color: var(--accent-color); border-radius: 50%; } </style> </head> <body> <div class="container"> <header> <div class="logo">Ambrosía</div> <nav> <a href="#menu">Our Menu</a> <a href="#gallery">Gallery</a> <a href="#reservations">Reservations</a> </nav> </header> <div class="hero"> <img src="https://images.unsplash.com/photo-1540189549336-e6e99c3679fe?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80" alt="Culinary masterpiece at Ambrosía"> <div class="hero-content"> <h1>Where Each Dish Tells a Story</h1> <p>A culinary journey through seasonal ingredients and artisanal traditions</p> </div> </div> <section class="section" id="menu"> <h2>Seasonal Delights</h2> <p>Our menu changes with the rhythm of seasons, allowing us to showcase the finest local produce at its peak. Each dish is meticulously crafted to bring out authentic flavors while presenting a visual poetry on your plate.</p> <div class="photo-grid"> <div class="photo-card"> <img src="https://images.unsplash.com/photo-1547496502-affa22d38842?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Autumn Harvest Salad"> <div class="caption"> <h3>Autumn Harvest Salad</h3> <p>Heirloom tomatoes, burrata, basil oil</p> </div> </div> <div class="photo-card"> <img src="https://images.unsplash.com/photo-1551504734-5ee1c4a1479b?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Truffle Risotto"> <div class="caption"> <h3>Truffle Risotto</h3> <p>Carnaroli rice, black truffle, aged parmesan</p> </div> </div> </div> <a href="#" class="cta">View Full Menu</a> </section> <section class="section" id="gallery"> <h2>Culinary Craftsmanship</h2> <p>At Ambrosía, we believe dining is a multisensory experience. Our photo gallery captures the intricate details, vibrant colors, and artistic presentations that define our approach to gastronomy.</p> <div class="photo-grid"> <div class="photo-card"> <img src="https://images.unsplash.com/photo-1533477321444-7f61cde2c4c3?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Chef's Special Dessert"> <div class="caption"> <h3>Chocolate Elevation</h3> <p>Single-origin chocolate, gold leaf, raspberry dust</p> </div> </div> <div class="photo-card"> <img src="https://images.unsplash.com/photo-1546069901-ba9599a7e63c?ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=80" alt="Garden Medley"> <div class="caption"> <h3>Garden Medley</h3> <p>Foraged vegetables, herb emulsion, edible flowers</p> </div> </div> </div> </section> <section class="section" id="reservations"> <h2>Reserve Your Experience</h2> <p>Each table at Ambrosía offers a unique perspective on our intimate dining space. Reservations are recommended to ensure we can provide you with our undivided attention and care.</p> <div class="booking-form"> <div class="form-row"> <div class="form-field"> <label for="date">Date</label> <input type="date" id="date" name="date" required> </div> <div class="form-field"> <label for="time">Time</label> <select id="time" name="time" required> <option value="">Select time</option> <option value="18:00">6:00 PM</option> <option value="18:30">6:30 PM</option> <option value="19:00">7:00 PM</option> <option value="19:30">7:30 PM</option> <option value="20:00">8:00 PM</option> <option value="20:30">8:30 PM</option> <option value="21:00">9:00 PM</option> </select> </div> </div> <div class="form-row"> <div class="form-field"> <label for="guests">Guests</label> <select id="guests" name="guests" required> <option value="">Select number</option> <option value="1">1 person</option> <option value="2">2 people</option> <option value="3">3 people</option> <option value="4">4 people</option> <option value="5">5 people</option> <option value="6">6 people</option> <option value="more">More than 6</option> </select> </div> <div class="form-field"> <label for="occasion">Occasion</label> <select id="occasion" name="occasion"> <option value="">Select (optional)</option> <option value="birthday">Birthday</option> <option value="anniversary">Anniversary</option> <option value="business">Business</option> <option value="other">Other</option> </select> </div> </div> <div class="form-row"> <div class="form-field"> <label for="name">Name</label> <input type="text" id="name" name="name" required> </div> <div class="form-field"> <label for="phone">Phone</label> <input type="tel" id="phone" name="phone" required> </div> </div> <div class="form-row"> <div class="form-field"> <label for="email">Email</label> <input type="email" id="email" name="email" required> </div> </div> <div class="form-row"> <div class="form-field"> <label for="requests">Special Requests</label> <textarea id="requests" name="requests"></textarea> </div> </div> <button type="button" class="cta" id="reserve-btn">Reserve Table</button> </div> </section> <div class="newsletter"> <h3>Join Our Culinary Community</h3> <p>Subscribe to receive seasonal menu updates, special event invitations, and chef's notes on ingredient stories.</p> <div class="newsletter-form"> <input type="email" placeholder="Your email address" required> <button type="button">Subscribe</button> </div> </div> <footer> <p>© 2023 Ambrosía Restaurant. An epicurean sanctuary.</p> </footer> <div class="decoration decoration-1"></div> <div class="decoration decoration-2"></div> <div class="decoration decoration-3"></div> </div> <div class="modal" id="photo-modal"> <div class="modal-content"> <img id="modal-image" src="" alt="Enlarged food photography"> <button class="close-modal" id="close-modal">×</button> <button id="bokeh-toggle">Enhance Photo</button> </div> </div> <div class="bokeh-cursor"></div> <script> document.addEventListener('DOMContentLoaded', () => { // Photo modal functionality const photoCards = document.querySelectorAll('.photo-card'); const modal = document.getElementById('photo-modal'); const modalImage = document.getElementById('modal-image'); const closeModal = document.getElementById('close-modal'); const bokehToggle = document.getElementById('bokeh-toggle'); const bokehCursor = document.querySelector('.bokeh-cursor'); photoCards.forEach(card => { card.addEventListener('click', () => { const img = card.querySelector('img'); modalImage.src = img.src; modalImage.alt = img.alt; modal.classList.add('active'); document.body.style.overflow = 'hidden'; }); }); closeModal.addEventListener('click', () => { modal.classList.remove('active'); document.body.style.overflow = ''; modalImage.classList.remove('bokeh-effect'); modalImage.classList.remove('soft-focus'); }); // Close modal when clicking outside the content modal.addEventListener('click', (e) => { if (e.target === modal) { modal.classList.remove('active'); document.body.style.overflow = ''; modalImage.classList.remove('bokeh-effect'); modalImage.classList.remove('soft-focus'); } }); // Bokeh and soft focus toggle let effectActive = false; bokehToggle.addEventListener('click', () => { if (!effectActive) { modalImage.classList.add('bokeh-effect'); setTimeout(() => { modalImage.classList.add('soft-focus'); }, 300); bokehToggle.textContent = 'Reset Photo'; effectActive = true; } else { modalImage.classList.remove('bokeh-effect'); modalImage.classList.remove('soft-focus'); bokehToggle.textContent = 'Enhance Photo'; effectActive = false; } }); // Bokeh cursor effect document.addEventListener('mousemove', (e) => { bokehCursor.style.left = `${e.clientX}px`; bokehCursor.style.top = `${e.clientY}px`; }); // Activate bokeh cursor effect on food images hover photoCards.forEach(card => { card.addEventListener('mouseenter', () => { bokehCursor.classList.add('active'); }); card.addEventListener('mouseleave', () => { bokehCursor.classList.remove('active'); }); }); // Form handling const reserveBtn = document.getElementById('reserve-btn'); reserveBtn.addEventListener('click', () => { const formFields = document.querySelectorAll('.booking-form input, .booking-form select, .booking-form textarea'); let formValid = true; formFields.forEach(field => { if (field.hasAttribute('required') && !field.value) { formValid = false; field.style.borderColor = '#c74d4d'; } else { field.style.borderColor = ''; } }); if (formValid) { reserveBtn.textContent = 'Reservation Confirmed!'; reserveBtn.style.backgroundColor = '#4d8b55'; // Reset form setTimeout(() => { formFields.forEach(field => { field.value = ''; }); reserveBtn.textContent = 'Reserve Table'; reserveBtn.style.backgroundColor = ''; }, 3000); } }); // Parallax effect for decoration elements document.addEventListener('mousemove', (e) => { const decorations = document.querySelectorAll('.decoration'); decorations.forEach((decoration, index) => { const speed = 0.03 + (index * 0.01); const x = (window.innerWidth - e.pageX * speed) / 100; const y = (window.innerHeight - e.pageY * speed) / 100; decoration.style.transform = `translateX(${x}px) translateY(${y}px)`; }); }); // Smooth scrolling for navigation links document.querySelectorAll('nav a').forEach(anchor => { anchor.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('href'); const targetElement = document.querySelector(targetId); if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PanoVista - Real Estate Photo Enhancer</title> <style> :root { --primary: #2a5298; --secondary: #ff6b35; --tertiary: #4ecdc4; --light: #f7f7f7; --dark: #222831; --shadow: rgba(0, 0, 0, 0.1); } * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: var(--light); color: var(--dark); height: 100vh; overflow: hidden; } .container { width: 700px; height: 700px; margin: 0 auto; padding: 20px; display: flex; flex-direction: column; position: relative; overflow: hidden; } .header { text-align: center; margin-bottom: 15px; position: relative; z-index: 2; } .header h1 { font-size: 28px; font-weight: 700; color: var(--primary); margin-bottom: 5px; letter-spacing: -0.5px; } .header p { font-size: 14px; color: var(--dark); opacity: 0.8; max-width: 80%; margin: 0 auto; } .panorama-container { flex: 1; position: relative; overflow: hidden; border-radius: 12px; box-shadow: 0 10px 30px var(--shadow); background: var(--dark); } .panorama-wrapper { position: absolute; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform 1s cubic-bezier(0.165, 0.84, 0.44, 1); } .panorama-item { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; background-size: cover; background-position: center; transition: all 0.5s ease; } .panorama-original { background-image: url('https://images.unsplash.com/photo-1564013799919-ab600027ffc6?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80'); z-index: 1; } .panorama-enhanced { background-image: url('https://images.unsplash.com/photo-1564013799919-ab600027ffc6?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80'); filter: brightness(1.1) contrast(1.05) saturate(1.2); transform: rotateY(180deg); z-index: 0; } .panorama-slider { position: absolute; height: 100%; width: 2px; background: rgba(255, 255, 255, 0.8); top: 0; left: 50%; transform: translateX(-50%); z-index: 3; transition: left 0.3s ease; } .panorama-slider:before { content: ''; position: absolute; width: 30px; height: 30px; border-radius: 50%; background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: ew-resize; } .panorama-slider:after { content: '⟷'; position: absolute; font-size: 12px; color: var(--dark); top: 50%; left: 50%; transform: translate(-50%, -50%); pointer-events: none; } .controls { display: flex; justify-content: space-between; align-items: center; margin-top: 20px; padding: 0 10px; position: relative; z-index: 2; } .toggle-container { display: flex; align-items: center; gap: 10px; } .toggle-label { font-size: 14px; color: var(--dark); font-weight: 500; } .toggle-switch { position: relative; display: inline-block; width: 60px; height: 30px; } .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: 30px; } .toggle-slider:before { position: absolute; content: ""; height: 22px; width: 22px; left: 4px; bottom: 4px; background-color: white; transition: .4s; border-radius: 50%; } input:checked + .toggle-slider { background-color: var(--tertiary); } input:checked + .toggle-slider:before { transform: translateX(30px); } .btn { background-color: var(--secondary); color: white; border: none; padding: 10px 20px; border-radius: 30px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 8px rgba(255, 107, 53, 0.2); display: flex; align-items: center; gap: 8px; } .btn:hover { transform: translateY(-2px); box-shadow: 0 6px 12px rgba(255, 107, 53, 0.3); } .btn:active { transform: translateY(0); } .btn span { font-size: 14px; } .btn i { font-size: 16px; } .properties-gallery { margin-top: 15px; display: flex; gap: 10px; overflow-x: auto; scrollbar-width: thin; scrollbar-color: var(--primary) var(--light); padding: 5px; position: relative; z-index: 2; } .properties-gallery::-webkit-scrollbar { height: 6px; } .properties-gallery::-webkit-scrollbar-track { background: var(--light); border-radius: 10px; } .properties-gallery::-webkit-scrollbar-thumb { background-color: var(--primary); border-radius: 10px; } .property-thumb { min-width: 80px; height: 60px; border-radius: 6px; background-size: cover; background-position: center; cursor: pointer; transition: all 0.3s ease; position: relative; overflow: hidden; } .property-thumb:hover { transform: translateY(-3px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .property-thumb.active { box-shadow: 0 0 0 3px var(--tertiary); } .property-thumb::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(to top, rgba(0, 0, 0, 0.3), transparent); } .loading-overlay { position: absolute; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.9); display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 5; opacity: 0; visibility: hidden; transition: all 0.3s ease; } .loading-overlay.active { opacity: 1; visibility: visible; } .spinner { width: 50px; height: 50px; border: 4px solid rgba(78, 205, 196, 0.2); border-radius: 50%; border-top-color: var(--tertiary); animation: spin 1s ease-in-out infinite; } .loading-text { margin-top: 15px; font-size: 16px; color: var(--primary); font-weight: 500; } .tooltip { position: absolute; background: rgba(0, 0, 0, 0.8); color: white; padding: 5px 10px; border-radius: 4px; font-size: 12px; pointer-events: none; opacity: 0; transition: opacity 0.3s ease; z-index: 10; } @keyframes spin { to { transform: rotate(360deg); } } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(78, 205, 196, 0.4); } 70% { box-shadow: 0 0 0 10px rgba(78, 205, 196, 0); } 100% { box-shadow: 0 0 0 0 rgba(78, 205, 196, 0); } } @media (max-width: 600px) { .container { padding: 15px; } .header h1 { font-size: 24px; } .header p { font-size: 12px; } .controls { flex-direction: column; gap: 15px; } .toggle-container { width: 100%; justify-content: space-between; } .btn { width: 100%; justify-content: center; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>PanoVista</h1> <p>Transform ordinary property photos into stunning panoramic showcases with enhanced lighting</p> </div> <div class="panorama-container"> <div class="panorama-wrapper"> <div class="panorama-item panorama-original"></div> <div class="panorama-item panorama-enhanced"></div> </div> <div class="panorama-slider"></div> <div class="loading-overlay"> <div class="spinner"></div> <div class="loading-text">Enhancing your property view...</div> </div> </div> <div class="properties-gallery"> <div class="property-thumb active" style="background-image: url('https://images.unsplash.com/photo-1564013799919-ab600027ffc6?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80');" data-original="https://images.unsplash.com/photo-1564013799919-ab600027ffc6?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80"></div> <div class="property-thumb" style="background-image: url('https://images.unsplash.com/photo-1518780664697-55e3ad937233?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80');" data-original="https://images.unsplash.com/photo-1518780664697-55e3ad937233?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80"></div> <div class="property-thumb" style="background-image: url('https://images.unsplash.com/photo-1512917774080-9991f1c4c750?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80');" data-original="https://images.unsplash.com/photo-1512917774080-9991f1c4c750?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80"></div> <div class="property-thumb" style="background-image: url('https://images.unsplash.com/photo-1570129477492-45c003edd2be?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80');" data-original="https://images.unsplash.com/photo-1570129477492-45c003edd2be?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80"></div> <div class="property-thumb" style="background-image: url('https://images.unsplash.com/photo-1580587771525-78b9dba3b914?ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=80');" data-original="https://images.unsplash.com/photo-1580587771525-78b9dba3b914?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80"></div> </div> <div class="controls"> <div class="toggle-container"> <span class="toggle-label">Before</span> <label class="toggle-switch"> <input type="checkbox" id="view-toggle"> <span class="toggle-slider"></span> </label> <span class="toggle-label">After</span> </div> <button class="btn" id="enhance-btn"> <span>Apply Smart Enhancement</span> </button> </div> <div class="tooltip" id="tooltip"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Elements const container = document.querySelector('.panorama-container'); const wrapper = document.querySelector('.panorama-wrapper'); const original = document.querySelector('.panorama-original'); const enhanced = document.querySelector('.panorama-enhanced'); const slider = document.querySelector('.panorama-slider'); const toggleBtn = document.getElementById('view-toggle'); const enhanceBtn = document.getElementById('enhance-btn'); const propertyThumbs = document.querySelectorAll('.property-thumb'); const loadingOverlay = document.querySelector('.loading-overlay'); const tooltip = document.getElementById('tooltip'); // Variables let isSliding = false; let isDragging = false; let enhancementActive = false; let startX; let sliderPosition = 50; // percentage // Initialize the comparison view updateComparison(sliderPosition); // Event Listeners slider.addEventListener('mousedown', startSliding); slider.addEventListener('touchstart', startSliding, { passive: true }); container.addEventListener('mousemove', moveSlider); container.addEventListener('touchmove', moveSlider, { passive: false }); window.addEventListener('mouseup', stopSliding); window.addEventListener('touchend', stopSliding); container.addEventListener('mouseenter', () => { showTooltip('Drag the slider to compare'); }); container.addEventListener('mouseleave', () => { hideTooltip(); }); toggleBtn.addEventListener('change', function() { if (this.checked) { wrapper.style.transform = 'rotateY(180deg)'; } else { wrapper.style.transform = 'rotateY(0deg)'; } }); enhanceBtn.addEventListener('click', function() { if (!enhancementActive) { applyEnhancement(); } }); propertyThumbs.forEach(thumb => { thumb.addEventListener('click', function() { loadProperty(this); }); }); // Functions function startSliding(e) { isSliding = true; isDragging = true; container.style.cursor = 'ew-resize'; // Prevent any default behavior if (e.type === 'touchstart') { startX = e.touches[0].clientX; } else { startX = e.clientX; e.preventDefault(); } } function moveSlider(e) { if (!isSliding) return; let clientX; if (e.type === 'touchmove') { clientX = e.touches[0].clientX; e.preventDefault(); // Prevent scrolling while dragging } else { clientX = e.clientX; } const rect = container.getBoundingClientRect(); const x = clientX - rect.left; sliderPosition = (x / rect.width) * 100; // Constrain to container bounds sliderPosition = Math.max(0, Math.min(sliderPosition, 100)); updateComparison(sliderPosition); } function stopSliding() { if (isDragging) { isSliding = false; isDragging = false; container.style.cursor = 'default'; } } function updateComparison(position) { slider.style.left = `${position}%`; original.style.clipPath = `inset(0 ${100 - position}% 0 0)`; enhanced.style.clipPath = `inset(0 0 0 ${position}%)`; } function applyEnhancement() { enhancementActive = true; loadingOverlay.classList.add('active'); // Simulate processing time setTimeout(() => { const filters = [ 'brightness(1.1) contrast(1.05) saturate(1.2)', 'brightness(1.15) contrast(1.1) saturate(1.1)', 'brightness(1.08) contrast(1.12) saturate(1.15) hue-rotate(2deg)', 'brightness(1.12) contrast(1.08) saturate(1.25)', ]; // Randomly select a filter combination const selectedFilter = filters[Math.floor(Math.random() * filters.length)]; enhanced.style.filter = selectedFilter; loadingOverlay.classList.remove('active'); enhancementActive = false; // Create "completed" notification showCompleteNotification(); }, 1500); } function loadProperty(thumbElement) { // Remove active class from all thumbnails propertyThumbs.forEach(thumb => thumb.classList.remove('active')); // Add active class to clicked thumbnail thumbElement.classList.add('active'); loadingOverlay.classList.add('active'); const imgUrl = thumbElement.dataset.original; // Simulate loading time setTimeout(() => { original.style.backgroundImage = `url('${imgUrl}')`; enhanced.style.backgroundImage = `url('${imgUrl}')`; // Reset enhancement enhanced.style.filter = 'brightness(1.1) contrast(1.05) saturate(1.2)'; loadingOverlay.classList.remove('active'); // Reset view toggleBtn.checked = false; wrapper.style.transform = 'rotateY(0deg)'; sliderPosition = 50; updateComparison(sliderPosition); }, 800); } function showCompleteNotification() { const notification = document.createElement('div'); notification.style.position = 'absolute'; notification.style.bottom = '20px'; notification.style.left = '50%'; notification.style.transform = 'translateX(-50%)'; notification.style.background = 'rgba(78, 205, 196, 0.9)'; notification.style.color = 'white'; notification.style.padding = '10px 20px'; notification.style.borderRadius = '30px'; notification.style.fontWeight = '500'; notification.style.zIndex = '10'; notification.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.1)'; notification.style.animation = 'pulse 2s infinite'; notification.textContent = '✓ Enhancement Applied Successfully'; document.querySelector('.container').appendChild(notification); setTimeout(() => { notification.style.opacity = '0'; notification.style.transition = 'opacity 0.5s ease'; setTimeout(() => { notification.remove(); }, 500); }, 3000); } function showTooltip(text) { tooltip.textContent = text; tooltip.style.opacity = '1'; // Position the tooltip const rect = container.getBoundingClientRect(); tooltip.style.top = `${rect.top + rect.height / 2 - 30}px`; tooltip.style.left = `${rect.left + rect.width / 2}px`; tooltip.style.transform = 'translate(-50%, -50%)'; // Hide tooltip after 3 seconds setTimeout(() => { hideTooltip(); }, 3000); } function hideTooltip() { tooltip.style.opacity = '0'; } }); </script> </body> </html>
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>TEXTURIZE Magazine</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Helvetica Neue', Arial, sans-serif; } :root { --primary-color: #ff3366; --secondary-color: #121212; --accent-color: #00c6ff; --text-color: #f5f5f5; --border-color: rgba(255, 255, 255, 0.2); } body { background-color: var(--secondary-color); color: var(--text-color); width: 100%; height: 100vh; overflow: hidden; display: flex; justify-content: center; align-items: center; } .magazine-container { width: 700px; height: 700px; position: relative; overflow: hidden; background: linear-gradient(45deg, #1a1a1a, #0a0a0a); } .header { position: absolute; top: 20px; left: 20px; z-index: 10; mix-blend-mode: difference; } .magazine-title { font-size: 2.5rem; font-weight: 900; letter-spacing: -1px; color: var(--primary-color); text-transform: uppercase; margin-bottom: 5px; text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.5); } .magazine-subtitle { font-size: 0.9rem; text-transform: uppercase; letter-spacing: 3px; color: var(--text-color); opacity: 0.8; } .image-container { width: 100%; height: 100%; position: relative; display: flex; align-items: center; justify-content: center; } .texture-image { position: absolute; width: 80%; height: 80%; object-fit: cover; transform-origin: center; transition: all 0.5s cubic-bezier(0.25, 0.1, 0.25, 1); filter: grayscale(0.3) contrast(1.2); cursor: pointer; } .vignette-overlay { position: absolute; width: 100%; height: 100%; background: radial-gradient(ellipse at center, transparent 50%, rgba(0, 0, 0, 0.7) 100%); pointer-events: none; opacity: 0.8; transition: opacity 0.3s ease; } .controls { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); display: flex; gap: 15px; z-index: 10; } .control-btn { background: rgba(255, 255, 255, 0.1); border: 1px solid var(--border-color); color: var(--text-color); padding: 8px 15px; font-size: 0.8rem; text-transform: uppercase; letter-spacing: 1px; cursor: pointer; transition: all 0.3s ease; backdrop-filter: blur(5px); } .control-btn:hover { background: var(--primary-color); color: white; transform: translateY(-2px); } .image-info { position: absolute; bottom: 100px; left: 40px; max-width: 300px; opacity: 0; transform: translateY(20px); transition: all 0.5s ease; } .image-info.active { opacity: 1; transform: translateY(0); } .info-title { font-size: 1.8rem; font-weight: 800; margin-bottom: 10px; line-height: 1; color: var(--primary-color); } .info-description { font-size: 0.9rem; line-height: 1.5; margin-bottom: 15px; } .texture-slider { position: absolute; right: 40px; top: 50%; transform: translateY(-50%); width: 200px; display: flex; flex-direction: column; align-items: center; gap: 10px; } .slider-label { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 5px; } .slider { width: 100%; appearance: none; height: 3px; background: rgba(255, 255, 255, 0.2); outline: none; } .slider::-webkit-slider-thumb { appearance: none; width: 15px; height: 15px; background: var(--primary-color); border-radius: 50%; cursor: pointer; transition: all 0.2s ease; } .slider::-webkit-slider-thumb:hover { transform: scale(1.2); } .image-counter { position: absolute; top: 40px; right: 40px; font-size: 1.2rem; font-weight: 700; color: var(--primary-color); mix-blend-mode: difference; } .highlight-point { position: absolute; width: 20px; height: 20px; border-radius: 50%; background: rgba(255, 51, 102, 0.5); transform: translate(-50%, -50%) scale(0); z-index: 5; pointer-events: none; animation: pulse 2s infinite; } @keyframes pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 51, 102, 0.7); transform: translate(-50%, -50%) scale(0.8); } 70% { box-shadow: 0 0 0 15px rgba(255, 51, 102, 0); transform: translate(-50%, -50%) scale(1); } 100% { box-shadow: 0 0 0 0 rgba(255, 51, 102, 0); transform: translate(-50%, -50%) scale(0.8); } } .loading-screen { position: absolute; width: 100%; height: 100%; background-color: var(--secondary-color); display: flex; justify-content: center; align-items: center; z-index: 100; opacity: 1; transition: opacity 0.8s ease; } .loading-screen.hidden { opacity: 0; pointer-events: none; } .loader { width: 50px; height: 50px; border: 3px solid rgba(255, 255, 255, 0.1); border-top: 3px solid var(--primary-color); border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .texture-grid { position: absolute; bottom: 30px; right: 30px; display: grid; grid-template-columns: repeat(4, 40px); gap: 10px; z-index: 10; opacity: 0; transform: translateX(50px); transition: all 0.5s ease; } .texture-grid.visible { opacity: 1; transform: translateX(0); } .texture-thumbnail { width: 40px; height: 40px; object-fit: cover; cursor: pointer; transition: all 0.3s ease; border: 2px solid transparent; } .texture-thumbnail:hover { transform: scale(1.1); border-color: var(--primary-color); } .texture-thumbnail.active { border-color: var(--primary-color); } /* Responsive adjustments */ @media (max-width: 700px) { .magazine-title { font-size: 2rem; } .texture-slider { right: 20px; width: 150px; } .image-info { bottom: 80px; left: 20px; max-width: 250px; } .controls { bottom: 20px; } .texture-grid { bottom: 20px; right: 20px; grid-template-columns: repeat(2, 35px); } .texture-thumbnail { width: 35px; height: 35px; } } @media (max-width: 500px) { .magazine-title { font-size: 1.8rem; } .image-info { bottom: 70px; max-width: 200px; } .info-title { font-size: 1.5rem; } .texture-slider { display: none; } } </style> </head> <body> <div class="magazine-container"> <div class="loading-screen"> <div class="loader"></div> </div> <div class="header"> <h1 class="magazine-title">TEXTURIZE</h1> <div class="magazine-subtitle">Tactility in Fashion</div> </div> <div class="image-container"> <img class="texture-image" alt="Fabric Texture"> <div class="vignette-overlay"></div> </div> <div class="image-counter">01/05</div> <div class="image-info"> <h2 class="info-title">RAW SILK REVERIE</h2> <p class="info-description">Exploring the interplay between light and natural fibers in this season's most textural pieces. The uneven surface catches shadow, creating micro-landscapes within the garment.</p> </div> <div class="texture-slider"> <div class="slider-label">Contrast</div> <input type="range" min="100" max="200" value="120" class="slider" id="contrast-slider"> <div class="slider-label">Brightness</div> <input type="range" min="80" max="120" value="100" class="slider" id="brightness-slider"> <div class="slider-label">Saturation</div> <input type="range" min="0" max="200" value="70" class="slider" id="saturation-slider"> </div> <div class="controls"> <button class="control-btn" id="prev-btn">Previous</button> <button class="control-btn" id="next-btn">Next</button> <button class="control-btn" id="highlight-btn">Highlight</button> </div> <div class="texture-grid" id="texture-grid"></div> </div> <script> document.addEventListener('DOMContentLoaded', function() { // Images and their information const textureImages = [ { src: "https://images.unsplash.com/photo-1581513184241-0c6094aac239?w=600&auto=format&fit=crop", title: "RAW SILK REVERIE", description: "Exploring the interplay between light and natural fibers in this season's most textural pieces. The uneven surface catches shadow, creating micro-landscapes within the garment." }, { src: "https://images.unsplash.com/photo-1618377385526-83108e9af520?w=600&auto=format&fit=crop", title: "WOVEN LANDSCAPES", description: "Architectural weaves create structural integrity that transforms as the body moves. This season's standout textures challenge conventional flatness with dimensional complexity." }, { src: "https://images.unsplash.com/photo-1580644228275-8051f7a9bdf5?w=600&auto=format&fit=crop", title: "TACTILE DISSONANCE", description: "Contradicting elements merge in provocative fabrications. Smooth against rough, synthetic meeting natural—these juxtapositions define the avant-garde aesthetic of 2023." }, { src: "https://images.unsplash.com/photo-1597696929736-7c50a6e55f20?w=600&auto=format&fit=crop", title: "TRANSLUCENT DEPTH", description: "Layered sheers create phantom textures through visual transparency rather than touch. Light becomes an active participant in these ethereal compositions." }, { src: "https://images.unsplash.com/photo-1584285575014-bb4d344e5f45?w=600&auto=format&fit=crop", title: "MACRO MINIMALISM", description: "Magnified natural patterns become abstract when translated to fabric. This macro approach to minimalism creates visual interest while maintaining elegance." } ]; // Variables const imageElement = document.querySelector('.texture-image'); const imageInfo = document.querySelector('.image-info'); const imageTitle = document.querySelector('.info-title'); const imageDescription = document.querySelector('.info-description'); const imageCounter = document.querySelector('.image-counter'); const prevBtn = document.getElementById('prev-btn'); const nextBtn = document.getElementById('next-btn'); const highlightBtn = document.getElementById('highlight-btn'); const contrastSlider = document.getElementById('contrast-slider'); const brightnessSlider = document.getElementById('brightness-slider'); const saturationSlider = document.getElementById('saturation-slider'); const vignetteOverlay = document.querySelector('.vignette-overlay'); const textureGrid = document.getElementById('texture-grid'); const loadingScreen = document.querySelector('.loading-screen'); const imageContainer = document.querySelector('.image-container'); let currentImageIndex = 0; let highlights = []; let isHighlightMode = false; // Initialize function init() { updateImage(); createTextureGrid(); // Simulate loading setTimeout(() => { loadingScreen.classList.add('hidden'); // Show the image info after loading setTimeout(() => { imageInfo.classList.add('active'); textureGrid.classList.add('visible'); }, 500); }, 1500); } // Update the current image function updateImage() { const currentImage = textureImages[currentImageIndex]; // Update counter imageCounter.textContent = `0${currentImageIndex + 1}/0${textureImages.length}`; // Fade out current info imageInfo.classList.remove('active'); // Change image with slight delay for smoother transition setTimeout(() => { imageElement.src = currentImage.src; imageTitle.textContent = currentImage.title; imageDescription.textContent = currentImage.description; // Reset highlights removeAllHighlights(); // Fade in new info setTimeout(() => { imageInfo.classList.add('active'); // Update active thumbnail document.querySelectorAll('.texture-thumbnail').forEach((thumb, index) => { if (index === currentImageIndex) { thumb.classList.add('active'); } else { thumb.classList.remove('active'); } }); }, 300); }, 300); } // Create texture thumbnails grid function createTextureGrid() { textureImages.forEach((image, index) => { const thumbnail = document.createElement('img'); thumbnail.src = image.src; thumbnail.alt = `Texture ${index + 1}`; thumbnail.classList.add('texture-thumbnail'); if (index === currentImageIndex) { thumbnail.classList.add('active'); } thumbnail.addEventListener('click', () => { currentImageIndex = index; updateImage(); }); textureGrid.appendChild(thumbnail); }); } // Add highlight point function addHighlight(x, y) { const highlight = document.createElement('div'); highlight.classList.add('highlight-point'); highlight.style.left = `${x}px`; highlight.style.top = `${y}px`; imageContainer.appendChild(highlight); highlights.push(highlight); } // Remove all highlights function removeAllHighlights() { highlights.forEach(highlight => highlight.remove()); highlights = []; isHighlightMode = false; highlightBtn.textContent = 'Highlight'; } // Update filter based on slider values function updateFilter() { const contrast = contrastSlider.value; const brightness = brightnessSlider.value; const saturation = saturationSlider.value; imageElement.style.filter = ` grayscale(0.3) contrast(${contrast}%) brightness(${brightness}%) saturate(${saturation}%) `; } // Event Listeners prevBtn.addEventListener('click', () => { currentImageIndex = (currentImageIndex - 1 + textureImages.length) % textureImages.length; updateImage(); }); nextBtn.addEventListener('click', () => { currentImageIndex = (currentImageIndex + 1) % textureImages.length; updateImage(); }); highlightBtn.addEventListener('click', () => { isHighlightMode = !isHighlightMode; highlightBtn.textContent = isHighlightMode ? 'Done' : 'Highlight'; if (!isHighlightMode) { removeAllHighlights(); } }); imageElement.addEventListener('click', (e) => { if (isHighlightMode) { const rect = imageContainer.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; addHighlight(x, y); } }); // Image hover effect imageElement.addEventListener('mousemove', (e) => { if (!isHighlightMode) { const rect = imageContainer.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; // Calculate the center of the image const centerX = rect.width / 2; const centerY = rect.height / 2; // Calculate how far the mouse is from center, as a percentage const moveX = (x - centerX) / 20; const moveY = (y - centerY) / 20; // Move the image slightly in the opposite direction imageElement.style.transform = `translate(${-moveX}px, ${-moveY}px) scale(1.05)`; // Adjust vignette based on mouse position const distance = Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2)); const maxDistance = Math.sqrt(Math.pow(centerX, 2) + Math.pow(centerY, 2)); const vignetteOpacity = 0.4 + (distance / maxDistance) * 0.5; vignetteOverlay.style.opacity = vignetteOpacity; } }); imageElement.addEventListener('mouseleave', () => { imageElement.style.transform = 'translate(0, 0) scale(1)'; vignetteOverlay.style.opacity = '0.8'; }); // Slider events contrastSlider.addEventListener('input', updateFilter); brightnessSlider.addEventListener('input', updateFilter); saturationSlider.addEventListener('input', updateFilter); // Initialize the app init(); }); </script> </body> </html>