| <!DOCTYPE html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>AI 文生图生成器</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> |
| <style> |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); |
| |
| body { |
| font-family: 'Inter', sans-serif; |
| background: linear-gradient(135deg, #f0f9ff 0%, #f5f3ff 100%); |
| } |
| |
| .gradient-text { |
| background: linear-gradient(90deg, #3b82f6 0%, #8b5cf6 100%); |
| -webkit-background-clip: text; |
| background-clip: text; |
| color: transparent; |
| } |
| |
| .range-slider::-webkit-slider-thumb { |
| -webkit-appearance: none; |
| appearance: none; |
| width: 18px; |
| height: 18px; |
| background: #6366f1; |
| cursor: pointer; |
| border-radius: 50%; |
| } |
| |
| .range-slider::-moz-range-thumb { |
| width: 18px; |
| height: 18px; |
| background: #6366f1; |
| cursor: pointer; |
| border-radius: 50%; |
| } |
| |
| .toggle-checkbox:checked { |
| right: 0; |
| border-color: #6366f1; |
| } |
| |
| .toggle-checkbox:checked + .toggle-label { |
| background-color: #6366f1; |
| } |
| |
| .model-select:focus { |
| box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.3); |
| } |
| |
| .generated-image { |
| transition: all 0.3s ease; |
| } |
| |
| .generated-image:hover { |
| transform: scale(1.02); |
| } |
| |
| |
| @keyframes loading-pulse { |
| 0%, 100% { |
| opacity: 0.4; |
| } |
| 50% { |
| opacity: 1; |
| } |
| } |
| |
| .loading-animation { |
| animation: loading-pulse 1.5s infinite ease-in-out; |
| } |
| |
| .loading-animation-delay-100 { |
| animation-delay: 0.1s; |
| } |
| |
| .loading-animation-delay-200 { |
| animation-delay: 0.2s; |
| } |
| </style> |
| </head> |
| <body class="min-h-screen"> |
| <div class="container mx-auto px-4 py-8"> |
| |
| <div class="text-center mb-8"> |
| <h1 class="text-4xl font-bold mb-2 gradient-text">AI 文生图生成器</h1> |
| <p class="text-gray-600">使用先进的 AI 技术将您的文字描述转化为精美图像</p> |
| </div> |
| |
| |
| <div class="flex flex-col lg:flex-row gap-8"> |
| |
| <div class="w-full lg:w-1/3 bg-white rounded-xl shadow-lg p-6"> |
| <h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center"> |
| <i class="fas fa-sliders-h mr-2 text-indigo-500"></i> |
| 生成参数 |
| </h2> |
| |
| |
| <div class="mb-6"> |
| <label for="prompt" class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-comment-dots mr-1 text-blue-500"></i> |
| 提示词 |
| </label> |
| <textarea |
| id="prompt" |
| rows="4" |
| class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-200 focus:border-indigo-500 transition" |
| placeholder="描述您想生成的图像 (例如: 一只穿着宇航服的猫在月球上行走,未来科技风格,绚丽光影)" |
| ></textarea> |
| </div> |
| |
| |
| <div class="mb-6"> |
| <label for="negativePrompt" class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-ban mr-1 text-purple-500"></i> |
| 负向提示词 (可选) |
| </label> |
| <input |
| type="text" |
| id="negativePrompt" |
| class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-200 focus:border-indigo-500 transition" |
| placeholder="不想包含的元素 (例如: 模糊的,低质量)" |
| > |
| </div> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6"> |
| |
| <div> |
| <label for="model" class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-robot mr-1 text-blue-400"></i> |
| 模型选择 |
| </label> |
| <select |
| id="model" |
| class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-200 focus:border-indigo-500 transition model-select" |
| > |
| <option value="stable-diffusion">Stable Diffusion</option> |
| <option value="dall-e">DALL·E</option> |
| <option value="midjourney">Midjourney</option> |
| <option value="sd-xl">SD XL</option> |
| </select> |
| </div> |
| |
| |
| <div> |
| <label for="size" class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-expand mr-1 text-purple-400"></i> |
| 图片尺寸 |
| </label> |
| <select |
| id="size" |
| class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-200 focus:border-indigo-500 transition" |
| > |
| <option value="1024x1024">1024x1024 (正方形)</option> |
| <option value="1024x768">1024x768 (宽屏)</option> |
| <option value="768x1024">768x1024 (竖屏)</option> |
| <option value="512x512">512x512 (小正方形)</option> |
| </select> |
| </div> |
| </div> |
| |
| |
| <div class="mb-6"> |
| <label class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-copy mr-1 text-blue-500"></i> |
| 生成数量 |
| </label> |
| <div class="flex items-center gap-4"> |
| <input |
| type="range" |
| min="1" |
| max="4" |
| value="1" |
| class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer range-slider" |
| id="imageCount" |
| > |
| <span id="imageCountValue" class="text-sm font-medium text-indigo-600 w-8 text-center">1</span> |
| </div> |
| </div> |
| |
| |
| <div class="mb-6"> |
| <label class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-bolt mr-1 text-purple-500"></i> |
| 创作强度 (CFG Scale) |
| </label> |
| <div class="flex items-center gap-4"> |
| <input |
| type="range" |
| min="1" |
| max="20" |
| value="7" |
| class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer range-slider" |
| id="cfgScale" |
| > |
| <span id="cfgScaleValue" class="text-sm font-medium text-indigo-600 w-8 text-center">7</span> |
| </div> |
| </div> |
| |
| |
| <div class="mb-6"> |
| <label class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-footsteps mr-1 text-blue-500"></i> |
| 采样步数 |
| </label> |
| <div class="flex items-center gap-4"> |
| <input |
| type="range" |
| min="1" |
| max="50" |
| value="25" |
| class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer range-slider" |
| id="steps" |
| > |
| <span id="stepsValue" class="text-sm font-medium text-indigo-600 w-8 text-center">25</span> |
| </div> |
| </div> |
| |
| |
| <div class="mb-6"> |
| <label for="seed" class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-seedling mr-1 text-purple-500"></i> |
| 随机种子 |
| </label> |
| <div class="flex gap-2"> |
| <input |
| type="number" |
| id="seed" |
| class="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-200 focus:border-indigo-500 transition" |
| placeholder="留空随机" |
| > |
| <button id="randomSeedBtn" class="px-3 py-2 bg-indigo-100 text-indigo-600 rounded-lg hover:bg-indigo-200 transition"> |
| <i class="fas fa-random"></i> |
| </button> |
| </div> |
| </div> |
| |
| |
| <div class="border-t border-gray-200 pt-4 mb-6"> |
| <button id="advancedToggle" class="flex items-center text-sm font-medium text-gray-600 hover:text-indigo-600 transition"> |
| <i class="fas fa-cog mr-2 text-blue-400"></i> |
| 高级选项 |
| <i class="fas fa-chevron-down ml-1 transition-transform" id="advancedArrow"></i> |
| </button> |
| <div id="advancedOptions" class="mt-2 hidden space-y-4"> |
| |
| <div class="flex items-center justify-between"> |
| <label for="fixFaces" class="block text-sm font-medium text-gray-700"> |
| <i class="fas fa-user mr-1 text-purple-400"></i> |
| 修复面部 |
| </label> |
| <div class="relative inline-block w-10 mr-2 align-middle select-none"> |
| <input |
| type="checkbox" |
| id="fixFaces" |
| class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer" |
| checked |
| > |
| <label for="fixFaces" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label> |
| </div> |
| </div> |
| |
| |
| <div class="flex items-center justify-between"> |
| <label for="hiresFix" class="block text-sm font-medium text-gray-700"> |
| <i class="fas fa-search-plus mr-1 text-blue-400"></i> |
| 高清修复 |
| </label> |
| <div class="relative inline-block w-10 mr-2 align-middle select-none"> |
| <input |
| type="checkbox" |
| id="hiresFix" |
| class="toggle-checkbox absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer" |
| > |
| <label for="hiresFix" class="toggle-label block overflow-hidden h-6 rounded-full bg-gray-300 cursor-pointer"></label> |
| </div> |
| </div> |
| |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-2"> |
| <i class="fas fa-paint-brush mr-1 text-purple-400"></i> |
| 风格化程度 |
| </label> |
| <div class="flex items-center gap-4"> |
| <input |
| type="range" |
| min="0" |
| max="100" |
| value="50" |
| class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer range-slider" |
| id="style" |
| > |
| <span id="styleValue" class="text-sm font-medium text-indigo-600 w-8 text-center">50</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <button id="generateBtn" class="w-full py-3 px-4 bg-gradient-to-r from-blue-500 to-purple-600 text-white font-medium rounded-lg shadow-md hover:from-blue-600 hover:to-purple-700 transition-all duration-300 flex items-center justify-center"> |
| <i class="fas fa-magic mr-2"></i> |
| 生成图像 |
| </button> |
| </div> |
| |
| |
| <div class="w-full lg:w-2/3"> |
| <div class="bg-white rounded-xl shadow-lg p-6 h-full flex flex-col"> |
| <h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center"> |
| <i class="fas fa-images mr-2 text-purple-500"></i> |
| 生成结果 |
| </h2> |
| |
| |
| <div id="loadingState" class="hidden flex flex-col items-center justify-center flex-grow py-12"> |
| <div class="flex space-x-2 mb-6"> |
| <div class="w-3 h-3 rounded-full bg-blue-400 loading-animation"></div> |
| <div class="w-3 h-3 rounded-full bg-indigo-400 loading-animation loading-animation-delay-100"></div> |
| <div class="w-3 h-3 rounded-full bg-purple-400 loading-animation loading-animation-delay-200"></div> |
| </div> |
| <h3 class="text-lg font-medium text-gray-700 mb-2">AI 正在创作您描述的图像</h3> |
| <p class="text-gray-500 text-center max-w-md"> |
| 这可能需要几秒钟到一分钟不等,请耐心等待... |
| <br> |
| 正在处理细节和颜色组合 |
| </p> |
| </div> |
| |
| |
| <div id="resultContainer" class="flex-grow flex flex-col"> |
| |
| <div id="initialState" class="flex-grow flex flex-col items-center justify-center py-12"> |
| <div class="mb-6 text-indigo-400"> |
| <svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> |
| </svg> |
| </div> |
| <h3 class="text-lg font-medium text-gray-700 mb-2">等待生成图像</h3> |
| <p class="text-gray-500 text-center max-w-md"> |
| 输入您的提示词并点击"生成图像"按钮<br> |
| AI 将根据您的描述创造独一无二的图像 |
| </p> |
| </div> |
| |
| |
| <div id="generatedImages" class="grid grid-cols-1 md:grid-cols-2 gap-4 hidden"></div> |
| </div> |
| |
| |
| <div id="actionButtons" class="mt-6 flex flex-wrap gap-3 hidden"> |
| <button class="px-4 py-2 bg-indigo-50 text-indigo-600 rounded-lg hover:bg-indigo-100 transition flex items-center"> |
| <i class="fas fa-save mr-2"></i> 保存全部 |
| </button> |
| <button class="px-4 py-2 bg-purple-50 text-purple-600 rounded-lg hover:bg-purple-100 transition flex items-center"> |
| <i class="fas fa-redo mr-2"></i> 重新生成 |
| </button> |
| <button class="px-4 py-2 bg-blue-50 text-blue-600 rounded-lg hover:bg-blue-100 transition flex items-center"> |
| <i class="fas fa-play mr-2"></i> 生成变体 |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="mt-8 bg-white rounded-xl shadow-lg p-6 hidden" id="historySection"> |
| <h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center"> |
| <i class="fas fa-history mr-2 text-blue-500"></i> |
| 生成历史 |
| </h2> |
| <div class="grid grid-cols-2 md:grid-cols-4 gap-4" id="historyGrid"> |
| |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| const promptInput = document.getElementById('prompt'); |
| const negativePromptInput = document.getElementById('negativePrompt'); |
| const modelSelect = document.getElementById('model'); |
| const sizeSelect = document.getElementById('size'); |
| const imageCountSlider = document.getElementById('imageCount'); |
| const imageCountValue = document.getElementById('imageCountValue'); |
| const cfgScaleSlider = document.getElementById('cfgScale'); |
| const cfgScaleValue = document.getElementById('cfgScaleValue'); |
| const stepsSlider = document.getElementById('steps'); |
| const stepsValue = document.getElementById('stepsValue'); |
| const seedInput = document.getElementById('seed'); |
| const randomSeedBtn = document.getElementById('randomSeedBtn'); |
| const fixFacesToggle = document.getElementById('fixFaces'); |
| const hiresFixToggle = document.getElementById('hiresFix'); |
| const styleSlider = document.getElementById('style'); |
| const styleValue = document.getElementById('styleValue'); |
| const advancedToggle = document.getElementById('advancedToggle'); |
| const advancedOptions = document.getElementById('advancedOptions'); |
| const advancedArrow = document.getElementById('advancedArrow'); |
| const generateBtn = document.getElementById('generateBtn'); |
| const loadingState = document.getElementById('loadingState'); |
| const initialState = document.getElementById('initialState'); |
| const generatedImages = document.getElementById('generatedImages'); |
| const actionButtons = document.getElementById('actionButtons'); |
| const historySection = document.getElementById('historySection'); |
| const historyGrid = document.getElementById('historyGrid'); |
| |
| |
| imageCountSlider.addEventListener('input', updateImageCount); |
| cfgScaleSlider.addEventListener('input', updateCfgScale); |
| stepsSlider.addEventListener('input', updateSteps); |
| styleSlider.addEventListener('input', updateStyle); |
| randomSeedBtn.addEventListener('click', generateRandomSeed); |
| advancedToggle.addEventListener('click', toggleAdvancedOptions); |
| generateBtn.addEventListener('click', generateImages); |
| |
| |
| function updateImageCount() { |
| imageCountValue.textContent = imageCountSlider.value; |
| } |
| |
| function updateCfgScale() { |
| cfgScaleValue.textContent = cfgScaleSlider.value; |
| } |
| |
| function updateSteps() { |
| stepsValue.textContent = stepsSlider.value; |
| } |
| |
| function updateStyle() { |
| styleValue.textContent = styleSlider.value; |
| } |
| |
| |
| function generateRandomSeed() { |
| const randomSeed = Math.floor(Math.random() * 1000000000); |
| seedInput.value = randomSeed; |
| } |
| |
| |
| function toggleAdvancedOptions() { |
| advancedOptions.classList.toggle('hidden'); |
| advancedArrow.classList.toggle('rotate-180'); |
| } |
| |
| |
| function generateImages() { |
| const prompt = promptInput.value.trim(); |
| |
| if (!prompt) { |
| alert('请输入提示词以生成图像'); |
| return; |
| } |
| |
| |
| loadingState.classList.remove('hidden'); |
| initialState.classList.add('hidden'); |
| generatedImages.classList.add('hidden'); |
| actionButtons.classList.add('hidden'); |
| |
| |
| historySection.classList.add('hidden'); |
| |
| |
| setTimeout(() => { |
| const count = parseInt(imageCountSlider.value); |
| |
| |
| generatedImages.innerHTML = ''; |
| |
| |
| for (let i = 0; i < count; i++) { |
| const imgCol = document.createElement('div'); |
| imgCol.className = 'relative group'; |
| |
| const imgContainer = document.createElement('div'); |
| imgContainer.className = 'bg-gray-100 rounded-xl overflow-hidden generated-image hover:shadow-md transition-all'; |
| imgContainer.style.aspectRatio = '1/1'; |
| |
| |
| let imgUrl; |
| const randomNum = Math.floor(Math.random() * 4); |
| |
| switch(randomNum) { |
| case 0: |
| imgUrl = 'https://source.unsplash.com/random/800x800/?abstract,sci-fi'; |
| break; |
| case 1: |
| imgUrl = 'https://source.unsplash.com/random/800x800/?digital-art,fantasy'; |
| break; |
| case 2: |
| imgUrl = 'https://source.unsplash.com/random/800x800/?landscape,futuristic'; |
| break; |
| default: |
| imgUrl = 'https://source.unsplash.com/random/800x800/?ai,neon,cyberpunk'; |
| } |
| |
| |
| imgUrl += `&t=${Date.now() + i}`; |
| |
| const img = document.createElement('img'); |
| img.src = imgUrl; |
| img.alt = 'AI 生成的图像'; |
| img.className = 'w-full h-full object-cover'; |
| img.loading = 'lazy'; |
| |
| |
| const hoverActions = document.createElement('div'); |
| hoverActions.className = 'absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300'; |
| |
| const downloadBtn = document.createElement('button'); |
| downloadBtn.className = 'p-2 bg-indigo-600 rounded-full text-white mx-1 hover:bg-indigo-700 transition'; |
| downloadBtn.innerHTML = '<i class="fas fa-download"></i>'; |
| |
| const likeBtn = document.createElement('button'); |
| likeBtn.className = 'p-2 bg-pink-600 rounded-full text-white mx-1 hover:bg-pink-700 transition'; |
| likeBtn.innerHTML = '<i class="fas fa-heart"></i>'; |
| |
| const refreshBtn = document.createElement('button'); |
| refreshBtn.className = 'p-2 bg-blue-600 rounded-full text-white mx-1 hover:bg-blue-700 transition'; |
| refreshBtn.innerHTML = '<i class="fas fa-redo"></i>'; |
| |
| hoverActions.appendChild(downloadBtn); |
| hoverActions.appendChild(likeBtn); |
| hoverActions.appendChild(refreshBtn); |
| |
| imgContainer.appendChild(img); |
| imgContainer.appendChild(hoverActions); |
| imgCol.appendChild(imgContainer); |
| |
| const imgPrompt = document.createElement('p'); |
| imgPrompt.className = 'text-sm text-gray-600 mt-2 truncate'; |
| imgPrompt.textContent = prompt.length > 40 ? prompt.substring(0, 40) + '...' : prompt; |
| |
| imgCol.appendChild(imgPrompt); |
| generatedImages.appendChild(imgCol); |
| } |
| |
| |
| loadingState.classList.add('hidden'); |
| generatedImages.classList.remove('hidden'); |
| actionButtons.classList.remove('hidden'); |
| |
| |
| historySection.classList.remove('hidden'); |
| |
| |
| addHistoryItem(prompt, count); |
| |
| }, 3000); |
| } |
| |
| |
| function addHistoryItem(prompt, count) { |
| const historyItem = document.createElement('div'); |
| historyItem.className = 'relative group'; |
| |
| const imgContainer = document.createElement('div'); |
| imgContainer.className = 'bg-gray-100 rounded-xl overflow-hidden hover:shadow-md transition-all'; |
| imgContainer.style.aspectRatio = '1/1'; |
| |
| |
| const randomNum = Math.floor(Math.random() * 4); |
| let imgUrl; |
| |
| switch(randomNum) { |
| case 0: |
| imgUrl = 'https://source.unsplash.com/random/400x400/?abstract'; |
| break; |
| case 1: |
| imgUrl = 'https://source.unsplash.com/random/400x400/?art'; |
| break; |
| case 2: |
| imgUrl = 'https://source.unsplash.com/random/400x400/?digital'; |
| break; |
| default: |
| imgUrl = 'https://source.unsplash.com/random/400x400/?ai'; |
| } |
| |
| |
| imgUrl += `&t=${Date.now() - Math.floor(Math.random() * 1000000)}`; |
| |
| const img = document.createElement('img'); |
| img.src = imgUrl; |
| img.alt = '历史生成的图像'; |
| img.className = 'w-full h-full object-cover'; |
| img.loading = 'lazy'; |
| |
| imgContainer.appendChild(img); |
| historyItem.appendChild(imgContainer); |
| |
| const promptText = document.createElement('p'); |
| promptText.className = 'text-xs text-gray-600 mt-1 truncate'; |
| promptText.textContent = prompt.length > 30 ? prompt.substring(0, 30) + '...' : prompt; |
| |
| historyItem.appendChild(promptText); |
| historyGrid.insertBefore(historyItem, historyGrid.firstChild); |
| |
| |
| if (historyGrid.children.length > 8) { |
| historyGrid.removeChild(historyGrid.lastChild); |
| } |
| } |
| |
| |
| updateImageCount(); |
| updateCfgScale(); |
| updateSteps(); |
| updateStyle(); |
| generateRandomSeed(); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=exrock/ai" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |