Desarrollo Divertido: Practica con HTML, CSS y JS Creando una App del Clima

Desarrollo Divertido: Practica con HTML, CSS y JS Creando una App del Clima

¡Bienvenido a este emocionante viaje donde aprenderemos a construir una aplicación web que te permitirá consultar la temperatura actual de cualquier ciudad del mundo! En este tutorial, nos sumergiremos en los fundamentos de HTML, CSS y JavaScript para crear una aplicación atractiva y funcional que aprovecha la API del clima de OpenWeatherMap.

Premisa:

Esta aplicación tiene como objetivo brindar una manera sencilla y rápida de consultar el clima en múltiples ciudades. Su diseño se enfoca en la usabilidad, ofreciendo a los usuarios la posibilidad de elegir una ciudad desde un menú desplegable o ingresar directamente el nombre. Una vez activado, al presionar el botón, la aplicación utiliza la API de OpenWeatherMap para obtener datos detallados, incluyendo temperatura, descripción del clima, sensación térmica, humedad, presión atmosférica y velocidad del viento

¿Qué vamos a aprender?

HTML (HyperText Markup Language): HTML es el lenguaje fundamental para la construcción de páginas web. Se encarga de definir la estructura y el contenido de una página mediante etiquetas. Estas etiquetas representan elementos como encabezados, párrafos, imágenes, enlaces y más. Utilizar HTML es como crear un esqueleto para tu página web, definiendo qué elementos contiene y cómo se organizan.

CSS (Cascading Style Sheets): CSS es un lenguaje que complementa a HTML y se utiliza para estilizar y diseñar páginas web. Permite definir la apariencia visual de los elementos HTML, como colores, fuentes, márgenes, tamaños y posicionamiento. Con CSS, puedes mejorar el aspecto estético y la presentación de tu sitio web, dando estilo y personalidad a la estructura creada con HTML.

JavaScript: JavaScript es un lenguaje de programación que agrega interactividad y dinamismo a las páginas web. A través de JavaScript, puedes realizar acciones como validar formularios, crear efectos visuales, modificar el contenido de la página en respuesta a eventos (como clics o desplazamientos) y comunicarte con servidores para obtener o enviar datos sin recargar la página. Es esencial para crear experiencias web interactivas y fluidas.

Estos tres lenguajes, cuando se combinan, permiten crear sitios web completos y funcionales, donde HTML define la estructura, CSS controla el diseño visual y JavaScript añade la interactividad. Comprender los fundamentos de cada uno te brinda la base necesaria para comenzar a construir y desarrollar proyectos web.

Tecnologías Utilizadas:

HTMLEl marcado HTML establece la estructura de la aplicación. HTML, o HyperText Markup Language, se utiliza para crear la estructura y el contenido de las páginas web. Es el lenguaje fundamental que describe la estructura básica de una página web, definiendo cómo se deben mostrar los elementos en un navegador web. Algunos usos específicos incluyen:

  1. Estructura del contenido: HTML define la estructura lógica y jerárquica de una página web. Permite organizar el contenido en secciones como encabezados, párrafos, listas, imágenes, enlaces y otros elementos.

  2. Semántica: Las etiquetas de HTML proporcionan un significado semántico al contenido, lo que ayuda a los motores de búsqueda y a otros dispositivos a entender la naturaleza del contenido y su relación con otras partes de la página.

  3. Compatibilidad y accesibilidad: HTML es el lenguaje estándar para la creación de páginas web y es interpretado por todos los navegadores modernos. Además, al utilizar etiquetas semánticas, se mejora la accesibilidad para usuarios con lectores de pantalla y otros dispositivos asistenciales.

  4. Integración con otros lenguajes: HTML se combina con CSS (Cascading Style Sheets) para aplicar estilos y con JavaScript para añadir interactividad y funcionalidad dinámica a las páginas web

El número exacto de etiquetas en HTML y HTML5 puede variar dependiendo de cómo se cuenten y si se consideran las etiquetas obsoletas o en desuso. En general, HTML5 introdujo varias etiquetas nuevas para brindar una mejor semántica y estructura al marcado web.

En HTML4, se contabilizaban alrededor de 100 elementos, incluyendo etiquetas de apertura y cierre, así como elementos obsoletos o poco utilizados.

HTML5 introdujo nuevas etiquetas semánticas como <header>, <footer>, <nav>, <article>, <section>, entre otras, que ayudan a estructurar el contenido web de manera más descriptiva. Además, se añadieron elementos multimedia como <video> y <audio>, formularios más avanzados con etiquetas como <input type="email"> y <input type="date">, y etiquetas para contenido incrustado como <canvas>.

En total, HTML5 introdujo alrededor de 40 etiquetas nuevas, lo que sumaría aproximadamente unas 140 etiquetas en total si se cuentan las etiquetas obsoletas y las nuevas introducidas en HTML5. Sin embargo, hay que tener en cuenta que este número puede variar dependiendo de cómo se clasifiquen las etiquetas, y algunas etiquetas pueden estar en desuso o no ser ampliamente soportadas por todos los navegadores.

Algunas de las Mas usadas son:

EtiquetaDescripción / FunciónAtributos y Propiedades
<html>Envuelve todo el contenido de la página.lang, manifest
<head>Contiene información sobre el documento. 
<title>Define el título de la página. 
<body>Contiene el contenido principal visible de la página.bgcolor, text, link, vlink, alink
<h1> – <h6>Encabezados de diferentes niveles. 
<p>Define un párrafo de texto. 
<span>Define una sección en línea en el documento. 
<br>Crea un salto de línea. 
<ul>Define una lista desordenada. 
<ol>Define una lista ordenada. 
<li>Elemento de la lista (tanto para listas ordenadas como desordenadas). 
<a>Crea un enlace a otra página o recurso.href, target, download
<img>Inserta una imagen en la página.src, alt, width, height
<div>Define una división o sección genérica en el documento.id, class, style
<header>Define la cabecera de una página o sección. 
<footer>Define el pie de página de una página o sección. 
<nav>Define una sección de navegación. 
<section>Define una sección en un documento. 
<article>Define un contenido independiente y autónomo. 
<aside>Define contenido relacionado con el contenido circundante. 
<audio>Inserta contenido de audio en la página.src, controls, autoplay, loop, preload
<video>Inserta contenido de video en la página.src, controls, autoplay, loop, preload
<iframe>Inserta un marco de página web.src, width, height, title, sandbox
<select>Crea un menú desplegable.size, multiple
<option>Define una opción en un menú desplegable.selected, value, disabled
<form>Define un formulario para la entrada de datos.action, method, enctype, target
<input>Crea campos de entrada en un formulario.type, name, value, placeholder, required
<textarea>Crea un área de texto de múltiples líneas en un formulario.name, rows, cols, maxlength, placeholder
<button>Crea un botón en un formulario.type, name, value, disabled

CSSLos estilos CSS aplicados garantizan una experiencia visual agradable y una interfaz de usuario amigable. Los colores, tamaños y distribución se ajustan a diferentes tamaños de pantalla, utilizando estilos responsivos para dispositivos móviles y de escritorio.

En CSS, las reglas son instrucciones que especifican el estilo visual o el formato de elementos HTML. Cada regla consta de un selector y un conjunto de propiedades y valores.

  1. Selector: Es una expresión que apunta a los elementos HTML a los que se les aplicarán los estilos. Los selectores pueden ser:

    • Universal: Se aplica a todos los elementos HTML y se representa por el símbolo «*».
    • Por tipo: Selecciona todos los elementos de un tipo específico, como <p>, <h1>, <div>.
    • Por clase: Selecciona elementos que tienen un atributo class específico. Se denota con un punto seguido del nombre de la clase (por ejemplo, .clase).
    • Por ID: Selecciona un elemento específico que tiene un atributo id único. Se denota con un «#» seguido del nombre del ID (por ejemplo, #identificador).
Fuente: https://3con14.biz/css/selectores/10-reglas-y-selectores.html

En el ejemplo, el documento CSS contiene 5 reglas. Los selectores de estas tres reglas serian *bodyh1,h2,h3,h4,h5,h6#contenedor y .cuaIindice1 respectivamente.

Cada regla define un bloque de declaración propio. En la primera regla el selector es el selector universal * y el bloque de declaración es todo lo comprendido entre las llaves, incluidas éstas.

El bloque de declaración del selector de tipo body tiene 5 pares propiedad/valor separados por punto y coma. Como el punto y coma sólo es requerido para separar pares, el punto y coma final no es necesario, pero es legal y se suele poner.

El bloque de declaración del selector de clase .cuaIndice1 (comienza por un punto .) y tiene 5 pares propiedad/valor separados por un punto y coma.

El bloque de declaración del selector de id #contenedor (comienza por #) y tiene 4 pares propiedad/valor separados por un punto y coma.

Mayores usos

 
PropiedadDescripciónAtributos y ValoresElementos Asociados
colorColor del textoNombre del color (#ff0000), rgb(255, 0, 0), rgba(255, 0, 0, 0.5)Todas las etiquetas HTML
font-familyTipo de fuenteNombre de la fuente (Arial, Helvetica, sans-serif)Todas las etiquetas HTML
font-sizeTamaño de la fuenteTamaño en píxeles (16px), em, remTodas las etiquetas HTML
font-weightGrosor de la fuenteNormal, bold, bolder, lighter, number (400)Todas las etiquetas HTML
text-alignAlineación del textoleft, right, center, justifyTodas las etiquetas HTML
text-decorationDecoración del textonone, underline, overline, line-throughTodas las etiquetas HTML
background-colorColor de fondo del elementoNombre del color (#0000ff), rgb(0, 0, 255), rgba(0, 0, 255, 0.5)Todas las etiquetas HTML
background-imageImagen de fondo del elementoURL de la imagen (url(‘imagen.jpg’))Todas las etiquetas HTML
marginMargen externo del elementoTamaño en píxeles o porcentajes (10px, 5%)Todas las etiquetas HTML
paddingRelleno interno del elementoTamaño en píxeles o porcentajes (10px, 5%)Todas las etiquetas HTML
borderEstilo del borde del elementoGrosor, estilo, color (1px solid black)Todas las etiquetas HTML
displayControla cómo se muestra el elementoblock, inline, inline-block, noneTodas las etiquetas HTML
positionPosición del elemento en la páginastatic, relative, absolute, fixedTodas las etiquetas HTML
widthAncho del elementoTamaño en píxeles o porcentajes (100px, 50%)Todas las etiquetas HTML
heightAlto del elementoTamaño en píxeles o porcentajes (100px, 50%)Todas las etiquetas HTML
font-familyTipo de fuenteNombre de la fuente (Arial, Helvetica, sans-serif)Todas las etiquetas HTML
divDefine una división o sección genérica en el documentoid, class, style<div>
tableDefine una tablaborder, cellpadding, cellspacing<table>
background-colorColor de fondo del elementoNombre del color (#0000ff), rgb(0, 0, 255), rgba(0, 0, 255, 0.5)Todas las etiquetas HTML
background-imageImagen de fondo del elementoURL de la imagen (url(‘imagen.jpg’))Todas las etiquetas HTML
text-decorationDecoración del textonone, underline, overline, line-throughTodas las etiquetas HTML
marginMargen externo del elementoTamaño en píxeles o porcentajes (10px, 5%)Todas las etiquetas HTML
paddingRelleno interno del elementoTamaño en píxeles o porcentajes (10px, 5%)Todas las etiquetas HTML
borderEstilo del borde del elementoGrosor, estilo, color (1px solid black)Todas las etiquetas HTML
displayControla cómo se muestra el elementoblock, inline, inline-block, noneTodas las etiquetas HTML
positionPosición del elemento en la páginastatic, relative, absolute, fixedTodas las etiquetas HTML
widthAncho del elementoTamaño en píxeles o porcentajes (100px, 50%)Todas las etiquetas HTML
heightAlto del elementoTamaño en píxeles o porcentajes (100px, 50%)Todas las etiquetas HTML
floatPosicionamiento flotanteleft, right, noneTodas las etiquetas HTML
clearControl de saltos de línealeft, right, both, noneTodas las etiquetas HTML
overflowControl del desbordamiento del contenidovisible, hidden, scroll, autoTodas las etiquetas HTML
text-transformTransformación del textocapitalize, uppercase, lowercase, noneTodas las etiquetas HTML
list-style-typeTipo de viñeta de la listadisc, circle, square, decimal<ul>, <ol>
table-layoutAlgoritmo de diseño de la tablaauto, fixed<table>
border-collapseColapso de bordes de la tablacollapse, separate<table>
caption-sidePosición de la leyenda de la tablatop, bottom<table>
text-shadowSombra del textooffset-x, offset-y, blur-radius, colorTodas las etiquetas HTML
box-shadowSombra del elementoinset, offset-x, offset-y, blur-radius, spread-radius, colorTodas las etiquetas HTML
border-radiusRadio del borde del elementolongitud (px), porcentaje (%)Todas las etiquetas HTML
opacityOpacidad del elemento0 (transparente) a 1 (opaco)Todas las etiquetas HTML
transformTransformación 2D o 3D del elementotranslate, rotate, scale, skew, matrixTodas las etiquetas HTML
transitionTransición de propiedades del elementopropiedad, duración, función, retardoTodas las etiquetas HTML
animationAnimación del elementonombre, duración, función, retardo, iteraciónTodas las etiquetas HTML
filterEfectos visuales y filtros en el elementoblur(), brightness(), contrast(), grayscale(), hue-rotate(), invert(), opacity(), saturate(), sepia()Todas las etiquetas HTML
flex-directionDirección de los elementos en un contenedor flexrow, row-reverse, column, column-reverse<div> con display: flex
flex-wrapEnvoltura de elementos en un contenedor flexnowrap, wrap, wrap-reverse<div> con display: flex
justify-contentAlineación de elementos a lo largo del eje principal en un contenedor flexflex-start, flex-end, center, space-between, space-around, space-evenly<div> con display: flex
align-itemsAlineación de elementos a lo largo del eje secundario en un contenedor flexstretch, flex-start, flex-end, center, baseline<div> con display: flex
align-selfAlineación de un elemento específico en un contenedor flexauto, stretch, flex-start, flex-end, center, baseline<div> con display: flex
grid-template-columnsEspecifica las columnas de una cuadrícula CSSTamaños de columna (px, %, fr), auto<div> con display: grid
grid-template-rowsEspecifica las filas de una cuadrícula CSSTamaños de fila (px, %, fr), auto<div> con display: grid
grid-gapEspecifica el espacio entre las celdas de una cuadrícula CSSTamaño de espacio (px, %)<div> con display: grid
grid-columnDefine la ubicación de un elemento dentro de una cuadrícula CSSinicio / fin<div> con display: grid
grid-rowDefine la ubicación de un elemento dentro de una cuadrícula CSSinicio / fin<div> con display: grid
column-countNúmero de columnas en una disposición de varias columnasNúmero de columnasTodas las etiquetas HTML
column-gapEspecifica el espacio entre las columnasTamaño de espacio (px, %)Todas las etiquetas HTML
column-widthAncho mínimo para una columnaTamaño de ancho (px, %)Todas las etiquetas HTML
column-ruleAncho, estilo y color de la línea entre columnasAncho, estilo, colorTodas las etiquetas HTML
shape-outsideEspecifica una forma para envolver el contenido alrededor de un elemento flotantenone, circle(), ellipse(), polygon()Todas las etiquetas HTML
scroll-behaviorComportamiento de desplazamiento suaveauto, smoothTodas las etiquetas HTML
backdrop-filterEfectos visuales detrás del elemento, como desenfoque o atenuaciónblur(), brightness(), contrast(), grayscale(), hue-rotate(), invert(), opacity(), saturate(), sepia()Todas las etiquetas HTML
user-selectControla si el usuario puede seleccionar el contenido del elementoauto, none, text, contain, allTodas las etiquetas HTML
cursorEstilo del cursor del mousedefault, pointer, crosshair, move, text, wait, helpTodas las etiquetas HTML
contentGenera contenido en el elemento usando el método de CSS «content»Texto, imagen, contador, atribute::before, ::after
counter-incrementIncrementa el valor de un contador CSSnone, nombre del contadorTodas las etiquetas HTML
counter-resetEstablece el valor de un contador CSSnone, nombre del contadorTodas las etiquetas HTML
box-sizingDefine cómo se calcula el ancho y alto total de un elementocontent-box, border-boxTodas las etiquetas HTML
outlineEstablece un borde alrededor de un elemento sin ocupar espacio adicionalGrosor, estilo, colorTodas las etiquetas HTML
resizeControla si un elemento se puede redimensionar por el usuarionone, both, horizontal, verticalTodas las etiquetas HTML
object-fitControla cómo un elemento rellena su contenedorfill, contain, cover, none, scale-down<img>, <video>, <object>
object-positionEspecifica la posición de un objeto dentro de su contenedorleft top, center, right bottom, etc.<img>, <video>, <object>
pointer-eventsControla la interactividad del puntero del mouseauto, none, visiblePainted, visibleFill, visibleStrokeTodas las etiquetas HTML
unicode-bidiControla el flujo de texto en un elemento bidireccionalnormal, embed, bidi-overrideTodas las etiquetas HTML
word-wrapControla cómo se rompen las palabras cuando no caben en su contenedornormal, break-wordTodas las etiquetas HTML
text-overflowEspecifica cómo se muestra el texto que desborda su contenedorclip, ellipsisTodas las etiquetas HTML
white-spaceEspecifica cómo se maneja el espacio en blanco dentro de un elementonormal, nowrap, pre, pre-line, pre-wrapTodas las etiquetas HTML
will-changeInforma al navegador de cambios en la propiedad esperados por el scriptauto, scroll-position, contents, transform, opacity, etc.Todas las etiquetas HTML
backface-visibilityControla si la parte posterior de un elemento es visible cuando se giravisible, hiddenTodas las etiquetas HTML
scroll-snap-typeControla el comportamiento de desplazamiento de un contenedor y sus hijosnone, mandatory, proximityTodas las etiquetas HTML
scroll-snap-alignEspecifica cómo se alinean los elementos dentro de un contenedor de desplazamientonone, start, end, centerTodas las etiquetas HTML
scroll-paddingDefine el espacio entre el contenido y los bordes de un contenedor de desplazamientolongitud (px, %)Todas las etiquetas HTML
scroll-behaviorControla si un contenedor de desplazamiento utiliza un desplazamiento suaveauto, smoothTodas las etiquetas HTML
scroll-marginEstablece el margen del área de desplazamientolongitud (px, %)Todas las etiquetas HTML

JavaScriptEl código JavaScript maneja la funcionalidad de la aplicación. Al recibir la selección del usuario, hace solicitudes a la API de OpenWeatherMap, procesa los datos y actualiza dinámicamente la información mostrada en la interfaz de usuario.

  1. Lenguaje de programación: JavaScript es un lenguaje de programación de alto nivel, interpretado por los navegadores web. Permite la creación de contenido interactivo y dinámico en páginas web.

  2. Cliente y servidor: Es un lenguaje de programación del lado del cliente, lo que significa que se ejecuta en el navegador del usuario final, en lugar de en un servidor.

  3. Sintaxis: JavaScript tiene una sintaxis similar a otros lenguajes de programación como C++ o Java, pero tiene diferencias notables en su manejo de objetos y su tipado.

  4. Funciones: Las funciones son bloques de código reutilizables que pueden realizar tareas específicas. Pueden ser definidas y ejecutadas en cualquier momento.

  5. Variables: Se utilizan para almacenar datos. En JavaScript, las variables pueden contener varios tipos de datos como números, cadenas de texto, booleanos, objetos, etc.

  6. Condicionales y bucles: JavaScript utiliza estructuras de control como if, else, switch, for, while para ejecutar código en función de condiciones y para repetir tareas.

  7. DOM (Document Object Model): Permite a JavaScript interactuar con el contenido HTML y CSS de una página. Puede modificar, agregar o eliminar elementos y estilos.

 
ConceptoDescripciónUsos ComunesEjemplos de Propiedades
Lenguaje de programaciónJavaScript es un lenguaje de programación interpretado que se ejecuta en el navegador del cliente.Interactividad en páginas web, validaciones de formularios, animaciones, etc.console.log(), alert(), prompt()
SintaxisLa estructura y las reglas del lenguaje JavaScript.Definir variables, escribir funciones, condicionales, bucles, etc.var x = 5; function sum(a, b) { return a + b; }
VariablesContenedores para almacenar datos.Almacenar valores, manipulación de datos, control de flujo.let nombre = ‘Juan’; const PI = 3.1416;
FuncionesBloques de código reutilizables.Realizar tareas específicas, modularización de código.function sum(a, b) { return a + b; }
CondicionalesDecisiones basadas en condiciones.Control de flujo, ejecutar código según condiciones.if (condición) { // código }
BuclesEjecución repetida de código.Iterar sobre datos, realizar acciones múltiples.for (let i = 0; i < array.length; i++) { // código }
EventosAcciones del usuario o del sistema.Interactividad, respuesta a acciones del usuario.element.addEventListener(‘click’, function() { // código });
ObjetosEstructuras de datos complejas.Modelar entidades, agrupar propiedades y métodos.let persona = { nombre: ‘Ana’, edad: 25 };
ArraysColecciones ordenadas de elementos.Almacenar múltiples valores, operaciones con conjuntos de datos.let frutas = [‘manzana’, ‘naranja’, ‘plátano’];
Fetch APIRealizar solicitudes HTTP asíncronas.Obtener/recibir datos de servidores web.fetch(‘https://api.com/data’)
ES6+Actualizaciones del estándar de JavaScript.Uso de características modernas de JavaScript.const arrowFunction = () => { // código }
FuncionesBloques de código reutilizables.Realizar tareas específicas, modularización de código.function sum(a, b) { return a + b; }
Tipo de DatosDiferentes tipos de valores en JavaScript.Almacenamiento y manipulación de datos.string, number, boolean, array, object, null, undefined
VariablesContenedores para almacenar datos.Almacenar valores, manipulación de datos.let nombre = ‘Juan’; const PI = 3.1416;
Bucles/IteradoresEjecución repetida de código.Iterar sobre datos, realizar acciones múltiples.for, while, do…while, forEach()
ArraysColecciones ordenadas de elementos.Almacenar múltiples valores, operaciones con conjuntos de datos.let frutas = [‘manzana’, ‘naranja’, ‘plátano’];
ObjetosEstructuras de datos complejas.Modelar entidades, agrupar propiedades y métodos.let persona = { nombre: ‘Ana’, edad: 25 };
ColeccionesContenedores de datos.Almacenar múltiples valores, estructurar información.Map, Set, WeakMap, WeakSet
MatricesArreglos bidimensionales.Almacenamiento de datos en forma de tabla.let matriz = [[1, 2], [3, 4]];
ClasesPlantillas para la creación de objetos.Definición de estructuras y métodos.class Persona { constructor(nombre) { this.nombre = nombre; } }
EventosAcciones del usuario o del sistema.Interactividad, respuesta a acciones del usuario.element.addEventListener(‘click’, function() { // código });
DOMDocument Object Model.Manipulación de la estructura HTML/CSS de la página.document.getElementById(‘elemento’).innerHTML = ‘Nuevo texto’;
DOM ManipulationInteractuar con la estructura HTML/CSS de la página.Actualizar contenido, manipular estilos y elementos.document.getElementById(‘elemento’).innerHTML = ‘Nuevo texto’;
JSONJavaScript Object Notation.Formato de intercambio de datos.{ «nombre»: «Juan», «edad»: 30 }

APIs: ¿Qué son y por qué son importantes?

API significa Interfaz de Programación de Aplicaciones y actúa como un puente que permite que diferentes aplicaciones se comuniquen entre sí. En nuestro caso, la API del clima nos proporciona datos climáticos actualizados que podemos integrar en nuestra aplicación. ¿El beneficio? Accedemos a información precisa sin tener que almacenarla nosotros mismos.

¿Qué es la API del Clima de OpenWeatherMap?

OpenWeatherMap ofrece una API del clima que brinda acceso a datos meteorológicos detallados de prácticamente cualquier ubicación en el planeta. Puedes obtener información sobre la temperatura actual, la humedad, la velocidad del viento y más. En este tutorial, aprenderemos cómo consumir esta API utilizando JavaScript puro y cómo presentar estos datos de manera atractiva en nuestra aplicación web.

Paso 1: Configuración del Proyecto

Antes de sumergirnos en la codificación, necesitamos asegurarnos de tener una clave de API de OpenWeatherMap. Esta clave es esencial para autenticarnos y acceder a los datos climáticos proporcionados por la API. Aquí te dejo una guía paso a paso sobre cómo obtener tu propia clave:

1.2 Accede a la Sección de Claves de API

Dentro del panel de control, busca la sección que se llama «API keys» o «Claves de API».

  1. https://home.openweathermap.org/api_keys
  2. Al entrar veras los siguientes datos.
  3. Key, Name, Status, Actions, [Create key]

Si aún no tienes una clave, busca la opción para generar una nueva clave de API. Si ya tienes una, asegúrate de que esté activa y copia esa clave.

1.3 Copia tu Clave de API

Una vez que hayas generado o seleccionado una clave de API, cópiala. Esta clave es como una contraseña que utilizaremos en nuestro código para autenticarnos y acceder a la información del clima.
¡Listo! Ahora tienes tu clave de API de OpenWeatherMap, y estás listo para incorporarla en nuestro proyecto y comenzar a construir nuestra aplicación del clima. ¡Sigamos al siguiente paso del tutorial!

Paso 4: Codigo de la Estructura HTML


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Obtener Temperatura</title>

    <head>
        <!-- Otros elementos head -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
        <link rel="stylesheet" href="style.css">
    </head>
</head>

<body>
    <div class="container">

        <h1>Consulta el Clima</h1>

        <!-- Input para ingresar la ciudad -->
        <input type="text" id="inputCiudad" placeholder="Ingresa la ciudad">

        <select id="selectCiudades" onchange="actualizarCiudadSeleccionada()">
            <option value="">Selecciona una ciudad</option>

            <!-- Ciudades de América -->
            <optgroup label="América">
                <option value="New York">Nueva York, EE. UU.</option>
                <option value="Los Angeles">Los Ángeles, EE. UU.</option>
                <option value="Toronto">Toronto, Canadá</option>
                <option value="São Paulo">São Paulo, Brasil</option>
                <!-- Agregar más ciudades de América aquí -->
            </optgroup>

            <!-- Ciudades de Europa -->
            <optgroup label="Europa">
                <option value="London">Londres, Reino Unido</option>
                <option value="Paris">París, Francia</option>
                <option value="Berlin">Berlín, Alemania</option>
                <option value="Rome">Roma, Italia</option>
                <!-- Agregar más ciudades de Europa aquí -->
            </optgroup>

            <!-- Ciudades de Asia -->
            <optgroup label="Asia">
                <option value="Tokyo">Tokio, Japón</option>
                <option value="Shanghai">Shanghái, China</option>
                <option value="Seoul">Seúl, Corea del Sur</option>
                <option value="Mumbai">Bombay (Mumbai), India</option>
                <!-- Agregar más ciudades de Asia aquí -->
            </optgroup>

            <!-- Ciudades de África -->
            <optgroup label="África">
                <option value="Cairo">El Cairo, Egipto</option>
                <option value="Nairobi">Nairobi, Kenia</option>
                <option value="Johannesburg">Johannesburgo, Sudáfrica</option>
                <option value="Casablanca">Casablanca, Marruecos</option>
                <!-- Agregar más ciudades de África aquí -->
            </optgroup>

            <!-- Ciudades de Oceanía -->
            <optgroup label="Oceanía">
                <option value="Sydney">Sídney, Australia</option>
                <option value="Auckland">Auckland, Nueva Zelanda</option>
                <option value="Melbourne">Melbourne, Australia</option>
                <option value="Brisbane">Brisbane, Australia</option>
                <!-- Agregar más ciudades de Oceanía aquí -->

                <!-- Ciudades de Republica Dominicana -->
            <optgroup label="Región del Cibao">
                <option value="Santiago de los Caballeros">Santiago de los Caballeros</option>
                <option value="Santo Domingo">Santo Domingo Norte</option>
                <option value="Santo Domingo">Santo Domingo Oeste</option>
                <option value="Santo Domingo Este">Santo Domingo Este</option>
                <option value="San Francisco de Macorís">San Francisco de Macorís</option>
                <option value="La Vega">La Vega</option>
                <option value="San Cristóbal">San Cristóbal</option>
                <option value="Moca">Moca</option>
                <option value="Bonao">Bonao</option>
                <!-- Agregar más ciudades de Región del Cibao -->
            </optgroup>

            <optgroup label="Región del Sur">
                <option value="San Juan de la Maguana">San Juan de la Maguana</option>
                <option value="Barahona">Barahona</option>
                <option value="Azua">Azua</option>
                <option value="Bani">Baní</option>
                <option value="Pedernales">Pedernales</option>

                <!-- Agregar más ciudades de Región del Sur -->
            </optgroup>

            <optgroup label="Región del Este">
                <option value="Higüey">Higüey</option>
                <option value="La Romana">La Romana</option>
                <option value="San Pedro de Macorís">San Pedro de Macorís</option>
                <option value="Hato Mayor">Hato Mayor</option>
                <option value="El Seibo">El Seibo</option>
                <!-- Agregar más ciudades de Región del Este -->
            </optgroup>

            <optgroup label="Región del Norte">
                <option value="Puerto Plata">Puerto Plata</option>
                <option value="Samaná">Samaná</option>
                <option value="Nagua">Nagua</option>
                <option value="MonteCristi">Monte Cristi</option>
                <option value="Mao">Mao</option>
                <!-- Agregar más ciudades de Región del Norte-->
            </optgroup>

            <optgroup label="Región del Noroeste">
                <option value="Dajabón">Dajabón</option>
                <option value="Valverde">Valverde</option>
                <option value="Montecristi">Montecristi</option>
            </optgroup>
            <!-- Agregar más ciudades de Región del Noroeste -->

        </select>
        <!-- Botón para obtener la temperatura -->
        <button onclick="obtenerTemperatura()" id="botonVerClima">Ver Clima</button>



        <!-- Elemento para mostrar la información del clima -->
        <p id="infoClima"></p>

        <br> <!-- Salto de línea -->
        <!-- Párrafo con clase "js" que contiene iconos de JavaScript y código -->
        <p class="js">
            <i class="fab fa-js-square"></i> <!-- Icono de JavaScript -->
            Creado con JavaScript puro <!-- Texto indicando que fue creado con JavaScript puro -->
            <i class="fas fa-laptop-code"></i> <!-- Icono de laptop/code -->
        </p>



    </div>

    <script src="script.js"></script>
</body>

</html>


Paso 3: Estilos CSS

Añadimos estilos CSS para darle un aspecto agradable a nuestra aplicación:

/* … (Estilos CSS) … */

En el codigo, tenemos un archivo style.css, en el vamos a explicar todo lo que tenemos y como lo aplicamos para ver nuestra aplicacion con el estilo que tiene:

COFIGO CSS:

CODIGO COMPLETO DE CSS Y RESPONSIVE

body {
    background-image: radial-gradient(circle, #ffcc00, #ff6600);
    background-image: radial-gradient(circle, #66ffcc, #ff33cc);
    text-align: center;
    padding: 50px;
}

.container {
    width: 70%;
    margin: 0 auto;
    /* Centra el contenedor en la página */
    text-align: center;
}

/* Estilos para los elementos internos */
.h1,
#inputCiudad,
#botonVerClima,
#infoClima,
#selectCiudades {
    margin: 0 auto;
    padding-top: 40px;
    color: blue;
    font-size: 35px;
    font-weight: 700;
    text-align: center;
    /* Centra los elementos dentro del contenedor */
}


#inputCiudad {
    padding: 8px;
    margin: 20px;
    margin-bottom: 10px;
    text-align: center;
    color: rgb(255, 77, 0);
    font-weight: 700;
    font-size: 35px;
    width: 80%;
}



/* Estilos para el menú desplegable de ciudades */
#selectCiudades {
    padding: 8px;
    font-size: 16px;
    width: 50%;
    margin: 20px auto;
    border: 1px solid #ccc;
    border-radius: 5px;
    outline: none;
    text-align: center;
    color: green;
    background-color: #eeebdd;

}

/* Estilo para las etiquetas de grupo (continente) */
optgroup {
    font-weight: bold;
    color: #333;
    box-shadow: -5px 0 5px -2px rgba(216, 247, 13, 0.5), 5px 0 5px -2px rgba(216, 247, 13, 0.5); /* Sombreado en ambos lados */
  }
  

#botonVerClima {
    padding: 8px 20px;
    font-size: 20px;
    background-color: greenyellow;
    height: 50px;
    width: 50%;
    border-radius: 20px;

}


#infoClima {
    font-size: 25px;
    color: black;
    background-color: yellow;
    padding: 10px;
    margin-top: 20px;
    border-radius: 30px;
    box-shadow: 0 0 8px 4px yellow, 0 0 16px 8px black;
}


.additional-info {
    margin: 20px auto 20px; /* Margen superior e inferior y centrado horizontal */
    padding: 10px;
    background-color: #f7f7f7;
    border-radius: 25px;
    box-shadow: 0 2px 4px rgba(50, 100, 150, 0.5); /* Sombreado azul grisáceo */
    width: 90%;
  }
  
  

.additional-info h2 {
    color: #333;
    font-size: 18px;
    margin-bottom: 10px;
}

.additional-info ul {
    list-style: none;
    padding: 0;
}

.additional-info ul li {
    margin-bottom: 5px;
}

.fab,
.fas {
    font-size: 48px;
    color: #e9c32d;
    font-weight: 700;
}

.js {
    font-size: 30px;
    color: #04200b;
    font-weight: 700;
}

/* Media queries para diferentes tamaños de pantalla */

@media screen and (max-width: 768px) {

    /* Estilos para pantallas más pequeñas */
    .container {
        width: 100%;
    }

    h1 {
        font-size: 26px;
    }



    #inputCiudad {
        padding: 8px;
        margin: 20px auto;
        color: rgb(255, 77, 0);
        font-weight: 700;
        font-size: 30px;
        width: 80%;
        max-width: 400px;
        text-align: center;
    }


    #botonVerClima {
        padding: 8px 20px;
        font-size: 20px;
        background-color: greenyellow;
        height: 50px;
        width: 90%;
        border-radius: 25px;
    }


    #infoClima {
        font-size: 25px;
        color: black;
        background-color: yellow;
        padding: 10px;
        margin-top: 20px;
        width: 100%;
        max-width: 400px;
        text-align: center;
        border-radius: 25px;
    }

    /* Estilos para el menú desplegable de ciudades */
    #selectCiudades {
        padding: 8px;
        font-size: 16px;
        width: 70%;
        margin: 20px auto;
        border: 1px solid #ccc;
        border-radius: 5px;
        outline: none;
    }

    /* Estilo para las etiquetas de grupo (continente) */
    optgroup {
        font-weight: bold;
        color: #333;
        box-shadow: -5px 0 5px -2px rgba(216, 247, 13, 0.5), 5px 0 5px -2px rgba(216, 247, 13, 0.5); /* Sombreado en ambos lados */
      }
      

    .additional-info {
        margin: 20px auto 20px; /* Margen superior e inferior y centrado horizontal */
        padding: 10px;
        background-color: #f7f7f7;
        border-radius: 25px;
        box-shadow: 0 2px 4px rgba(50, 100, 150, 0.5); /* Sombreado azul grisáceo */
        width: 90%;
      }

    .additional-info h2 {
        color: #333;
        font-size: 18px;
        margin-bottom: 10px;
    }

    .additional-info ul {
        list-style: none;
        padding: 0;
    }

    .additional-info ul li {
        margin-bottom: 5px;
    }

    .fab,
    .fas {
        font-size: 35px;
        color: #e9c32d;
        font-weight: 700;
    }

    .js {
        font-size: 30px;
        color: #04200b;
        font-weight: 700;
    }
}

/* RELGA DE ESTILO PARA EL MOVIL max-width: 480px */

@media screen and (max-width: 480px) {
    .container {
        width: 100%;
    }

    h1 {
        font-size: 26px;
    }

    #inputCiudad {
        display: block;
        margin: 10px auto;
        font-size: 20px;
        width: 90%;
        max-width: 300px;
        text-align: center;
        border-radius: 25px;
    }

    #botonVerClima {
        font-size: 25px;
    }

    #infoClima {
        font-size: 18px;
        width: 100%;
    }

    /* Estilos para el menú desplegable de ciudades */
    #selectCiudades {
        padding: 8px;
        font-size: 25px;
        width: 100%;
        margin: 20px auto;
        border: 1px solid #ccc;
        border-radius: 25px;
        outline: none;
    }

    /* Estilo para las etiquetas de grupo (continente) */
    optgroup {
        font-weight: bold;
        color: #333;
        box-shadow: -5px 0 5px -2px rgba(216, 247, 13, 0.5), 5px 0 5px -2px rgba(216, 247, 13, 0.5); /* Sombreado en ambos lados */
      }
      
    .additional-info {
        margin: 20px auto 20px; /* Margen superior e inferior y centrado horizontal */
        padding: 10px;
        background-color: #f7f7f7;
        border-radius: 25px;
        box-shadow: 0 2px 4px rgba(50, 100, 150, 0.5); /* Sombreado azul grisáceo */
        width: 90%;
      }
    .additional-info h2 {
        color: #333;
        font-size: 18px;
        margin-bottom: 10px;
    }

    .additional-info ul {
        list-style: none;
        padding: 0;
    }

    .additional-info ul li {
        margin-bottom: 5px;
    }

    .fab,
    .fas {
        font-size: 35px;
        color: #e9c32d;
        font-weight: 700;
    }

    .js {
        font-size: 30px;
        color: #04200b;
        font-weight: 700;
    }
}

