En este blog post, exploraremos cómo crear un Generador de Imágenes con IA usando HTML, CSS, y JavaScript. Este proyecto es una excelente manera de entender cómo integrar APIs de IA en aplicaciones web para generar imágenes a partir de descripciones de texto.
Video Explicativo del Sistema
Estructura HTML (index.html)
El archivo index.html
establece la estructura básica de nuestra aplicación web. Usamos elementos estándar de HTML5 para crear una interfaz de usuario que incluye un formulario para ingresar el texto descriptivo y seleccionar la cantidad de imágenes a generar.
- Sección Generador de Imágenes: Un formulario (
<form>
) captura la entrada del usuario, incluyendo la descripción de la imagen deseada y la cantidad de imágenes a generar. Este formulario utiliza Bootstrap para un diseño responsivo y estéticamente agradable. - Sección Galería de Imágenes: Muestra las imágenes generadas como resultado. Inicialmente, se pueden mostrar imágenes de ejemplo para ilustrar cómo se verán las imágenes generadas.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generador de Imágenes IA con HTML, CSS y JavaScript</title>
<link rel="stylesheet" href="style.css">
<!-- Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/5.1.0/css/bootstrap.min.css" rel="stylesheet">
<link rel="shortcut icon" href="./images/faviconconfiguroweb.png" type="image/x-icon">
<script src="script.js" defer></script>
</head>
<body>
<section class="image-generator py-5">
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-8 text-center">
<div class="content">
<h1>Herramienta Generadora de Imágenes IA con JavaScript</h1>
<p>Convierte tu texto en una imagen en segundos utilizando esta herramienta de generación de imágenes con IA y JavaScript.</p>
<form action="#" class="generate-form d-flex flex-column flex-md-row justify-content-center align-items-center">
<input class="prompt-input form-control" type="text" placeholder="Describe lo que quieres ver" required>
<div class="controls d-flex align-items-center">
<select class="img-quantity form-select mx-2">
<option value="1" selected>1 Imagen</option>
<option value="2">2 Imágenes</option>
<option value="3">3 Imágenes</option>
</select>
<button type="submit" class="generate-btn btn btn-primary">Generar</button>
</div>
</form>
</div>
</div>
</div>
</div>
</section>
<section class="image-gallery py-5">
<div class="container">
<div class="row g-3">
<!-- Asegúrate de tener solo tres .img-card para la demostración -->
<div class="col-12 col-md-4">
<div class="img-card"><img src="images/img-1.jpg" alt="imagen" class="img-fluid"></div>
</div>
<div class="col-12 col-md-4">
<div class="img-card"><img src="images/img-2.jpg" alt="imagen" class="img-fluid"></div>
</div>
<div class="col-12 col-md-4">
<div class="img-card"><img src="images/img-3.jpg" alt="imagen" class="img-fluid"></div>
</div>
</div>
</div>
</section>
</body>
</html>
Estilos CSS (style.css)
Los estilos CSS aseguran que nuestra aplicación no solo sea funcional sino también visualmente atractiva. Utilizamos el framework Bootstrap para aprovechar sus componentes responsivos y añadimos nuestros propios estilos personalizados para mejorar la apariencia de nuestra herramienta:
- Estilos Generales: Configuramos estilos globales para el cuerpo del documento y elementos comunes como el formulario y las tarjetas de imagen.
- Responsividad: Mediante media queries, aseguramos que nuestra herramienta sea accesible y se vea bien en dispositivos de diferentes tamaños.
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
background-color: #f8f9fa;
}
.image-generator {
background: linear-gradient(135deg, #9d50bb, #6e48aa);
color: #fff;
}
.content {
padding: 2rem;
background-color: #fc7d1c;
}
.content h1, .content p {
margin-bottom: 1rem;
}
.generate-form, .image-gallery {
padding: 1rem;
}
.generate-form .generate-btn {
background-color: #007bff;
border: none;
margin-top: 0.5rem;
}
.generate-form .prompt-input, .generate-form .img-quantity {
border: 1px solid #ced4da;
margin: 0.5rem 0;
}
.generate-form .controls {
flex-wrap: wrap;
}
.img-card {
position: relative; /* Establece referencia para la posición absoluta del icono de descarga */
border: 1px solid #dee2e6;
border-radius: 0.25rem;
overflow: hidden;
}
.img-card img {
width: 100%;
height: auto;
}
.img-card .download-btn {
position: absolute; /* Posicionamiento absoluto respecto al .img-card */
bottom: 10px; /* Ubicación desde el fondo del contenedor .img-card */
left: 10px; /* Ubicación desde la izquierda del contenedor .img-card */
width: 32px; /* Tamaño del icono */
height: 32px; /* Tamaño del icono */
display: flex; /* Centrar el ícono de la flecha dentro del botón */
align-items: center; /* Alineación vertical */
justify-content: center; /* Alineación horizontal */
background-color: rgba(0, 0, 0, 0.5); /* Fondo semitransparente para visibilidad */
border-radius: 50%; /* Hace el botón circular */
cursor: pointer; /* Cambia el cursor para indicar que es clickeable */
}
.img-card .download-btn img {
display: block; /* Asegura que la imagen del icono se muestre correctamente */
width: 50%; /* Tamaño del icono respecto al botón */
height: auto; /* Mantiene la proporción del icono */
}
@media (max-width: 768px) {
.image-gallery .row {
display: block;
}
.img-card {
margin-bottom: 1rem;
width: calc(100% - 20px);
margin-left: auto;
margin-right: auto;
}
}
@media (min-width: 992px) {
.image-gallery .row {
display: flex;
justify-content: space-between;
}
.img-card {
flex-basis: calc(33.333% - 10px);
margin: 5px;
}
}
.generate-form .prompt-input, .generate-form .img-quantity {
border: 1px solid #ced4da;
margin: 0.5rem 0;
padding: 0.75rem 1.25rem; /* Aumenta el padding para más visibilidad */
font-size: 1.1rem; /* Aumenta el tamaño de la fuente para mayor vistosidad */
width: auto; /* Asegura que el ancho sea el adecuado */
max-width: 100%; /* Asegura que no sobrepase el ancho de su contenedor */
}
/* Ajustes específicos para el prompt-input para hacerlo más ancho y destacado */
.generate-form .prompt-input {
flex-grow: 1; /* Permite que el input crezca para ocupar espacio disponible */
min-width: 0; /* Para flexbox en IE11 */
}
@media (max-width: 768px) {
/* Resto de los media queries... */
.generate-form {
flex-direction: column;
}
.generate-form .prompt-input {
width: 90%; /* Hace el input más ancho en móviles */
margin-bottom: 1rem; /* Añade espacio debajo del input en móviles */
}
}
@media (min-width: 992px) {
/* Resto de los media queries... */
.generate-form {
flex-direction: row;
}
.generate-form .prompt-input {
margin-right: 1rem; /* Añade un pequeño margen a la derecha del input */
}
}
Lógica JavaScript (script.js)
El archivo script.js
contiene la lógica de nuestra aplicación. Se encarga de interactuar con la API de OpenAI para generar imágenes basadas en el texto proporcionado por el usuario. Aquí es donde la magia ocurre:
- Generación de Imágenes: Al enviar el formulario, se recoge la descripción del usuario y se realiza una petición POST a la API de OpenAI, enviando el texto y la cantidad de imágenes solicitadas.
- Actualización de la Galería de Imágenes: Una vez que recibimos las imágenes de la API, actualizamos la galería para mostrar las nuevas imágenes generadas.
const generateForm = document.querySelector(".generate-form");
const generateBtn = generateForm.querySelector(".generate-btn");
const imageGallery = document.querySelector(".image-gallery");
const OPENAI_API_KEY = "tu api"; // tu token acá
let isImageGenerating = false;
const updateImageCard = (imgDataArray) => {
if (!Array.isArray(imgDataArray)) {
console.error("imgDataArray is not an array:", imgDataArray);
return;
}
imgDataArray.forEach((imgObject, index) => {
const imgCard = imageGallery.querySelectorAll(".img-card")[index];
if (!imgCard) {
console.error("No se encontró ninguna tarjeta imgCard para el índice: ", index);
return;
}
const imgElement = imgCard.querySelector("img");
if (!imgElement) {
console.error("No se encontró ningún elemento img en imgCard: ", imgCard);
return;
}
// Utilizar la URL de la imagen directamente
imgElement.src = imgObject.url;
// Intentar encontrar el botón de descarga dentro de la tarjeta de imagen
const downloadBtn = imgCard.querySelector("a.download-btn");
if (downloadBtn) {
imgElement.onload = () => {
imgCard.classList.remove("loading");
downloadBtn.setAttribute("href", imgObject.url);
downloadBtn.setAttribute("download", `AI_Image_${new Date().getTime()}.png`); // Asumiendo que las imágenes son PNG
}
} else {
imgElement.onload = () => {
imgCard.classList.remove("loading");
}
}
});
}
const generateAiImages = async (userPrompt, userImgQuantity) => {
try {
const response = await fetch("https://api.openai.com/v1/images/generations", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${OPENAI_API_KEY}`,
},
body: JSON.stringify({
prompt: userPrompt,
n: userImgQuantity,
}),
});
if (!response.ok) throw new Error("Failed to generate AI images. Make sure your API key is valid.");
const { data } = await response.json();
// Asegurándose de que pasamos el arreglo correcto a updateImageCard
if (data && Array.isArray(data)) {
updateImageCard(data); // data es el arreglo que contiene las URLs de las imágenes
} else {
console.error("Unexpected response structure:", data);
}
} catch (error) {
alert(error.message);
} finally {
generateBtn.removeAttribute("disabled");
generateBtn.innerText = "Generate";
isImageGenerating = false;
}
}
const handleImageGeneration = (e) => {
e.preventDefault();
if(isImageGenerating) return;
// Get user input and image quantity values
const userPrompt = e.srcElement[0].value;
const userImgQuantity = parseInt(e.srcElement[1].value);
// Disable the generate button, update its text, and set the flag
generateBtn.setAttribute("disabled", true);
generateBtn.innerText = "Generating";
isImageGenerating = true;
// Creating HTML markup for image cards with loading state
const imgCardMarkup = Array.from({ length: userImgQuantity }, () =>
`<div class="img-card loading">
<img src="images/loader.svg" alt="AI generated image">
<a class="download-btn" href="#">
<img src="images/download.svg" alt="download icon">
</a>
</div>`
).join("");
imageGallery.innerHTML = imgCardMarkup;
generateAiImages(userPrompt, userImgQuantity);
}
generateForm.addEventListener("submit", handleImageGeneration);
Integración de la API de OpenAI
Para comunicarnos con la API de OpenAI, necesitamos:
- Clave API de OpenAI: Esencial para autenticar nuestras solicitudes. Se debe almacenar y utilizar de manera segura para evitar el abuso.
- Fetch API: Usamos JavaScript para realizar solicitudes HTTP a la API de OpenAI, manejar las respuestas y actualizar la interfaz de usuario acorde a los datos recibidos.
Repositorio del Generador de Imágenes con IA en Javascript
En el siguiente enlace puedes acceder al código, solo requieres generar el Token correspondiente y ya viene listo para que lo uses:
Conclusión
Crear una herramienta generadora de imágenes con IA es un proyecto fascinante que demuestra el poder de combinar tecnologías web con inteligencia artificial. Este tutorial proporciona una base sobre la cual puedes construir, personalizar y ampliar. Ya sea que estés interesado en aprender sobre integración de APIs, desarrollo web, o IA, este proyecto ofrece una oportunidad práctica para explorar estas áreas.
Recuerda, el código proporcionado es un punto de partida. Animo a experimentar con diferentes estilos, configuraciones de la API, y funcionalidades para crear una herramienta única que refleje tu creatividad y habilidades técnicas. ¡Feliz codificación!
Te recomiendo que pases por mi blog, tengo más de 150 aplicaciones que te podrían interesar. Cualquier duda también me puedes contactar a mi Whatsapp en el siguiente enlace: