Comment créer une application météo en JavaScript

webapp Salut cher lecteur(euse) dans cet article, nous allons apprendre comment créer une application météo en utilisant JavaScript. Nous allons utiliser une API météo pour récupérer les données météorologiques en temps réel et afficher les résultats dans notre application web.

Mise en place du projet

Avant de commencer, assurez-vous d'avoir une connexion Internet pour accéder à l'API météo et d'avoir un éditeur de code installé sur votre machine. Vous pouvez utiliser n'importe quel éditeur de code de votre choix, comme Visual Studio Code.

Étape 1 : Structure de base HTML


<!DOCTYPE html>
<html lang="fr">
  <head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Weather App</title>
    <!-- Google Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;600&display=swap"
      rel="stylesheet"
    />
    <!-- Feuille de styles -->
    <style>
      /* Styles CSS ici */
    </style>
  </head>
  <body>
    <div class="wrapper">
      <div class="shape shape-1"></div>
      <div class="shape shape-2"></div>
      <div class="container">
        <div class="search-container">
          <input
            type="text"
            placeholder="Entrez le nom d'une ville"
            id="city"
            value="Dakar"
          />
          <button id="search-btn">Rechercher</button>
        </div>
        <div id="result"></div>
      </div>
    </div>
    <!-- Code JavaScript ici -->
    <script>
      // Code JavaScript ici
    </script>
  </body>
</html>

Étape 2 : Stylisons avec CSS

Maintenant, nous allons ajouter des styles CSS à notre application pour lui donner un aspect attrayant. Voici le code CSS à ajouter dans la balise <style></style> :

Double taper sur le code pour copier son contenu


* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
:root {
  --white: #ffffff;
  --off-white: #e5e5e5;
  --transp-white-1: rgba(255, 255, 255, 0.25);
  --transp-white-2: rgba(255, 255, 255, 0.1);
  --blue-1: #62b8f5;
  --blue-2: #4475ef;
  --shadow: rgba(3, 46, 87, 0.2);
}
body {
  height: 100vh;
  background: linear-gradient(135deg, var(--blue-1), var(--blue-2));
}
.wrapper {
  font-size: 16px;
  width: 90vw;
  max-width: 28em;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
}
.container {
  width: 100%;
  background: var(--transp-white-2);
  backdrop-filter: blur(10px);
  padding: 3em 1.8em;
  border: 2px solid var(--transp-white-2);
  border-radius: 0.6em;
  box-shadow: 0 1.8em 3.7em var(--shadow);
  text-align: center;
}
.shape {
  position: absolute;
  background-color: var(--transp-white-1);
  backdrop-filter: blur(1.2em);
  border: 2px solid var(--transp-white-2);
  border-radius: 50%;
}
.shape-1 {
  height: 13em;
  width: 13em;
  right: -6.5em;
  top: 1.8em;
}
.shape-2 {
  height: 11em;
  width: 11em;
  bottom: -3.7em;
  left: -2.5em;
}
.search-container {
  font-size: 1em;
  display: grid;
  grid-template-columns: 9fr 3fr;
  gap: 1.25em;
}
.search-container input,
.search-container button {
  outline: none;
  font-size: 1em;
  border: none;
}
.search-container input {
  padding: 0.7em;
  background-color: transparent;
  border-bottom: 2px solid var(--transp-white-1);
  color: var(--white);
  font-weight: 300;
}
.search-container input::placeholder {
  color: var(--off-white);
}
.search-container input:focus {
  border-color: var(--white);
}
.search-container button {
  color: var(--blue-2);
  background-color: var(--white);
  border-radius: 0.3em;
}
#result h2 {
  color: var(--white);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 600;
  margin: 1.25em 0;
}
.weather,
.desc {
  color: var(--off-white);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-size: 0.9em;
  font-weight: 500;
  line-height: 2em;
}
.weather {
  margin-top: -0.7em;
}
#result img {
  margin: 0.6em 0 0 0;
  width: 6.2em;
  filter: drop-shadow(0 1.8em 3.7em var(--shadow));
}
#result h1 {
  font-size: 4em;
  margin: 0.3em 0 0.7em 0;
  line-height: 0;
  font-weight: 400;
  color: var(--white);
}
.temp-container {
  display: flex;
  justify-content: center;
}
.temp-container div {
  padding: 0.3em 1em;
}
.temp-container div:first-child {
  border-right: 1px solid var(--transp-white-1);
}
.temp-container .title {
  font-weight: 600;
  color: var(--white);
}
.temp-container .temp {
  font-weight: 300;
  color: var(--off-white);
}
.msg {
  margin-top: 1.8em;
  color: var(--white);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
@media screen and (max-width: 450px) {
  .wrapper {
    font-size: 14px;
  }
      }

Étape 3 : Récupération des données météorologiques

Maintenant, nous allons écrire le code JavaScript qui va récupérer les données météorologiques à partir de l'API et les afficher dans notre application. Voici le code JavaScript à ajouter dans la balise <script></script> :

Double taper sur le code pour copier son contenu


let result = document.getElementById("result");
let searchBtn = document.getElementById("search-btn");
let cityRef = document.getElementById("city");

// Fonction pour récupérer les détails météorologiques à partir de l'API et les afficher
let getWeather = () => {
  let cityValue = cityRef.value;
  // Si le champ de saisie est vide
  if (cityValue.length == 0) {
    result.innerHTML = `<h3 class="msg">Veuillez entrer le nom d'une ville</h3>`;
  }
  // Si le champ de saisie n'est PAS vide
  else {
    let url = `https://codingweather.onrender.com/meteo/${cityValue}`;
    fetch(url)
      .then((resp) => resp.json())
      // Si le nom de la ville est valide
      .then((data) => {
        result.innerHTML = `
        <h2>${data.lieu.nom}</h2>
        <h4 class="weather">${data.meteo.principal}</h4>
        <h4 class="desc">Humidité : ${data.actuel.humidite}%</h4>
        <img src="${data.meteo.icone}">
        <h1>${data.actuel.temp_c} °</h1>
        <div class="temp-container">
            <div>
                <h4 class="title"><i class="fas fa-wind fa-inverse"></i> Vitesse du vent</h4>
                <h4 class="temp">${data.actuel.vitesse_vent_kph} km/h</h4>
            </div>
            <div>
                <h4 class="title"><i class="fas fa-sun fa-inverse"></i> Indice UV</h4>
                <h4 class="temp">${data.actuel.indice_uv}</h4>
            </div>
        </div>
        `;
      })
      // Si le nom de la ville n'est PAS valide
      .catch(() => {
        result.innerHTML = `<h3 class="msg">Ville non trouvée</h3>`;
      });
  }
};

searchBtn.addEventListener("click", getWeather);
window.addEventListener("load", getWeather);

Code complet

Double taper sur le code pour copier son contenu


<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Weather App</title>
    <!-- Google Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;600&display=swap"
      rel="stylesheet"
    />
    <!-- Stylesheet -->
    <style>* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}
