摩搭api 实现
AI图片生成器前端实现详解
本文详细解析一个功能完整的AI图片生成器前端实现,包含主题切换、参数配置、图片生成与预览等核心功能。
项目概述
这是一个基于ModelScope平台的AI图片生成器前端实现,用户可以通过输入提示词、选择模型和调整参数来生成高质量图片。该应用具有响应式设计、暗黑/明亮模式切换、图片预览和下载等完整功能。
下面是完整的实现代码:
<!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><style>:root {--bg-color: #f5f7fa;--text-color: #333;--panel-bg: #ffffff;--border-color: #e1e4e8;--primary-color: #4a6bdf;--secondary-color: #f0f2f5;--button-hover: #3a5bd9;--input-bg: #ffffff;--progress-bg: #e0e0e0;--image-bg: #f0f0f0;--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);--transition: all 0.3s ease;}.dark-mode {--bg-color: #1a1a1a;--text-color: #e0e0e0;--panel-bg: #2d2d2d;--border-color: #444;--primary-color: #5d7eff;--secondary-color: #3a3a3a;--button-hover: #4a6bdf;--input-bg: #3a3a3a;--progress-bg: #444;--image-bg: #2a2a2a;--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);}* {box-sizing: border-box;margin: 0;padding: 0;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;}body {background-color: var(--bg-color);color: var(--text-color);transition: var(--transition);line-height: 1.6;}.container {max-width: 1200px;margin: 0 auto;padding: 20px;display: flex;flex-direction: column;min-height: 100vh;}header {display: flex;justify-content: space-between;align-items: center;margin-bottom: 30px;padding-bottom: 15px;border-bottom: 1px solid var(--border-color);}h1 {font-size: 28px;color: var(--primary-color);font-weight: 700;letter-spacing: 0.5px;}.theme-toggle {background: var(--secondary-color);border: none;padding: 8px 15px;border-radius: 30px;cursor: pointer;color: var(--text-color);display: flex;align-items: center;gap: 8px;transition: var(--transition);font-weight: 500;box-shadow: var(--box-shadow);}.theme-toggle:hover {background: var(--border-color);transform: translateY(-2px);}.main-content {display: flex;gap: 25px;flex: 1;}.panel {background: var(--panel-bg);border-radius: 12px;padding: 25px;box-shadow: var(--box-shadow);border: 1px solid var(--border-color);transition: var(--transition);}.params-panel {flex: 0 0 400px;display: flex;flex-direction: column;}.preview-panel {flex: 1;display: flex;flex-direction: column;}.panel-title {font-size: 20px;margin-bottom: 20px;color: var(--primary-color);font-weight: 600;position: relative;padding-bottom: 10px;}.panel-title::after {content: '';position: absolute;bottom: 0;left: 0;width: 50px;height: 3px;background: var(--primary-color);border-radius: 3px;}.form-group {margin-bottom: 20px;}label {display: block;margin-bottom: 8px;font-weight: 500;color: var(--text-color);}input, select, textarea {width: 100%;padding: 12px;border: 1px solid var(--border-color);border-radius: 8px;background: var(--input-bg);color: var(--text-color);font-size: 14px;transition: var(--transition);}input:focus, select:focus, textarea:focus {outline: none;border-color: var(--primary-color);box-shadow: 0 0 0 2px rgba(74, 107, 223, 0.2);}textarea {min-height: 120px;resize: vertical;}.advanced-params {margin-top: 20px;padding-top: 20px;border-top: 1px solid var(--border-color);}.param-row {display: flex;gap: 15px;margin-bottom: 15px;}.param-item {flex: 1;}button {background: var(--primary-color);color: white;border: none;padding: 12px 20px;border-radius: 8px;cursor: pointer;font-weight: 500;transition: var(--transition);box-shadow: var(--box-shadow);}button:hover {background: var(--button-hover);transform: translateY(-2px);}button:active {transform: translateY(0);}button:disabled {background: #cccccc;cursor: not-allowed;transform: none;}.status-area {margin-top: 20px;padding: 15px;background: var(--secondary-color);border-radius: 8px;min-height: 20px;font-size: 14px;border-left: 4px solid var(--primary-color);}.progress-container {margin-top: 20px;}progress {width: 100%;height: 10px;border-radius: 5px;background: var(--progress-bg);border: none;}progress::-webkit-progress-bar {background: var(--progress-bg);border-radius: 5px;}progress::-webkit-progress-value {background: var(--primary-color);border-radius: 5px;transition: width 0.3s ease;}progress::-moz-progress-bar {background: var(--primary-color);border-radius: 5px;}.preview-container {flex: 1;display: flex;justify-content: center;align-items: center;background: var(--image-bg);border-radius: 12px;overflow: hidden;position: relative;transition: var(--transition);cursor: pointer;}.preview-container:hover {box-shadow: 0 0 0 2px var(--primary-color);}.preview-image {max-width: 100%;max-height: 100%;object-fit: contain;display: none;transition: var(--transition);}.preview-placeholder {text-align: center;padding: 30px;color: var(--text-color);opacity: 0.7;font-size: 16px;}.time-info {margin-top: 15px;font-size: 14px;color: var(--primary-color);font-weight: 500;text-align: center;}.action-buttons {display: flex;gap: 15px;margin-top: 20px;}.secondary-button {background: var(--secondary-color);color: var(--text-color);}.secondary-button:hover {background: var(--border-color);}/* 图片放大模态框样式 */.modal {display: none;position: fixed;z-index: 1000;left: 0;top: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.8);overflow: auto;opacity: 0;transition: opacity 0.3s ease;}.modal.show {display: flex;justify-content: center;align-items: center;opacity: 1;}.modal-content {max-width: 90%;max-height: 90%;object-fit: contain;animation: zoomIn 0.3s ease;}.close-modal {position: absolute;top: 20px;right: 30px;color: white;font-size: 35px;font-weight: bold;cursor: pointer;transition: transform 0.2s ease;}.close-modal:hover {transform: rotate(90deg);}@keyframes zoomIn {from {transform: scale(0.8);opacity: 0;}to {transform: scale(1);opacity: 1;}}/* 加载动画 */.loader {display: none;width: 48px;height: 48px;margin: 20px auto;border: 5px solid rgba(74, 107, 223, 0.2);border-radius: 50%;border-top-color: var(--primary-color);animation: spin 1s ease-in-out infinite;}@keyframes spin {to {transform: rotate(360deg);}}@media (max-width: 768px) {.main-content {flex-direction: column;}.params-panel {flex: 1;}header {flex-direction: column;gap: 15px;align-items: flex-start;}.action-buttons {flex-direction: column;}}</style>
</head>
<body>
<div class="container"><header><h1>AI 图片生成器</h1><button class="theme-toggle" id="themeToggle"><span id="themeIcon">🌙</span> <span id="themeText">暗夜模式</span></button></header><div class="main-content"><div class="panel params-panel"><h2 class="panel-title">生成参数</h2><div class="action-buttons"><button id="generateBtn">生成图片</button><button id="downloadBtn" class="secondary-button" disabled>下载图片</button></div><div class="status-area" id="statusArea">就绪</div><div class="time-info" id="timeInfo"></div><div class="progress-container"><progress id="progressBar" value="0" max="100" style="display: none;"></progress><div class="loader" id="loader"></div></div><div class="form-group"><label for="model">模型选择</label><select id="model"><option value="Qwen/Qwen-Image">Qwen/Qwen-Image</option><option value="Liudef/XB_F.1_MIX">Liudef/XB_F.1_MIX</option><option value="Liudef/XB_PONY">Liudef/XB_PONY</option><option value="Liudef/XB_Illustrious">Liudef/XB_Illustrious</option><option value="Liudef/XB_QWEN_ANIYA_FACE6_C">Liudef/XB_QWEN_ANIYA_FACE6_C</option><option value="Liudef/XB_F.1_ANIYA_FACE6_B">Liudef/XB_F.1_ANIYA_FACE6_B</option><option value="Liudef/XB_F.1_FACE_3">Liudef/XB_F.1_FACE_3</option><option value="Liudef/XB_F.1_MD">Liudef/XB_F.1_MD</option></select></div><div class="form-group"><label for="prompt">正向提示词</label><textarea id="prompt" placeholder="请输入详细的描述词以获得更好的效果...">一只棕色的猫</textarea></div><div class="form-group"><label for="negativePrompt">负向提示词 (可选)</label><textarea id="negativePrompt" placeholder="请输入不希望出现在图片中的内容...">lowres, bad anatomy, bad hands, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, username, blurry</textarea></div><div class="advanced-params"><h3 class="panel-title">高级参数</h3><div class="param-row"><div class="param-item"><label for="width">宽度</label><input type="number" id="width" min="64" max="2048" step="64" value="1024"></div><div class="param-item"><label for="height">高度</label><input type="number" id="height" min="64" max="2048" step="64" value="1024"></div></div><div class="param-row"><div class="param-item"><label for="steps">采样步数</label><input type="number" id="steps" min="1" max="100" value="30"></div><div class="param-item"><label for="guidance">引导系数</label><input type="number" id="guidance" min="1.5" max="20" step="0.1" value="3.5"></div></div></div>