Paso 4: Lógica JavaScript

Ahora, implementamos la lógica en JavaScript para obtener la temperatura de la API del clima:


<script>
function obtenerTemperatura() {
    // Obtiene el valor del input o select con el ID 'inputCiudad' o 'selectCiudades'
    const ciudad = document.getElementById('inputCiudad').value || document.getElementById('selectCiudades').value;

    // Clave de la API para acceder a los datos climáticos
    const api_key = 'TU API KEY AQUI';

    // URL para hacer la solicitud a la API del clima usando la ciudad y la clave de la API
    const url = `https://api.openweathermap.org/data/2.5/weather?q=${ciudad}&appid=${api_key}&units=metric`;

    // Hace la solicitud a la API y procesa los datos recibidos
    fetch(url)
        .then(response => {
            // Verifica si la respuesta es correcta; de lo contrario, lanza un error
            if (!response.ok) {
                throw new Error('Error al obtener los datos del clima');
            }
            return response.json();
        })
        .then(data => {
            // Extrae los datos específicos del clima desde la respuesta JSON
            const temperature = data.main.temp;
            const weatherDescription = traducirDescripcion(data.weather[0].description);
            const feelsLike = data.main.feels_like;
            const humidity = data.main.humidity;
            const pressure = data.main.pressure;
            const windSpeed = data.wind.speed;
            const weatherIcon = data.weather[0].icon; // Supongamos que 'icon' contiene el identificador del clima

            // Mapeo de identificadores de clima a emojis
            const weatherIcons = {
                '01d': '☀️', // Soleado
                '02d': '⛅', // Parcialmente nublado
                '03d': '☁️', // Nublado
                '04d': '☁️', // Nublado
                // ... otros identificadores y emojis
            };

            // Obtiene el emoji correspondiente al clima o un emoji predeterminado si no hay un emoji definido
            const weatherEmoji = weatherIcons[weatherIcon] || '🌍';

            // Actualiza el contenido del elemento con el ID 'infoClima' con los datos climáticos
            const infoClima = document.getElementById('infoClima');
            infoClima.innerHTML = `
                <p>La temperatura actual en ${ciudad} es: <span style="color: black; font-size: 25px;">${temperature} grados Celsius</span></p>
                <div class="additional-info">
                    <h2 style="color: black; font-size: 30px;">Información adicional:</h2>
                    <ul>
                        <li><strong>Descripción:</strong> ${weatherDescription} ${weatherEmoji}</li>
                        <li><strong>Sensación térmica:</strong> ${feelsLike} grados Celsius</li>
                        <li><strong>Humedad:</strong> ${humidity}%</li>
                        <li><strong>Presión atmosférica:</strong> ${pressure} hPa</li>
                        <li><strong>Velocidad del viento:</strong> ${windSpeed} m/s</li>
                    </ul>
                </div>
            `;
        })
        .catch(error => {
            // En caso de error, muestra un mensaje de error en el elemento con el ID 'infoClima' y lo resalta en rojo
            console.error('Hubo un error:', error);
            const infoClima = document.getElementById('infoClima');
            infoClima.innerText = 'Hubo un error al obtener la información del clima';
            infoClima.style.backgroundColor = 'red';
        });
}