:root {
  --white: #ffffff;
  --off-white: #e5e5e5;
  --transp-white-1: rgba(255, 255, 255, 0.25);
  --transp-white-2: rgba(255, 255, 255, 0.1);
  --blue-1: #62b8f5;
  --blue-2: #4475ef;
  --shadow: rgba(3, 46, 87, 0.2);
}
body {
  height: 100vh;
  background: linear-gradient(135deg, var(--blue-1), var(--blue-2));
}
.wrapper {
  font-size: 16px;
  width: 90vw;
  max-width: 28em;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
}
.container {
  width: 100%;
  background: var(--transp-white-2);
  backdrop-filter: blur(10px);
  padding: 3em 1.8em;
  border: 2px solid var(--transp-white-2);
  border-radius: 0.6em;
  box-shadow: 0 1.8em 3.7em var(--shadow);
  text-align: center;
}
.shape {
  position: absolute;
  background-color: var(--transp-white-1);
  backdrop-filter: blur(1.2em);
  border: 2px solid var(--transp-white-2);
  border-radius: 50%;
}
.shape-1 {
  height: 13em;
  width: 13em;
  right: -6.5em;
  top: 1.8em;
}
.shape-2 {
  height: 11em;
  width: 11em;
  bottom: -3.7em;
  left: -2.5em;
}
.search-container {
  font-size: 1em;
  display: grid;
  grid-template-columns: 9fr 3fr;
  gap: 1.25em;
}
.search-container input,
.search-container button {
  outline: none;
  font-size: 1em;
  border: none;
}
.search-container input {
  padding: 0.7em;
  background-color: transparent;
  border-bottom: 2px solid var(--transp-white-1);
  color: var(--white);
  font-weight: 300;
}
.search-container input::placeholder {
  color: var(--off-white);
}
.search-container input:focus {
  border-color: var(--white);
}
.search-container button {
  color: var(--blue-2);
  background-color: var(--white);
  border-radius: 0.3em;
}
#result h2 {
  color: var(--white);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 600;
  margin: 1.25em 0;
}
.weather,
.desc {
  color: var(--off-white);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-size: 0.9em;
  font-weight: 500;
  line-height: 2em;
}
.weather {
  margin-top: -0.7em;
}
#result img {
  margin: 0.6em 0 0 0;
  width: 6.2em;
  filter: drop-shadow(0 1.8em 3.7em var(--shadow));
}
#result h1 {
  font-size: 4em;
  margin: 0.3em 0 0.7em 0;
  line-height: 0;
  font-weight: 400;
  color: var(--white);
}
.temp-container {
  display: flex;
  justify-content: center;
}
.temp-container div {
  padding: 0.3em 1em;
}
.temp-container div:first-child {
  border-right: 1px solid var(--transp-white-1);
}
.temp-container .title {
  font-weight: 600;
  color: var(--white);
}
.temp-container .temp {
  font-weight: 300;
  color: var(--off-white);
}
.msg {
  margin-top: 1.8em;
  color: var(--white);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
@media screen and (max-width: 450px) {
  .wrapper {
    font-size: 14px;
  }
      }</style>
  </head>
  <body>
    <div class="wrapper">
      <div class="shape shape-1"></div>
      <div class="shape shape-2"></div>
      <div class="container">
        <div class="search-container">
          <input
            type="text"
            placeholder="Entrer le nom d'une ville"
            id="city"
            value="Dakar"
          />
          <button id="search-btn">Cherchez</button>
        </div>
        <div id="result"></div>
      </div>
    </div>
    <!-- Script -->
    <script>let result = document.getElementById("result");
let searchBtn = document.getElementById("search-btn");
let cityRef = document.getElementById("city");

// Fonction pour récupérer les détails météorologiques à partir de l'API et les afficher
let getWeather = () => {
  let cityValue = cityRef.value;
  // Si le champ de saisie est vide
  if (cityValue.length == 0) {
    result.innerHTML = `<h3 class="msg">Veuillez entrer le nom d'une ville</h3>`;
  }
  // Si le champ de saisie n'est PAS vide
  else {
    let url = `https://codingweather.onrender.com/meteo/${cityValue}`;
    fetch(url)
      .then((resp) => resp.json())
      // Si le nom de la ville est valide
      .then((data) => {
        result.innerHTML = `
        <h2>${data.lieu.nom}</h2>
        <h4 class="weather">${data.meteo.principal}</h4>
        <h4 class="desc">Humidité : ${data.actuel.humidite}%</h4>
        <img src="${data.meteo.icone}">
        <h1>${data.actuel.temp_c} °</h1>
        <div class="temp-container">
            <div>
                <h4 class="title"><i class="fas fa-wind fa-inverse"></i> Vitesse du vent</h4>
                <h4 class="temp">${data.actuel.vitesse_vent_kph} km/h</h4>
            </div>
            <div>
                <h4 class="title"><i class="fas fa-sun fa-inverse"></i> Indice UV</h4>
                <h4 class="temp">${data.actuel.indice_uv}</h4>
            </div>
        </div>
        `;
      })
      // Si le nom de la ville n'est PAS valide
      .catch(() => {
        result.innerHTML = `<h3 class="msg">Ville non trouvée</h3>`;
      });
  }
};

searchBtn.addEventListener("click", getWeather);
window.addEventListener("load", getWeather);
</script>
  </body>
</html>
  • A+
  • A-