anycoder-d281bf2b / index.html
Abhi1907's picture
Upload folder using huggingface_hub
14fc3dd verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Z-Image Turbo | AI Image Generator</title>
<!-- Importing FontAwesome for Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
/* Color Palette - Cyberpunk/Dark Mode */
--bg-color: #0f1115;
--panel-bg: #181b21;
--input-bg: #22262e;
--primary: #6366f1; /* Indigo */
--primary-hover: #4f46e5;
--accent: #ec4899; /* Pink */
--text-main: #ffffff;
--text-muted: #9ca3af;
--border-color: #2d313a;
--success: #10b981;
--radius-md: 12px;
--radius-sm: 8px;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--glow: 0 0 15px rgba(99, 102, 241, 0.3);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}
body {
background-color: var(--bg-color);
color: var(--text-main);
min-height: 100vh;
display: flex;
flex-direction: column;
overflow-x: hidden;
}
/* --- Header --- */
header {
background-color: rgba(15, 17, 21, 0.9);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border-color);
padding: 1rem 2rem;
position: sticky;
top: 0;
z-index: 100;
display: flex;
justify-content: space-between;
align-items: center;
}
.brand {
display: flex;
align-items: center;
gap: 10px;
font-size: 1.5rem;
font-weight: 700;
background: linear-gradient(to right, var(--primary), var(--accent));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: -0.5px;
}
.brand i {
-webkit-text-fill-color: var(--primary);
font-size: 1.2rem;
}
.anycoder-link {
font-size: 0.9rem;
color: var(--text-muted);
text-decoration: none;
transition: color 0.3s ease;
border: 1px solid var(--border-color);
padding: 0.4rem 0.8rem;
border-radius: var(--radius-sm);
background: var(--panel-bg);
}
.anycoder-link:hover {
color: var(--primary);
border-color: var(--primary);
}
/* --- Main Layout --- */
main {
flex: 1;
display: grid;
grid-template-columns: 350px 1fr;
gap: 2rem;
padding: 2rem;
max-width: 1600px;
margin: 0 auto;
width: 100%;
}
/* --- Sidebar / Controls --- */
.controls-panel {
background: var(--panel-bg);
border-radius: var(--radius-md);
padding: 1.5rem;
border: 1px solid var(--border-color);
height: fit-content;
box-shadow: var(--shadow);
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.control-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
label {
font-size: 0.85rem;
font-weight: 600;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.5px;
}
textarea {
background: var(--input-bg);
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
color: var(--text-main);
padding: 1rem;
resize: vertical;
min-height: 120px;
font-size: 1rem;
transition: border-color 0.3s;
}
textarea:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.1);
}
select, input[type="text"] {
background: var(--input-bg);
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
color: var(--text-main);
padding: 0.75rem;
font-size: 0.95rem;
width: 100%;
}
select:focus, input[type="text"]:focus {
outline: none;
border-color: var(--primary);
}
.ratio-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.5rem;
}
.ratio-btn {
background: var(--input-bg);
border: 1px solid var(--border-color);
color: var(--text-muted);
padding: 0.6rem;
border-radius: var(--radius-sm);
cursor: pointer;
transition: all 0.2s;
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
}
.ratio-btn i {
font-size: 1.2rem;
}
.ratio-btn span {
font-size: 0.7rem;
}
.ratio-btn:hover {
background: var(--border-color);
}
.ratio-btn.active {
background: rgba(99, 102, 241, 0.1);
border-color: var(--primary);
color: var(--primary);
}
.generate-btn {
background: linear-gradient(135deg, var(--primary), var(--accent));
color: white;
border: none;
padding: 1rem;
border-radius: var(--radius-sm);
font-size: 1rem;
font-weight: 700;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
box-shadow: var(--glow);
}
.generate-btn:hover {
transform: translateY(-2px);
box-shadow: 0 0 25px rgba(99, 102, 241, 0.5);
}
.generate-btn:active {
transform: translateY(0);
}
.generate-btn:disabled {
opacity: 0.7;
cursor: not-allowed;
transform: none;
}
/* --- Preview Area --- */
.preview-panel {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.image-container {
background: var(--panel-bg);
border-radius: var(--radius-md);
border: 1px solid var(--border-color);
min-height: 500px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
box-shadow: var(--shadow);
}
.generated-image {
max-width: 100%;
max-height: 600px;
object-fit: contain;
opacity: 0;
transition: opacity 0.5s ease;
}
.generated-image.loaded {
opacity: 1;
}
.placeholder-text {
position: absolute;
color: var(--text-muted);
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
}
.placeholder-text i {
font-size: 3rem;
opacity: 0.3;
}
/* Loading State */
.loader-overlay {
position: absolute;
inset: 0;
background: rgba(15, 17, 21, 0.8);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 10;
backdrop-filter: blur(5px);
}
.loader-overlay.active {
display: flex;
}
.spinner {
width: 50px;
height: 50px;
border: 3px solid rgba(255, 255, 255, 0.1);
border-radius: 50%;
border-top-color: var(--primary);
animation: spin 1s ease-in-out infinite;
margin-bottom: 1rem;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.loading-text {
font-family: monospace;
color: var(--primary);
font-size: 0.9rem;
}
/* Action Bar */
.action-bar {
display: flex;
justify-content: flex-end;
gap: 1rem;
opacity: 0.5;
pointer-events: none;
transition: opacity 0.3s;
}
.action-bar.active {
opacity: 1;
pointer-events: all;
}
.action-btn {
background: var(--input-bg);
border: 1px solid var(--border-color);
color: var(--text-main);
padding: 0.6rem 1.2rem;
border-radius: var(--radius-sm);
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
transition: all 0.2s;
}
.action-btn:hover {
background: var(--border-color);
color: white;
}
.action-btn.primary {
background: var(--primary);
border-color: var(--primary);
}
.action-btn.primary:hover {
background: var(--primary-hover);
}
/* History Grid */
.history-section h3 {
margin-bottom: 1rem;
font-size: 1.1rem;
color: var(--text-main);
}
.history-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
gap: 1rem;
}
.history-item {
aspect-ratio: 1;
border-radius: var(--radius-sm);
overflow: hidden;
cursor: pointer;
border: 2px solid transparent;
transition: all 0.2s;
position: relative;
}
.history-item:hover {
transform: scale(1.05);
border-color: var(--primary);
}
.history-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Toast Notification */
.toast {
position: fixed;
bottom: 2rem;
right: 2rem;
background: var(--panel-bg);
border: 1px solid var(--border-color);
padding: 1rem 1.5rem;
border-radius: var(--radius-sm);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
transform: translateY(100px);
opacity: 0;
transition: all 0.3s cubic-bezier(0.68, -0.55, 0.27, 1.55);
z-index: 1000;
display: flex;
align-items: center;
gap: 0.8rem;
}
.toast.show {
transform: translateY(0);
opacity: 1;
}
.toast i {
color: var(--success);
}
/* Responsive */
@media (max-width: 900px) {
main {
grid-template-columns: 1fr;
}
.controls-panel {
order: 2;
}
.preview-panel {
order: 1;
}
}
</style>
</head>
<body>
<header>
<div class="brand">
<i class="fa-solid fa-bolt"></i>
Z-Image Turbo
</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
Built with anycoder <i class="fa-solid fa-arrow-up-right-from-square" style="font-size: 0.7em; margin-left: 5px;"></i>
</a>
</header>
<main>
<!-- Sidebar Controls -->
<section class="controls-panel">
<div class="control-group">
<label for="prompt">Prompt</label>
<textarea id="prompt" placeholder="Describe the image you want to generate... e.g., A futuristic cyberpunk city with neon lights, 4k, highly detailed"></textarea>
</div>
<div class="control-group">
<label for="negative-prompt">Negative Prompt</label>
<input type="text" id="negative-prompt" placeholder="blur, low quality, distorted">
</div>
<div class="control-group">
<label>Aspect Ratio</label>
<div class="ratio-grid">
<button class="ratio-btn active" data-ratio="1:1" data-w="1024" data-h="1024">
<i class="fa-regular fa-square"></i>
<span>1:1</span>
</button>
<button class="ratio-btn" data-ratio="16:9" data-w="1280" data-h="720">
<i class="fa-solid fa-rectangle-wide"></i>
<span>16:9</span>
</button>
<button class="ratio-btn" data-ratio="9:16" data-w="720" data-h="1280">
<i class="fa-solid fa-mobile-screen"></i>
<span>9:16</span>
</button>
</div>
</div>
<div class="control-group">
<label for="style">Style Preset</label>
<select id="style">
<option value="none">None (Default)</option>
<option value="cinematic">Cinematic</option>
<option value="anime">Anime / Manga</option>
<option value="3d-model">3D Model</option>
<option value="digital-art">Digital Art</option>
<option value="photographic">Photographic</option>
</select>
</div>
<div class="control-group">
<label for="steps">Inference Steps</label>
<input type="range" id="steps" min="10" max="50" value="25" style="width: 100%; accent-color: var(--primary);">
<div style="display: flex; justify-content: space-between; font-size: 0.8rem; color: var(--text-muted);">
<span>Fast</span>
<span id="steps-val">25</span>
<span>Quality</span>
</div>
</div>
<button id="generate-btn" class="generate-btn">
<i class="fa-solid fa-wand-magic-sparkles"></i> Generate Image
</button>
</section>
<!-- Preview Area -->
<section class="preview-panel">
<div class="image-container" id="image-container">
<div class="placeholder-text" id="placeholder">
<i class="fa-regular fa-image"></i>
<p>Enter a prompt and click Generate</p>
</div>
<div class="loader-overlay" id="loader">
<div class="spinner"></div>
<div class="loading-text" id="loading-text">Initializing Z-Image Turbo...</div>
</div>
<img src="" alt="Generated AI Art" class="generated-image" id="main-image">
</div>
<div class="action-bar" id="action-bar">
<button class="action-btn" id="copy-seed-btn">
<i class="fa-solid fa-fingerprint"></i> Copy Seed
</button>
<button class="action-btn primary" id="download-btn">
<i class="fa-solid fa-download"></i> Download HD
</button>
</div>
<div class="history-section">
<h3>Recent Generations</h3>
<div class="history-grid" id="history-grid">
<!-- History items will be injected here -->
</div>
</div>
</section>
</main>
<!-- Toast Notification -->
<div class="toast" id="toast">
<i class="fa-solid fa-circle-check"></i>
<span id="toast-message">Operation successful</span>
</div>
<script>
// DOM Elements
const promptInput = document.getElementById('prompt');
const negativePromptInput = document.getElementById('negative-prompt');
const generateBtn = document.getElementById('generate-btn');
const mainImage = document.getElementById('main-image');
const loader = document.getElementById('loader');
const loadingText = document.getElementById('loading-text');
const placeholder = document.getElementById('placeholder');
const actionBar = document.getElementById('action-bar');
const downloadBtn = document.getElementById('download-btn');
const copySeedBtn = document.getElementById('copy-seed-btn');
const historyGrid = document.getElementById('history-grid');
const ratioBtns = document.querySelectorAll('.ratio-btn');
const stepsInput = document.getElementById('steps');
const stepsVal = document.getElementById('steps-val');
const styleSelect = document.getElementById('style');
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toast-message');
// State
let currentSeed = '';
let currentWidth = 1024;
let currentHeight = 1024;
let isGenerating = false;
// Event Listeners for Aspect Ratio
ratioBtns.forEach(btn => {
btn.addEventListener('click', () => {
ratioBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
currentWidth = parseInt(btn.dataset.w);
currentHeight = parseInt(btn.dataset.h);
});
});
// Step Slider Update
stepsInput.addEventListener('input', (e) => {
stepsVal.textContent = e.target.value;
});
// Generate Button Logic
generateBtn.addEventListener('click', generateImage);
// Helper: Show Toast
function showToast(msg) {
toastMessage.textContent = msg;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, 3000);
}
// Helper: Generate a random seed based on prompt + random
function generateSeed(text) {
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
let result = text.replace(/[^a-zA-Z0-9]/g, '').substring(0, 10);
if (result.length < 5) result += 'zimageturbo'; // Fallback for short prompts
// Add randomness for unique generations of same prompt
const randomPart = Math.random().toString(36).substring(2, 7);
return result + randomPart;
}
async function generateImage() {
const prompt = promptInput.value.trim();
if (!prompt) {
showToast("Please enter a text prompt first.");
promptInput.focus();
return;
}
if (isGenerating) return;
isGenerating = true;
// UI Updates: Start Loading
generateBtn.disabled = true;
generateBtn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Generating...';
loader.classList.add('active');
placeholder.style.display = 'none';
mainImage.classList.remove('loaded');
actionBar.classList.remove('active');
// Simulate AI Steps for realism
const steps = [
"Encoding text prompt...",
"Initializing latent space...",
"Running Z-Image Turbo diffusion...",
"Denoising step 5/25...",
"Denoising step 15/25...",
"Upscaling result...",
"Finalizing render..."
];
let stepIndex = 0;
const stepInterval = setInterval(() => {
if (stepIndex < steps.length) {
loadingText.textContent = steps[stepIndex];
stepIndex++;
}
}, 400);
// Calculate Seed and Construct URL
// Note: Using picsum.photos as a placeholder for the actual AI generation.
// In a real app, this would be a fetch() call to the Z-Image Turbo API.
currentSeed = generateSeed(prompt);
// We use the seed to get a deterministic image from picsum
// We use the width/height settings from the UI
const imageUrl = `https://picsum.photos/seed/${currentSeed}/${currentWidth}/${currentHeight}`;
// Wait for simulated processing time (min 2.5s)
await new Promise(r => setTimeout(r, 2500));
clearInterval(stepInterval);
// Load Image
mainImage.src = imageUrl;
mainImage.onload = () => {
// Reset UI
isGenerating = false;
generateBtn.disabled = false;
generateBtn.innerHTML = '<i class="fa-solid fa-wand-magic-sparkles"></i> Generate Image';
loader.classList.remove('active');
mainImage.classList.add('loaded');
actionBar.classList.add('active');
loadingText.textContent = "Initializing Z-Image Turbo..."; // Reset text
// Add to history
addToHistory(imageUrl);
showToast("Image generated successfully!");
};
mainImage.onerror = () => {
isGenerating = false;
generateBtn.disabled = false;
generateBtn.innerHTML = '<i class="fa-solid fa-wand-magic-sparkles"></i> Generate Image';
loader.classList.remove('active');
placeholder.style.display = 'flex';
showToast("Error generating image. Try again.");
};
}
function addToHistory(url) {
const item = document.createElement('div');
item.className = 'history-item';
item.innerHTML = `<img src="${url}" alt="History Item">`;
item.addEventListener('click', () => {
mainImage.src = url;
mainImage.classList.add('loaded');
placeholder.style.display = 'none';
actionBar.classList.add('active');
// In a real app, we'd restore the prompt/seed data here too
});
// Add to beginning
historyGrid.insertBefore(item, historyGrid.firstChild);
// Limit history to 8 items
if (historyGrid.children.length > 8) {
historyGrid.removeChild(historyGrid.lastChild);
}
}
// Download Functionality
downloadBtn.addEventListener('click', async () => {
if (!mainImage.src) return;
try {
// Fetch blob to avoid cross-origin taint issues on some browsers
const response = await fetch(mainImage.src);
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = `z-image-${currentSeed}.jpg`;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
showToast("Download started");
} catch (err) {
console.error(err);
// Fallback: Open in new tab
window.open(mainImage.src, '_blank');
}
});
// Copy Seed Functionality
copySeedBtn.addEventListener('click', () => {
if (!currentSeed) return;
navigator.clipboard.writeText(currentSeed).then(() => {
showToast("Seed copied to clipboard");
});
});
</script>
</body>
</html>