// Función para actualizar el valor del input 'inputCiudad' con la opción seleccionada en 'selectCiudades'
function actualizarCiudadSeleccionada() {
    const ciudadSeleccionada = document.getElementById('selectCiudades').value;
    document.getElementById('inputCiudad').value = ciudadSeleccionada;
}


function traducirDescripcion(description) {
    // Objeto con las traducciones del estado del clima
    const traducciones = {
        // Mapeo de estados del clima en inglés a traducciones en español
        // Puedes expandir esta lista agregando más traducciones según sea necesario
        'clear sky': 'Cielo Despejado',
        'few clouds': 'Pocas Nubes',
        'scattered clouds': 'Nubes Dispersas',
        'broken clouds': 'Nubes Rotas',
        'overcast clouds': 'Nublado',
        'shower rain': 'Lluvia',
        'rain': 'lluvia',
        'thunderstorm with light rain': 'Tormenta eléctrica con Lluvia ligera',
        'thunderstorm with rain': 'Tormenta eléctrica con Lluvia',
        'thunderstorm with heavy rain': 'Tormenta eléctrica con Lluvia intensa',
        'light thunderstorm': 'Tormenta Eléctrica Ligera',
        'thunderstorm': 'Tormenta Eléctrica',
        'heavy thunderstorm': 'Tormenta Eléctrica Fuerte',
        'ragged thunderstorm': 'Tormenta Eléctrica Irregular',
        'thunderstorm with light drizzle': 'Tormenta Eléctrica con Llovizna ligera',
        'thunderstorm with drizzle': 'tormenta eléctrica con llovizna',
        'thunderstorm with heavy drizzle': 'Tormenta Tléctrica con Llovizna intensa',
        'light intensity drizzle': 'Llovizna Ligera',
        'drizzle': 'Llovizna',
        'heavy intensity drizzle': 'Llovizna Intensa',
        'light intensity drizzle rain': 'Lluvia Iigera',
        'drizzle rain': 'lluvia',
        'heavy intensity drizzle rain': 'Lluvia Intensa',
        'shower rain and drizzle': 'Lluvia y Llovizna',
        'heavy shower rain and drizzle': 'Lluvia Intensa y Llovizna',
        'shower drizzle': 'Llovizna',
        'light rain': 'Lluvia Ligera',
        'moderate rain': 'Lluvia Moderada',
        'heavy intensity rain': 'Lluvia Intensa',
        'very heavy rain': 'Lluvia Muy Intensa',
        'extreme rain': 'Lluvia Extrema',
        'freezing rain': 'Lluvia Helada',
        'light intensity shower rain': 'Lluvia Ligera',
        'shower rain': 'lluvia',
        'heavy intensity shower rain': 'Lluvia Intensa',
        'ragged shower rain': 'Lluvia Irregular',
        'light snow': 'Nieve Ligera',
        'snow': 'Nieve',
        'heavy snow': 'Nieve Intensa',
        'sleet': 'Aguanieve',
        'light shower sleet': 'Llovizna de Aguanieve Ligera',
        'shower sleet': 'Lluvia de Aguanieve',
        'light rain and snow': 'Lluvia y Nieve Ligera',
        'rain and snow': 'lluvia y nieve',
        'light shower snow': 'Nevada Ligera',
        'shower snow': 'nevada',
        'heavy shower snow': 'Nevada Intensa',
        'mist': 'Niebla',
        'smoke': 'Humo',
        'haze': 'Neblina',
        'sand/ dust whirls': 'Remolinos de Arena/Polvo',
        'fog': 'Niebla',
        'sand': 'Arena',
        'dust': 'Polvo',
        'volcanic ash': 'Ceniza Volcánica',
        'squalls': 'Ráfagas',
        'tornado': 'Tornado',
        'clear sky': 'Cielo Despejado',
        'broken clouds': 'Nubes Rotas',
        'partly cloudy': 'Parcialmente Nublado',
        'cloudy': 'nublado',
        'overcast clouds': 'Nublado',
        // Puedes agregar más traducciones según sea necesario
    };

    // Retorna la traducción correspondiente del estado del clima o el estado original si no hay traducción
    return traducciones[description] || description;
}
        </script>

