transforme / index.html
Chipema's picture
Crie um fluxo onde:
60d9994 verified
Raw
History Blame Contribute Delete
20.1 kB
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Magic Scene Creator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<style>
.file-input-label:hover .file-input-icon {
transform: translateY(-5px);
transition: all 0.3s ease;
}
.result-card {
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.animate-pulse-slow {
animation: pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
</style>
</head>
<body class="bg-gradient-to-br from-indigo-50 to-purple-50 min-h-screen">
<div class="container mx-auto px-4 py-12">
<!-- Header -->
<header class="text-center mb-16" data-aos="fade-down">
<h1 class="text-4xl md:text-5xl font-bold text-indigo-900 mb-4">Magic Scene Creator</h1>
<p class="text-lg text-indigo-700 max-w-2xl mx-auto">Transforme suas fotos em ilustrações mágicas com um toque pessoal</p>
</header>
<!-- Main Flow -->
<div class="max-w-3xl mx-auto bg-white rounded-2xl shadow-xl overflow-hidden">
<!-- Step 1: Upload Photo -->
<div id="step-1" class="p-8" data-aos="fade-up">
<div class="flex items-center mb-6">
<div class="flex items-center justify-center w-10 h-10 rounded-full bg-indigo-600 text-white font-bold mr-4">1</div>
<h2 class="text-2xl font-semibold text-gray-800">Envie sua foto</h2>
</div>
<div class="mt-6">
<label for="photo-upload" class="file-input-label cursor-pointer flex flex-col items-center justify-center border-2 border-dashed border-indigo-300 rounded-xl p-12 text-center hover:border-indigo-400 transition-colors duration-300">
<div class="file-input-icon mb-4">
<i data-feather="upload" class="w-12 h-12 text-indigo-500"></i>
</div>
<span class="text-lg font-medium text-indigo-700 mb-2">Clique para selecionar uma foto</span>
<span class="text-sm text-gray-500">Formatos suportados: JPG, PNG (até 5MB)</span>
<input id="photo-upload" type="file" accept="image/*" class="hidden">
</label>
</div>
<div id="preview-container" class="mt-6 hidden">
<h3 class="text-lg font-medium text-gray-700 mb-3">Pré-visualização:</h3>
<div class="relative">
<img id="image-preview" src="" alt="Preview" class="rounded-lg w-full max-h-80 object-contain border border-gray-200">
<button id="change-photo" class="absolute top-2 right-2 bg-white rounded-full p-2 shadow-md hover:bg-gray-100">
<i data-feather="x" class="w-4 h-4 text-gray-600"></i>
</button>
</div>
</div>
<div class="mt-8 flex justify-end">
<button id="next-step-1" class="px-6 py-3 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition-colors duration-300 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
Próximo <i data-feather="arrow-right" class="w-4 h-4 ml-2 inline"></i>
</button>
</div>
</div>
<!-- Step 2: Choose Style -->
<div id="step-2" class="p-8 border-t border-gray-200 hidden" data-aos="fade-up">
<div class="flex items-center mb-6">
<div class="flex items-center justify-center w-10 h-10 rounded-full bg-indigo-600 text-white font-bold mr-4">2</div>
<h2 class="text-2xl font-semibold text-gray-800">Escolha o estilo</h2>
</div>
<p class="text-gray-600 mb-8">Como você gostaria que sua foto fosse transformada?</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="style-option cursor-pointer group relative overflow-hidden rounded-xl border-2 border-transparent hover:border-indigo-400 transition-all duration-300">
<input type="radio" name="style" id="childish" value="childish" class="hidden peer">
<label for="childish" class="block">
<div class="relative">
<img src="http://static.photos/education/640x360/1" alt="Estilo Infantil" class="w-full h-48 object-cover">
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent"></div>
<div class="absolute bottom-0 left-0 p-4">
<h3 class="text-xl font-bold text-white">Infantil Lúdico</h3>
<p class="text-indigo-100">Cores vibrantes, elementos mágicos</p>
</div>
</div>
</label>
<div class="absolute top-4 right-4 w-6 h-6 rounded-full border-2 border-white bg-white peer-checked:bg-indigo-600 peer-checked:border-indigo-600 transition-colors duration-300"></div>
</div>
<div class="style-option cursor-pointer group relative overflow-hidden rounded-xl border-2 border-transparent hover:border-indigo-400 transition-all duration-300">
<input type="radio" name="style" id="elegant" value="elegant" class="hidden peer">
<label for="elegant" class="block">
<div class="relative">
<img src="http://static.photos/minimal/640x360/2" alt="Estilo Adulto" class="w-full h-48 object-cover">
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent"></div>
<div class="absolute bottom-0 left-0 p-4">
<h3 class="text-xl font-bold text-white">Adulto Elegante</h3>
<p class="text-indigo-100">Linhas limpas, tons sofisticados</p>
</div>
</div>
</label>
<div class="absolute top-4 right-4 w-6 h-6 rounded-full border-2 border-white bg-white peer-checked:bg-indigo-600 peer-checked:border-indigo-600 transition-colors duration-300"></div>
</div>
</div>
<div class="mt-8 flex justify-between">
<button id="prev-step-2" class="px-6 py-3 bg-gray-200 text-gray-700 rounded-lg font-medium hover:bg-gray-300 transition-colors duration-300">
<i data-feather="arrow-left" class="w-4 h-4 mr-2 inline"></i> Voltar
</button>
<button id="next-step-2" class="px-6 py-3 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition-colors duration-300 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
Próximo <i data-feather="arrow-right" class="w-4 h-4 ml-2 inline"></i>
</button>
</div>
</div>
<!-- Step 3: Add Text -->
<div id="step-3" class="p-8 border-t border-gray-200 hidden" data-aos="fade-up">
<div class="flex items-center mb-6">
<div class="flex items-center justify-center w-10 h-10 rounded-full bg-indigo-600 text-white font-bold mr-4">3</div>
<h2 class="text-2xl font-semibold text-gray-800">Adicione um texto</h2>
</div>
<p class="text-gray-600 mb-6">Insira uma frase ou dedicatória para aparecer na imagem final:</p>
<div class="mb-6">
<textarea id="custom-text" rows="3" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 transition-all duration-300" placeholder="Ex: Feliz aniversário! Que seu dia seja mágico como essa ilustração"></textarea>
<p class="text-sm text-gray-500 mt-2">Máximo de 120 caracteres</p>
</div>
<div class="flex items-center mb-6">
<input type="checkbox" id="add-watermark" class="w-4 h-4 text-indigo-600 rounded focus:ring-indigo-500">
<label for="add-watermark" class="ml-2 text-gray-700">Adicionar marca d'água "Criado com Magic Scene"</label>
</div>
<div class="mt-8 flex justify-between">
<button id="prev-step-3" class="px-6 py-3 bg-gray-200 text-gray-700 rounded-lg font-medium hover:bg-gray-300 transition-colors duration-300">
<i data-feather="arrow-left" class="w-4 h-4 mr-2 inline"></i> Voltar
</button>
<button id="generate-btn" class="px-6 py-3 bg-gradient-to-r from-indigo-600 to-purple-600 text-white rounded-lg font-medium hover:from-indigo-700 hover:to-purple-700 transition-colors duration-300 flex items-center">
<span id="generate-text">Gerar Imagem</span>
<span id="generating-spinner" class="hidden ml-2">
<svg class="animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</span>
</button>
</div>
</div>
</div>
<!-- Result Section (hidden initially) -->
<div id="result-section" class="max-w-3xl mx-auto mt-12 hidden" data-aos="fade-up">
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
<div class="p-8">
<div class="flex items-center mb-6">
<div class="flex items-center justify-center w-10 h-10 rounded-full bg-green-600 text-white font-bold mr-4">
<i data-feather="check" class="w-5 h-5"></i>
</div>
<h2 class="text-2xl font-semibold text-gray-800">Sua imagem está pronta!</h2>
</div>
<div class="result-card bg-gray-50 rounded-xl p-6 mb-8">
<div class="relative">
<img id="final-image" src="" alt="Imagem Final" class="w-full rounded-lg border border-gray-200">
<div id="final-text-overlay" class="absolute bottom-0 left-0 right-0 p-4 text-center text-white font-medium text-shadow" style="text-shadow: 1px 1px 3px rgba(0,0,0,0.8);"></div>
</div>
</div>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<button id="download-btn" class="px-6 py-3 bg-green-600 text-white rounded-lg font-medium hover:bg-green-700 transition-colors duration-300 flex items-center justify-center">
<i data-feather="download" class="w-4 h-4 mr-2"></i> Baixar Imagem
</button>
<button id="share-btn" class="px-6 py-3 bg-blue-600 text-white rounded-lg font-medium hover:bg-blue-700 transition-colors duration-300 flex items-center justify-center">
<i data-feather="share-2" class="w-4 h-4 mr-2"></i> Compartilhar
</button>
<button id="new-creation-btn" class="px-6 py-3 bg-indigo-600 text-white rounded-lg font-medium hover:bg-indigo-700 transition-colors duration-300 flex items-center justify-center">
<i data-feather="plus" class="w-4 h-4 mr-2"></i> Nova Criação
</button>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Initialize AOS and Feather Icons
AOS.init({
duration: 800,
once: true
});
feather.replace();
// DOM Elements
const photoUpload = document.getElementById('photo-upload');
const previewContainer = document.getElementById('preview-container');
const imagePreview = document.getElementById('image-preview');
const changePhotoBtn = document.getElementById('change-photo');
const nextStep1Btn = document.getElementById('next-step-1');
const step1 = document.getElementById('step-1');
const step2 = document.getElementById('step-2');
const step3 = document.getElementById('step-3');
const prevStep2Btn = document.getElementById('prev-step-2');
const nextStep2Btn = document.getElementById('next-step-2');
const prevStep3Btn = document.getElementById('prev-step-3');
const generateBtn = document.getElementById('generate-btn');
const generateText = document.getElementById('generate-text');
const generatingSpinner = document.getElementById('generating-spinner');
const resultSection = document.getElementById('result-section');
const finalImage = document.getElementById('final-image');
const finalTextOverlay = document.getElementById('final-text-overlay');
const downloadBtn = document.getElementById('download-btn');
const shareBtn = document.getElementById('share-btn');
const newCreationBtn = document.getElementById('new-creation-btn');
const customText = document.getElementById('custom-text');
// Variables to store user selections
let uploadedImage = null;
let selectedStyle = null;
// Event Listeners
photoUpload.addEventListener('change', function(e) {
if (e.target.files && e.target.files[0]) {
const reader = new FileReader();
reader.onload = function(event) {
imagePreview.src = event.target.result;
previewContainer.classList.remove('hidden');
uploadedImage = event.target.result;
nextStep1Btn.disabled = false;
};
reader.readAsDataURL(e.target.files[0]);
}
});
changePhotoBtn.addEventListener('click', function() {
photoUpload.value = '';
previewContainer.classList.add('hidden');
nextStep1Btn.disabled = true;
uploadedImage = null;
});
nextStep1Btn.addEventListener('click', function() {
step1.classList.add('hidden');
step2.classList.remove('hidden');
window.scrollTo({ top: 0, behavior: 'smooth' });
});
document.querySelectorAll('input[name="style"]').forEach(radio => {
radio.addEventListener('change', function() {
selectedStyle = this.value;
nextStep2Btn.disabled = false;
});
});
prevStep2Btn.addEventListener('click', function() {
step2.classList.add('hidden');
step1.classList.remove('hidden');
window.scrollTo({ top: 0, behavior: 'smooth' });
});
nextStep2Btn.addEventListener('click', function() {
step2.classList.add('hidden');
step3.classList.remove('hidden');
window.scrollTo({ top: 0, behavior: 'smooth' });
});
prevStep3Btn.addEventListener('click', function() {
step3.classList.add('hidden');
step2.classList.remove('hidden');
window.scrollTo({ top: 0, behavior: 'smooth' });
});
generateBtn.addEventListener('click', function() {
// Simulate processing
generateText.classList.add('hidden');
generatingSpinner.classList.remove('hidden');
generateBtn.disabled = true;
// In a real app, this would call an API to process the image
setTimeout(() => {
// For demo purposes, we'll just use the uploaded image with some text
finalImage.src = uploadedImage;
finalTextOverlay.textContent = customText.value || '';
// Show result
step3.classList.add('hidden');
resultSection.classList.remove('hidden');
generateText.classList.remove('hidden');
generatingSpinner.classList.add('hidden');
generateBtn.disabled = false;
window.scrollTo({ top: 0, behavior: 'smooth' });
}, 2000);
});
downloadBtn.addEventListener('click', function() {
// In a real app, this would download the processed image
alert('Download iniciado! (simulação)');
});
shareBtn.addEventListener('click', function() {
// In a real app, this would implement sharing functionality
alert('Compartilhando... (simulação)');
});
newCreationBtn.addEventListener('click', function() {
// Reset the flow
photoUpload.value = '';
previewContainer.classList.add('hidden');
nextStep1Btn.disabled = true;
uploadedImage = null;
document.querySelector('input[name="style"]:checked')?.checked = false;
selectedStyle = null;
nextStep2Btn.disabled = true;
customText.value = '';
document.getElementById('add-watermark').checked = false;
resultSection.classList.add('hidden');
step1.classList.remove('hidden');
window.scrollTo({ top: 0, behavior: 'smooth' });
});
// Character counter for text input
customText.addEventListener('input', function() {
const maxLength = 120;
const currentLength = this.value.length;
if (currentLength > maxLength) {
this.value = this.value.substring(0, maxLength);
}
});
});
</script>
</body>
</html>