Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Body Editor Pro</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| * { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| .gradient-bg { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| } | |
| .glass-effect { | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .tool-button { | |
| transition: all 0.3s ease; | |
| } | |
| .tool-button:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); | |
| } | |
| .chat-bubble { | |
| animation: slideIn 0.3s ease; | |
| } | |
| @keyframes slideIn { | |
| from { | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .editor-canvas { | |
| background: repeating-linear-gradient(45deg, | |
| #f0f0f0, | |
| #f0f0f0 10px, | |
| #e0e0e0 10px, | |
| #e0e0e0 20px); | |
| } | |
| .filter-preview { | |
| transition: all 0.3s ease; | |
| } | |
| .filter-preview:hover { | |
| transform: scale(1.05); | |
| } | |
| .slider { | |
| -webkit-appearance: none; | |
| appearance: none; | |
| height: 6px; | |
| border-radius: 5px; | |
| background: #d3d3d3; | |
| outline: none; | |
| } | |
| .slider::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| appearance: none; | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: #667eea; | |
| cursor: pointer; | |
| } | |
| .slider::-moz-range-thumb { | |
| width: 20px; | |
| height: 20px; | |
| border-radius: 50%; | |
| background: #667eea; | |
| cursor: pointer; | |
| } | |
| .body-marker { | |
| position: absolute; | |
| width: 12px; | |
| height: 12px; | |
| border-radius: 50%; | |
| background: #667eea; | |
| border: 2px solid white; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| } | |
| .body-marker:hover { | |
| transform: scale(1.3); | |
| } | |
| .body-zone { | |
| position: absolute; | |
| border: 2px dashed rgba(102, 126, 234, 0.7); | |
| border-radius: 8px; | |
| background: rgba(102, 126, 234, 0.1); | |
| pointer-events: none; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="app"> | |
| <!-- Header --> | |
| <header class="glass-effect text-white p-4"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <h1 class="text-2xl font-bold">Body Editor Pro</h1> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" class="text-white hover:text-gray-200 transition-colors"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| </header> | |
| <div class="container mx-auto p-4 flex flex-col lg:flex-row gap-4"> | |
| <!-- Editor Section --> | |
| <div class="flex-1 glass-effect rounded-xl p-6"> | |
| <h2 class="text-white text-xl font-semibold mb-4">Body Editor</h2> | |
| <!-- Image Upload --> | |
| <div class="mb-6"> | |
| <label class="block text-white mb-2">Upload Body Image</label> | |
| <input | |
| type="file" | |
| accept="image/*" | |
| id="imageUpload" | |
| class="w-full p-2 rounded-lg bg-white/20 text-white file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-white/30 file:text-white hover:file:bg-white/40" | |
| /> | |
| </div> | |
| <!-- Editor Canvas --> | |
| <div class="editor-canvas rounded-lg p-4 mb-6 min-h-96 flex items-center justify-center relative"> | |
| <div id="imageContainer" class="relative"> | |
| <img | |
| id="bodyImage" | |
| src="" | |
| alt="Body Image" | |
| class="max-w-full max-h-96 rounded-lg shadow-lg" | |
| /> | |
| <!-- Body adjustment markers --> | |
| <div id="bodyMarkers" class="absolute inset-0"> | |
| <!-- These markers will be positioned dynamically --> | |
| </div> | |
| <!-- Body zones for editing --> | |
| <div id="bodyZones" class="absolute inset-0 pointer-events-none"> | |
| <!-- These zones will be positioned dynamically --> | |
| </div> | |
| </div> | |
| <div id="noImageMessage" class="text-center text-white/60"> | |
| <i class="fas fa-user text-6xl mb-4"></i> | |
| <p>Upload a body image to start editing</p> | |
| </div> | |
| </div> | |
| <!-- Body Editing Tools --> | |
| <div class="mb-6"> | |
| <h3 class="text-white mb-3">Body Adjustment Tools</h3> | |
| <div class="grid grid-cols-3 sm:grid-cols-6 gap-2"> | |
| <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="slim"> | |
| <i class="fas fa-arrows-alt-h text-lg"></i> | |
| <span class="text-xs mt-1 block">Slim</span> | |
| </button> | |
| <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="tall"> | |
| <i class="fas fa-arrows-alt-v text-lg"></i> | |
| <span class="text-xs mt-1 block">Taller</span> | |
| </button> | |
| <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="muscle"> | |
| <i class="fas fa-dumbbell text-lg"></i> | |
| <span class="text-xs mt-1 block">Muscle</span> | |
| </button> | |
| <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="waist"> | |
| <i class="fas fa-circle text-lg"></i> | |
| <span class="text-xs mt-1 block">Waist</span> | |
| </button> | |
| <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="chest"> | |
| <i class="fas fa-square text-lg"></i> | |
| <span class="text-xs mt-1 block">Chest</span> | |
| </button> | |
| <button class="tool-button p-3 rounded-lg glass-effect text-white transition-all" data-tool="hips"> | |
| <i class="fas fa-circle text-lg"></i> | |
| <span class="text-xs mt-1 block">Hips</span> | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Body Adjustments --> | |
| <div class="mb-6"> | |
| <h3 class="text-white mb-3">Body Adjustments</h3> | |
| <div class="space-y-4"> | |
| <div> | |
| <label class="text-white text-sm block mb-1">Overall Slim: <span id="slimValue">0</span>%</label> | |
| <input | |
| type="range" | |
| min="-20" | |
| max="20" | |
| value="0" | |
| id="slimSlider" | |
| class="slider w-full" | |
| /> | |
| </div> | |
| <div> | |
| <label class="text-white text-sm block mb-1">Height: <span id="heightValue">0</span>%</label> | |
| <input | |
| type="range" | |
| min="-10" | |
| max="10" | |
| value="0" | |
| id="heightSlider" | |
| class="slider w-full" | |
| /> | |
| </div> | |
| <div> | |
| <label class="text-white text-sm block mb-1">Muscle Definition: <span id="muscleValue">0</span>%</label> | |
| <input | |
| type="range" | |
| min="0" | |
| max="30" | |
| value="0" | |
| id="muscleSlider" | |
| class="slider w-full" | |
| /> | |
| </div> | |
| <div> | |
| <label class="text-white text-sm block mb-1">Waist: <span id="waistValue">0</span>%</label> | |
| <input | |
| type="range" | |
| min="-15" | |
| max="15" | |
| value="0" | |
| id="waistSlider" | |
| class="slider w-full" | |
| /> | |
| </div> | |
| <div> | |
| <label class="text-white text-sm block mb-1">Chest: <span id="chestValue">0</span>%</label> | |
| <input | |
| type="range" | |
| min="-15" | |
| max="15" | |
| value="0" | |
| id="chestSlider" | |
| class="slider w-full" | |
| /> | |
| </div> | |
| <div> | |
| <label class="text-white text-sm block mb-1">Hips: <span id="hipsValue">0</span>%</label> | |
| <input | |
| type="range" | |
| min="-15" | |
| max="15" | |
| value="0" | |
| id="hipsSlider" | |
| class="slider w-full" | |
| /> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Action Buttons --> | |
| <div class="flex gap-2"> | |
| <button | |
| id="resetButton" | |
| class="px-4 py-2 rounded-lg glass-effect text-white hover:bg-white/20 transition-colors" | |
| > | |
| Reset All | |
| </button> | |
| <button | |
| id="downloadButton" | |
| class="px-4 py-2 rounded-lg bg-white text-purple-600 font-semibold hover:bg-gray-100 transition-colors" | |
| > | |
| Download | |
| </button> | |
| </div> | |
| </div> | |
| <!-- Chat Section --> | |
| <div class="lg:w-96 glass-effect rounded-xl p-6"> | |
| <h2 class="text-white text-xl font-semibold mb-4">Body Editor Assistant</h2> | |
| <!-- Chat Messages --> | |
| <div class="bg-white/10 rounded-lg p-4 h-96 overflow-y-auto mb-4"> | |
| <div class="chat-bubble mb-3"> | |
| <div class="flex items-start gap-2"> | |
| <div class="w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-sm font-semibold"> | |
| A | |
| </div> | |
| <div class="flex-1"> | |
| <div class="flex items-center gap-2 mb-1"> | |
| <span class="text-white font-semibold text-sm">AI Assistant</span> | |
| <span class="text-white/60 text-xs">10:30 AM</span> | |
| </div> | |
| <p class="text-white/90 text-sm">Welcome to Body Editor Pro! Upload a body image to start editing your physique.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="chat-bubble mb-3"> | |
| <div class="flex items-start gap-2"> | |
| <div class="w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-sm font-semibold"> | |
| S | |
| </div> | |
| <div class="flex-1"> | |
| <div class="flex items-center gap-2 mb-1"> | |
| <span class="text-white font-semibold text-sm">System</span> | |
| <span class="text-white/60 text-xs">10:31 AM</span> | |
| </div> | |
| <p class="text-white/90 text-sm">I can help you slim, tone, or build muscle in your photos.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="messagesEnd"></div> | |
| </div> | |
| <!-- Chat Input --> | |
| <div class="flex gap-2"> | |
| <input | |
| type="text" | |
| id="messageInput" | |
| placeholder="Ask about body editing..." | |
| class="flex-1 p-3 rounded-lg bg-white/20 text-white placeholder-white/60 border border-white/30 focus:outline-none focus:border-white/50" | |
| /> | |
| <button | |
| id="sendButton" | |
| class="px-4 py-3 rounded-lg bg-white text-purple-600 font-semibold hover:bg-gray-100 transition-colors" | |
| > | |
| <i class="fas fa-paper-plane"></i> | |
| </button> | |
| </div> | |
| <!-- Quick Actions --> | |
| <div class="mt-4"> | |
| <h3 class="text-white mb-2">Quick Body Edits</h3> | |
| <div class="grid grid-cols-2 gap-2"> | |
| <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors"> | |
| <i class="fas fa-running mr-1"></i> Athlete Mode | |
| </button> | |
| <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors"> | |
| <i class="fas fa-swimmer mr-1"></i> Swimmer Body | |
| </button> | |
| <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors"> | |
| <i class="fas fa-yin-yang mr-1"></i> Balanced | |
| </button> | |
| <button class="p-2 rounded-lg glass-effect text-white text-sm hover:bg-white/20 transition-colors"> | |
| <i class="fas fa-fire mr-1"></i> Fitness Model | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| // DOM Elements | |
| const imageUpload = document.getElementById('imageUpload'); | |
| const bodyImage = document.getElementById('bodyImage'); | |
| const noImageMessage = document.getElementById('noImageMessage'); | |
| const imageContainer = document.getElementById('imageContainer'); | |
| const messageInput = document.getElementById('messageInput'); | |
| const sendButton = document.getElementById('sendButton'); | |
| const messagesEnd = document.getElementById('messagesEnd'); | |
| const resetButton = document.getElementById('resetButton'); | |
| const downloadButton = document.getElementById('downloadButton'); | |
| const chatMessages = document.querySelector('.bg-white/10'); | |
| // Slider elements | |
| const slimSlider = document.getElementById('slimSlider'); | |
| const heightSlider = document.getElementById('heightSlider'); | |
| const muscleSlider = document.getElementById('muscleSlider'); | |
| const waistSlider = document.getElementById('waistSlider'); | |
| const chestSlider = document.getElementById('chestSlider'); | |
| const hipsSlider = document.getElementById('hipsSlider'); | |
| // Value displays | |
| const slimValue = document.getElementById('slimValue'); | |
| const heightValue = document.getElementById('heightValue'); | |
| const muscleValue = document.getElementById('muscleValue'); | |
| const waistValue = document.getElementById('waistValue'); | |
| const chestValue = document.getElementById('chestValue'); | |
| const hipsValue = document.getElementById('hipsValue'); | |
| // Tool buttons | |
| const toolButtons = document.querySelectorAll('[data-tool]'); | |
| // Current state | |
| let currentImage = null; | |
| let originalImage = null; | |
| let adjustments = { | |
| slim: 0, | |
| height: 0, | |
| muscle: 0, | |
| waist: 0, | |
| chest: 0, | |
| hips: 0 | |
| }; | |
| // Initialize the app | |
| function init() { | |
| // Hide the image initially | |
| bodyImage.style.display = 'none'; | |
| // Add event listeners | |
| imageUpload.addEventListener('change', handleImageUpload); | |
| sendButton.addEventListener('click', sendMessage); | |
| messageInput.addEventListener('keypress', (e) => { | |
| if (e.key === 'Enter') sendMessage(); | |
| }); | |
| // Slider event listeners | |
| slimSlider.addEventListener('input', updateSlimAdjustment); | |
| heightSlider.addEventListener('input', updateHeightAdjustment); | |
| muscleSlider.addEventListener('input', updateMuscleAdjustment); | |
| waistSlider.addEventListener('input', updateWaistAdjustment); | |
| chestSlider.addEventListener('input', updateChestAdjustment); | |
| hipsSlider.addEventListener('input', updateHipsAdjustment); | |
| // Tool button event listeners | |
| toolButtons.forEach(button => { | |
| button.addEventListener('click', () => { | |
| const tool = button.getAttribute('data-tool'); | |
| activateTool(tool); | |
| }); | |
| }); | |
| // Action button event listeners | |
| resetButton.addEventListener('click', resetAdjustments); | |
| downloadButton.addEventListener('click', downloadImage); | |
| } | |
| // Handle image upload | |
| function handleImageUpload(e) { | |
| const file = e.target.files[0]; | |
| if (file) { | |
| const reader = new FileReader(); | |
| reader.onload = (e) => { | |
| currentImage = e.target.result; | |
| originalImage = e.target.result; | |
| bodyImage.src = currentImage; | |
| bodyImage.style.display = 'block'; | |
| noImageMessage.style.display = 'none'; | |
| // Add message to chat | |
| addChatMessage('System', 'Body image uploaded successfully! You can now adjust the physique.'); | |
| // Add body markers after image loads | |
| bodyImage.onload = () => { | |
| addBodyMarkers(); | |
| }; | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| } | |
| // Add body markers for editing | |
| function addBodyMarkers() { | |
| const markersContainer = document.getElementById('bodyMarkers'); | |
| const zonesContainer = document.getElementById('bodyZones'); | |
| // Clear existing markers | |
| markersContainer.innerHTML = ''; | |
| zonesContainer.innerHTML = ''; | |
| // Define body points and zones | |
| const bodyPoints = [ | |
| { name: 'head', x: 50, y: 10 }, | |
| { name: 'shoulders', x: 50, y: 25 }, | |
| { name: 'chest', x: 50, y: 35 }, | |
| { name: 'waist', x: 50, y: 50 }, | |
| { name: 'hips', x: 50, y: 65 }, | |
| { name: 'legs', x: 50, y: 85 } | |
| ]; | |
| // Create markers | |
| bodyPoints.forEach(point => { | |
| const marker = document.createElement('div'); | |
| marker.className = 'body-marker'; | |
| marker.style.left = `${point.x}%`; | |
| marker.style.top = `${point.y}%`; | |
| marker.setAttribute('data-point', point.name); | |
| markersContainer.appendChild(marker); | |
| // Add click event to markers | |
| marker.addEventListener('click', () => { | |
| highlightBodyZone(point.name); | |
| addChatMessage('You', `Selected ${point.name} for adjustment`); | |
| }); | |
| }); | |
| // Create body zones | |
| const bodyZones = [ | |
| { name: 'chest', top: 25, left: 35, width: 30, height: 15 }, | |
| { name: 'waist', top: 45, left: 40, width: 20, height: 10 }, | |
| { name: 'hips', top: 60, left: 38, width: 24, height: 10 }, | |
| { name: 'legs', top: 70, left: 35, width: 30, height: 25 } | |
| ]; | |
| // Create zones | |
| bodyZones.forEach(zone => { | |
| const zoneDiv = document.createElement('div'); | |
| zoneDiv.className = 'body-zone'; | |
| zoneDiv.style.top = `${zone.top}%`; | |
| zoneDiv.style.left = `${zone.left}%`; | |
| zoneDiv.style.width = `${zone.width}%`; | |
| zoneDiv.style.height = `${zone.height}%`; | |
| zoneDiv.setAttribute('data-zone', zone.name); | |
| zonesContainer.appendChild(zoneDiv); | |
| }); | |
| } | |
| // Highlight a body zone | |
| function highlightBodyZone(zoneName) { | |
| const zones = document.querySelectorAll('.body-zone'); | |
| zones.forEach(zone => { | |
| if (zone.getAttribute('data-zone') === zoneName) { | |
| zone.style.background = 'rgba(102, 126, 234, 0.3)'; | |
| zone.style.border = '2px solid rgba(102, 126, 234, 0.9)'; | |
| } else { | |
| zone.style.background = 'rgba(102, 126, 234, 0.1)'; | |
| zone.style.border = '2px dashed rgba(102, 126, 234, 0.7)'; | |
| } | |
| }); | |
| // Adjust sliders based on zone | |
| switch(zoneName) { | |
| case 'chest': | |
| chestSlider.focus(); | |
| break; | |
| case 'waist': | |
| waistSlider.focus(); | |
| break; | |
| case 'hips': | |
| hipsSlider.focus(); | |
| break; | |
| case 'legs': | |
| slimSlider.focus(); | |
| break; | |
| } | |
| } | |
| // Activate a tool | |
| function activateTool(tool) { | |
| // Remove active state from all tools | |
| toolButtons.forEach(button => { | |
| button.classList.remove('ring-2', 'ring-white'); | |
| }); | |
| // Add active state to clicked tool | |
| event.currentTarget.classList.add('ring-2', 'ring-white'); | |
| // Show appropriate adjustments based on tool | |
| switch(tool) { | |
| case 'slim': | |
| slimSlider.focus(); | |
| addChatMessage('You', 'Activated slimming tool'); | |
| break; | |
| case 'tall': | |
| heightSlider.focus(); | |
| addChatMessage('You', 'Activated height adjustment tool'); | |
| break; | |
| case 'muscle': | |
| muscleSlider.focus(); | |
| addChatMessage('You', 'Activated muscle definition tool'); | |
| break; | |
| case 'waist': | |
| waistSlider.focus(); | |
| addChatMessage('You', 'Activated waist adjustment tool'); | |
| break; | |
| case 'chest': | |
| chestSlider.focus(); | |
| addChatMessage('You', 'Activated chest adjustment tool'); | |
| break; | |
| case 'hips': | |
| hipsSlider.focus(); | |
| addChatMessage('You', 'Activated hips adjustment tool'); | |
| break; | |
| } | |
| } | |
| // Update adjustments based on slider values | |
| function updateSlimAdjustment() { | |
| adjustments.slim = slimSlider.value; | |
| slimValue.textContent = adjustments.slim; | |
| applyBodyAdjustments(); | |
| } | |
| function updateHeightAdjustment() { | |
| adjustments.height = heightSlider.value; | |
| heightValue.textContent = adjustments.height; | |
| applyBodyAdjustments(); | |
| } | |
| function updateMuscleAdjustment() { | |
| adjustments.muscle = muscleSlider.value; | |
| muscleValue.textContent = adjustments.muscle; | |
| applyBodyAdjustments(); | |
| } | |
| function updateWaistAdjustment() { | |
| adjustments.waist = waistSlider.value; | |
| waistValue.textContent = adjustments.waist; | |
| applyBodyAdjustments(); | |
| } | |
| function updateChestAdjustment() { | |
| adjustments.chest = chestSlider.value; | |
| chestValue.textContent = adjustments.chest; | |
| applyBodyAdjustments(); | |
| } | |
| function updateHipsAdjustment() { | |
| adjustments.hips = hipsSlider.value; | |
| hipsValue.textContent = adjustments.hips; | |
| applyBodyAdjustments(); | |
| } | |
| // Apply body adjustments to the image | |
| function applyBodyAdjustments() { | |
| if (!currentImage) return; | |
| // In a real application, this would use a canvas and image processing | |
| // For this demo, we'll just simulate the effect | |
| // Show loading effect | |
| bodyImage.style.opacity = '0.7'; | |
| // Simulate processing delay | |
| setTimeout(() => { | |
| bodyImage.style.opacity = '1'; | |
| // Add chat message about the adjustment | |
| const totalAdjustment = Object.values(adjustments).reduce((sum, val) => sum + Math.abs(val), 0); | |
| if (totalAdjustment > 0) { | |
| addChatMessage('System', `Applied adjustments: Slim ${adjustments.slim}%, Height ${adjustments.height}%, Muscle ${adjustments.muscle}%`); | |
| } | |
| }, 300); | |
| } | |
| // Reset all adjustments | |
| function resetAdjustments() { | |
| adjustments = { | |
| slim: 0, | |
| height: 0, | |
| muscle: 0, | |
| waist: 0, | |
| chest: 0, | |
| hips: 0 | |
| }; | |
| // Reset sliders | |
| slimSlider.value = 0; | |
| heightSlider.value = 0; | |
| muscleSlider.value = 0; | |
| waistSlider.value = 0; | |
| chestSlider.value = 0; | |
| hipsSlider.value = 0; | |
| // Update value displays | |
| slimValue.textContent = '0'; | |
| heightValue.textContent = '0'; | |
| muscleValue.textContent = '0'; | |
| waistValue.textContent = '0'; | |
| chestValue.textContent = '0'; | |
| hipsValue.textContent = '0'; | |
| // Reset image | |
| bodyImage.src = originalImage; | |
| // Add message to chat | |
| addChatMessage('You', 'Reset all body adjustments'); | |
| } | |
| // Download the edited image | |
| function downloadImage() { | |
| if (!currentImage) { | |
| addChatMessage('System', 'Please upload an image first'); | |
| return; | |
| } | |
| // Create a temporary link to download the image | |
| const link = document.createElement('a'); | |
| link.download = 'edited-body-image.png'; | |
| link.href = currentImage; | |
| link.click(); | |
| // Add message to chat | |
| addChatMessage('System', 'Body image downloaded successfully!'); | |
| } | |
| // Chat functionality | |
| function sendMessage() { | |
| const message = messageInput.value.trim(); | |
| if (message) { | |
| addChatMessage('You', message); | |
| messageInput.value = ''; | |
| // Simulate AI response | |
| setTimeout(() => { | |
| const responses = [ | |
| "I can help you adjust that area. Try using the sliders to fine-tune the effect.", | |
| "For more natural results, make small adjustments to multiple areas.", | |
| "Body editing works best when you maintain natural proportions.", | |
| "Would you like me to suggest some quick presets for common body types?", | |
| "You can use the body markers to quickly select specific areas for editing.", | |
| "The muscle definition tool works well with the chest and arms areas.", | |
| "Try the height adjustment for a more balanced overall look." | |
| ]; | |
| const randomResponse = responses[Math.floor(Math.random() * responses.length)]; | |
| addChatMessage('AI Assistant', randomResponse); | |
| }, 1000); | |
| } | |
| } | |
| // Add a message to the chat | |
| function addChatMessage(user, message) { | |
| const time = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); | |
| const messageDiv = document.createElement('div'); | |
| messageDiv.className = 'chat-bubble mb-3'; | |
| messageDiv.innerHTML = ` | |
| <div class="flex items-start gap-2"> | |
| <div class="w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-sm font-semibold"> | |
| ${user[0]} | |
| </div> | |
| <div class="flex-1"> | |
| <div class="flex items-center gap-2 mb-1"> | |
| <span class="text-white font-semibold text-sm">${user}</span> | |
| <span class="text-white/60 text-xs">${time}</span> | |
| </div> | |
| <p class="text-white/90 text-sm">${message}</p> | |
| </div> | |
| `; | |
| chatMessages.appendChild(messageDiv); | |
| messagesEnd.scrollIntoView({ behavior: 'smooth' }); | |
| } | |
| // Initialize the app when DOM is loaded | |
| document.addEventListener('DOMContentLoaded', init); | |
| </script> | |
| </body> | |
| </html> |