Paso 5: Obtener la Clave de API:

Expliquemos cada parte del código en detalle en los siguientes pasos del tutorial. Antes de ejecutar el código, necesitarás obtener tu propia clave de API de OpenWeatherMap. Esta clave te permite acceder a su información meteorológica. Reemplaza ‘TU API KEY’ con tu clave personalizada en la línea const api_key = ‘TU_API_KEY‘;.

Paso 6: Haciendo la Solicitud a la API:

En el código JavaScript, la URL de la API se construye combinando la ciudad ingresada por el usuario y la clave de API. Explica cómo se construye esta URL utilizando la plantilla de cadena (const url = ‘http://api.openweathermap.org/data/2.5/weather?q=${ciudad}&appid=${api_key}&units=metric‘;) y cómo se realiza la solicitud GET utilizando fetch.

Paso 7: Manejo de la Respuesta de la API:

Explica cómo se maneja la respuesta de la API una vez que se recibe. Mostrar cómo se verifica si la respuesta es exitosa (if (!response.ok) { throw new Error(‘Error al obtener los datos del clima’); }) y luego cómo se extrae la temperatura de la respuesta JSON (const temperature = data.main.temp;).

Paso 8: Mostrar la Información en la Interfaz de Usuario:

Describe cómo se actualiza dinámicamente el contenido HTML para mostrar la temperatura en la interfaz de usuario. Puedes mencionar cómo se utiliza getElementById para encontrar el lugar donde se mostrará la temperatura (const infoClima = document.getElementById(‘infoClima’);) y cómo se actualiza el contenido utilizando innerHTML (infoClima.innerHTML = ‘La temperatura actual en ${ciudad} es: <span style=»color: black; font-size: 25px;»>${temperature} grados Celsius</span>’;).

EXPLICACION:

body: Define los estilos para el cuerpo de la página. Establece un fondo con un gradiente radial que cambia de colores dependiendo del tamaño de la pantalla. Además, alinea el texto al centro y agrega un espacio de 50px alrededor del contenido.

.container: Establece estilos para un contenedor que envuelve el contenido principal. Le asigna un ancho del 70% de la pantalla y lo centra horizontalmente.

h1 y p: Definen el estilo para los encabezados y párrafos respectivamente. Cambian el color, el tamaño de fuente, el peso y el espaciado para que se vean atractivos y legibles.

#inputCiudad: Establece el estilo para un campo de entrada de texto. Define el tamaño de fuente, el espaciado, el color y la alineación.

#botonVerClima: Define el estilo para un botón que se utilizará para ver el clima. Ajusta el tamaño del texto y el color de fondo.

#infoClima: Establece el estilo para mostrar la información del clima. Define el tamaño de fuente, el color de texto y el color de fondo para destacar la información.

Luego, vienen las secciones de Media Queries que ajustan los estilos según el tamaño de la pantalla:

@media screen and (max-width: 768px): Aquí se aplican estilos específicos para pantallas más pequeñas, como tabletas. Reduce el tamaño del contenedor, los encabezados, el tamaño de fuente y hace ajustes en el botón y la información del clima.

@media screen and (max-width: 480px): Estos estilos son para pantallas aún más pequeñas, como teléfonos móviles. Reducen aún más el tamaño del contenedor, encabezados, tamaño de fuente y hacen que el campo de entrada de ciudad sea más flexible y el botón y la información del clima sean más grandes y legibles.

Veamos como ha quedado la App

Conclusión

Mis amigos, llegamos al final de este del camino, la creación de esta aplicación de clima con selección de ciudad ha sido un viaje emocionante a través del mundo de la programación web. Hemos explorado cómo combinar HTML para la estructura, CSS para el diseño visual y JavaScript para la interactividad, dando vida a una herramienta que proporciona información meteorológica detallada de diversas ubicaciones.

Este proyecto no solo nos ha permitido integrar conocimientos fundamentales de programación web, sino que también hemos trabajado con una API externa, en este caso, la API de OpenWeatherMap, para obtener datos en tiempo real y enriquecer nuestra aplicación.

Al permitir a los usuarios seleccionar ciudades, tanto a través de un menú desplegable como mediante la entrada directa en un input o caja de texto, hemos logrado crear una experiencia intuitiva y fácil de usar. Además, al implementar consejos SEO como la distribución de la frase clave y la optimización de imágenes, hemos mejorado la visibilidad y accesibilidad de nuestra aplicación.

Este proyecto es solo el comienzo. Con un conocimiento más profundo de HTML, CSS, JS y la integración de APIs, ahora tenemos la base para explorar y expandir aún más las capacidades de nuestras aplicaciones web. 

La API tiene muchas otras propiedades que puedes explorar, como agregar imágenes y mapas, y ver cómo nos indica el tiempo. Te reto a que puedas llevar a cabo tu propia investigación y déjame debajo los comentarios

¡Adelante, sigue explorando y creando!»

Comparte este Contenido en tus Redes Sociales

Deja un comentario