Maison  >  Article  >  interface Web  >  Carrousel JavaScript réactif pour les données horaires de l'API

Carrousel JavaScript réactif pour les données horaires de l'API

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-10-21 14:42:30714parcourir

Responsive JavaScript Carousel for API Hourly Data

J'ai presque confondu une solution incomplète avec une solution terminée et j'ai continué à travailler sur d'autres parties de mon application météo ! En travaillant sur le carrousel qui était censé afficher 12 heures de météo, je voulais ajouter la fonctionnalité qui aiderait à récupérer les heures du lendemain au cas où la journée en cours serait terminée. Cependant, au lieu de passer au jour suivant, le carrousel revenait sans cesse au début des heures de la journée en cours et j'ai pensé à tort que la tâche était terminée. Ouais !

Défis initiaux

J'ai pensé à deux « boucles for » mais je ne pense pas que « j » imprimant tous ses éléments sur la longueur du « i » entier soit correct. J'ai trouvé de nombreux blogs en ligne sur l'utilisation de l'opérateur de module pour le "réseau circulaire". Mais je ne savais pas en quoi cela aiderait mon cas. Je devais parcourir les heures de la journée en cours, puis passer au jour suivant une fois les heures remises à zéro. Il se passait beaucoup de choses et je devais le rendre plus concis et tout placer dans une seule fonction. Difficile!

Reconnaître les solutions incomplètes et les erreurs

J'ai trouvé quelque chose de vraiment sympa en ligne, mais cela pourrait résoudre un gros problème pour moi. Cela m'a aidé à comprendre comment fonctionne l'opérateur de module pour les tableaux circulaires. Voici l'exemple sur le site :

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
// Function to cycle through the days of the week
function cycleDays(index) {
  return daysOfWeek[index % daysOfWeek.length];
}
// Let's cycle through the days:
for (let i = 0; i < 10; i++) {
  console.log(`Day ${i + 1}: ${cycleDays(i)}`);
}

Le résultat est comme :
Jour 1 : lundi
Jour 2 : mardi
...

Ce que je voulais, c'était qu'au lieu de revenir au tableau daysOfWeek et de commencer à partir de 'Monday', il devrait aller dans un tableau complètement différent. J'ai donc apporté le code à l'éditeur de code et je l'ai un peu modifié. Tout d’abord, j’ai créé une variable appelée ‘currentIndex’ et y ai stocké l’opération de module. Ensuite, je l'ai connecté à la console. Il s'est réinitialisé après 6 heures et est redevenu zéro.

Cependant, j'enregistrais la mauvaise variable sur la console. Parce que si j'écrivais la condition if comme ceci : if(currentIndex === 0), elle se déplacerait en fait vers un nouveau tableau juste au début de la boucle. Alors maintenant, j'ai enregistré "l'index" à la place, et j'ai finalement trouvé la réponse ! Afin de tester le nouveau code, j'ai créé un nouveau tableau pendant 'mois', puis j'ai essayé de faire le changement. Mais j'ai commis une autre erreur : laissez-moi vous montrer :

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
const months = [
  'Jan',
  'Feb',
  'March'
];
// Function to cycle through the days of the week
function cycleDays(index) {
  let currentIndex = index % daysOfWeek.length
  console.log(index)
 if(index === 7){
   return months[currentIndex]
 } else {
     return daysOfWeek[currentIndex];
 }
}
// Let's cycle through the days:
for (let i = 0; i < 10; i++) {
  console.log(`Day ${i + 1}: ${cycleDays(i)}`);
}

Après avoir enregistré "Jan", il est revenu au tableau d'origine. L'erreur était un contrôle d'égalité strict, j'aurais dû utiliser « supérieur ou égal à » à la place. Lorsque je l'ai branché, il est passé avec succès à la nouvelle baie !

Maintenant, je voulais que la boucle démarre à partir de l'heure en cours et continue sans s'arrêter, avec un marqueur en place pour basculer entre les tableaux. Ce marqueur sera l'opérateur de module au lieu de la longueur du tableau. Je pourrais également utiliser la longueur du tableau, qui dans ce cas est de 24, mais je m'en tiens à la valeur codée en dur de 24 pour l'instant.

currentIndex = (currentIndex 1) % 9

Cette ligne me permet de passer du premier au deuxième jour pendant la boucle sans l'arrêter. Voici un autre essai (j'ai mis à jour les tableaux pour qu'ils ressemblent aux résultats de l'API) :

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
// Function to cycle through the days of the week
function cycleDays(index) {
  return daysOfWeek[index % daysOfWeek.length];
}
// Let's cycle through the days:
for (let i = 0; i < 10; i++) {
  console.log(`Day ${i + 1}: ${cycleDays(i)}`);
}

Remarquez quelque chose d'intéressant dans les résultats :

l'index est 5 et lundi est six et i est 0
l'indice est 6 et lundi est sept et i est 1
l'indice est 7 et lundi est huit et je suis 2
l'index est 8 et lundi est neuf et je suis 3
l'index est 9 et lundi est dix et je suis 4
l'index est 0 et lundi est un et je suis 5
l'indice est 0 et mardi est 11
l'index est 1 et lundi est 12 et je suis 6
l'index est 2 et lundi est 13 et je suis 7
l'index est 3 et lundi est 14 et je suis 8
l'indice est 4 et lundi est 15 ¬ et i est 9

Le problème ici est que la boucle s'exécute une fois depuis le début, et lorsqu'elle atteint la condition (if(currentIndex === 0)), elle change de tableau. Cependant, lorsque currentIndex = 0 (c'est-à-dire 10 % 10 = 0), les hours[currentIndex] sont accessibles avant l'exécution de la condition if. C'est pourquoi vous voyez les valeurs de dayOne (comme "one") même après le changement.

Pour résoudre ce problème, la condition if doit être vérifiée juste après que currentIndex devienne 0, afin que le changement de tableau se produise avant la journalisation :

console.log(index est ${currentIndex} et lundi est ${hours[currentIndex]} et i est ${i})...

En modifiant la position de la condition, il est possible de garantir que le changement se produit au bon moment sans accéder au préalable au mauvais tableau.

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
const months = [
  'Jan',
  'Feb',
  'March'
];
// Function to cycle through the days of the week
function cycleDays(index) {
  let currentIndex = index % daysOfWeek.length
  console.log(index)
 if(index === 7){
   return months[currentIndex]
 } else {
     return daysOfWeek[currentIndex];
 }
}
// Let's cycle through the days:
for (let i = 0; i < 10; i++) {
  console.log(`Day ${i + 1}: ${cycleDays(i)}`);
}

Mon code est presque là. Ici, la seule erreur que je fais est d'enregistrer 'Lundi' au lieu de 'Mardi'. Les valeurs proviennent du tableau 'Tuesday', mais il continue de dire 'Monday' à cause d'une mauvaise façon d'écrire l'instruction console.log. Je suppose qu'il est assez difficile de mettre deux et deux ensemble et que la journalisation d'images VS la mise en place de valeurs dans des éléments HTML. Voici une petite amélioration en utilisant l'opérateur ternaire (oui, j'ai encore changé les éléments du tableau !) :

const dayOne = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten'];
const dayTwo = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
let hours = dayOne;
let currentHour = 5;
function cycleDays(currentHour) {
  let currentIndex = currentHour
  for (let i = 0; i < 10; i++) {
    console.log(`index is ${currentIndex} and dayOne is ${hours[currentIndex]}`)
    if(currentIndex === 0){
      hours = dayTwo
    console.log(`index is ${currentIndex} and dayTwo is ${hours[currentIndex]}`)
    } 
  currentIndex = (currentIndex + 1) % 9

} 
}
cycleDays(currentHour)

Enfin, je peux construire mon code pour les données de 3 jours que je récupère de l'API, voici la version raffinée :

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
// Function to cycle through the days of the week
function cycleDays(index) {
  return daysOfWeek[index % daysOfWeek.length];
}
// Let's cycle through the days:
for (let i = 0; i < 10; i++) {
  console.log(`Day ${i + 1}: ${cycleDays(i)}`);
}

Création d'éléments HTML dynamiques

Parlons de la génération des 12 divs. Je ne pouvais pas imaginer comment placer les boutons de chaque côté de la division parent alors que les 12 heures flottent entre eux. Si je devais générer les 12 divs dans le même parent que les boutons, alors les éléments du bouton auraient besoin d'un paramètre de justification différent de celui des 12 divs.

Il était logique de leur laisser leur propre conteneur. Il m'a fallu un certain temps pour comprendre cela – en fait, j'ai dû dormir dessus. Puis le lendemain, j'ai tapé .btn-container et j'ai appuyé sur l'onglet et à partir de là, tout a cliqué. J'avais vu chaque élément regroupé et leurs propres conteneurs à l'intérieur des conteneurs parents dans les tutoriels de John Smilga. Je ne savais pas pourquoi un tel regroupement serait nécessaire jusqu'à ce que je commence à concevoir le conteneur de 24 heures. C’était un véritable « moment de piège ».

Maintenant, un autre problème est apparu qui a persisté pendant des jours. Le curseur que j'ai conçu dans les didacticiels n'était pas aussi difficile que ces divs. Dans les didacticiels, il y avait une simple valeur de traduction, mais pour le moment, j'ai pas mal de problèmes. Sur des écrans plus petits, les divs se serraient les uns contre les autres et commençaient à ressembler à des spaghettis.

Et, lorsque j'ai utilisé une simple propriété TranslateX, c'est-à-dire lorsque j'ai « deviné » les pixels, il restait beaucoup d'espace après que les divs aient été complètement traduits vers la gauche. Cela signifiait qu'ils traduisaient plus que leur largeur combinée. J'avais besoin de trouver une valeur appropriée pour m'assurer que les divs s'arrêtaient exactement à la fin sans laisser cet espace supplémentaire. Après avoir longuement cherché, je suis tombé sur un blog proposant diverses solutions.

Il y avait beaucoup de solutions. Quelques-uns d'entre eux utilisaient l'opérateur modulo, ce qui m'a rappelé la logique de tableau circulaire que j'avais appliquée lors du changement de jour dans la « boucle for ». Il y avait beaucoup de commentaires ici qui utilisaient Math.min et Math.max. Ce qui, en gros, ferait traduire le conteneur jusqu'à ce que la fin de sa longueur soit atteinte. Excellent! Alors plus d'espace blanc ? Pas si vite...

Une chose qui différait de ces exemples était que mon conteneur afficherait initialement 3 ou 4 divs. Ainsi, lorsque le décalage est égal à 0, il existe déjà une certaine longueur dans le conteneur parent.

Ils montraient l'image en ajoutant le chiffre 1. Ainsi, leur carrousel faisait glisser 1 image vers l'avant en fonction du numéro d'index des images du tableau. Par exemple, s'il y a 10 images dans un conteneur et que nous en ajoutons une à la variable currentImage, la valeur calculée par Math.min sera '1'. Ensuite, lorsque nous ajoutons un autre « 1 », l'image actuelle sera 2 et la valeur sera 2 par Math.min car 2 mod 10 vaut 2. Cet exemple particulier changerait le jeu du curseur qui J'essaie de faire. C'est le code qui a attiré mon attention :

const daysOfWeek = [
  "Monday",
  "Tuesday",
  "Wednesday",
  "Thursday",
  "Friday",
  "Saturday",
  "Sunday",
];
// Function to cycle through the days of the week
function cycleDays(index) {
  return daysOfWeek[index % daysOfWeek.length];
}
// Let's cycle through the days:
for (let i = 0; i < 10; i++) {
  console.log(`Day ${i + 1}: ${cycleDays(i)}`);
}

Le génie derrière la solution de Richard Kichenama, trouvé dans les commentaires, réside dans l'utilisation de Math.max pour garantir que la valeur ne descende pas en dessous de 0 et de Math.min pour calculer la valeur de traduction jusqu'à ce qu'elle atteigne la longueur maximale du tableau d'images.

Maintenant, comment allais-je résoudre le problème de l’espace blanc ? J'ai dû prendre en compte les marges de tous les divs enfants et les additionner pour obtenir toute la longueur des divs enfants. Ensuite, le curseur devrait cesser de bouger une fois le dernier enfant atteint. Cela signifie que la largeur totale est la somme de toutes les largeurs des enfants plus leurs marges.

Cependant, j'ai rencontré un autre problème : certains divs étaient déjà affichés dans le conteneur, ce qui m'a laissé à nouveau bloqué. Heureusement, un de mes amis est venu à mon secours. Après avoir discuté du problème avec eux, voici ce que j'ai compris :

Je n'ai pas pu considérer toute la longueur des divs enfants. Il restait presque autant d’espace blanc que la longueur du conteneur. La solution consistait à soustraire la longueur du conteneur parent de la longueur totale des enfants (marges comprises). Cet ajustement a permis de résoudre le problème des espaces blancs – ouf !

Certains exemples de code avaient une variable qui ressemblait un peu à un « compteur ». Il agissait comme un « compteur » pour les propriétés de traduction. Lorsque cette variable augmente, la propriété de traduction augmente et ainsi de suite. J'ai séparé les propriétés Math.min et Math.max pour les boutons suivant et précédent. C'était plus utile et plus facile de cette façon.

Dans les exemples que j'ai référencés, le code utilisait la longueur du tableau pour déterminer la distance de glissement, mais, selon ma discussion précédente avec mon ami, je devais prendre en compte l'espace blanc, je dois donc soustraire la longueur de le conteneur. De cette façon, je me suis assuré que mes divs ne pouvaient se déplacer que d'un montant spécifique, évitant ainsi l'espace supplémentaire à la fin.

De plus, grâce aux tutoriels de John Smilga, j'ai appris à obtenir la largeur, la hauteur et les propriétés supérieures des éléments. Ce fut une lutte pour appliquer la bonne, mais aussi pour découvrir que certaines valeurs sont des chaînes et doivent être transformées en nombres. J'ai trouvé cela facilement sur Google et j'ai découvert 'parseFloat'.

Je suis également tombé sur une autre ressource utile qui m'a appris à afficher seulement trois divs pour les grands écrans et deux divs pour les petits écrans. L’astuce consistait à diviser 100 % de la largeur du conteneur par 3 (ou 2 pour les petits écrans) et à soustraire les marges. Cela permettait d'avoir des divs de taille égale qui s'intègrent parfaitement dans le conteneur (c'est tellement intelligent !). Enfin, pour découvrir la fonction finale, veuillez visiter mon GitHub. Voici le lien vers mon référentiel.

L'écouteur d'événements de fenêtre pour le redimensionnement a été crucial pour résoudre les problèmes d'alignement dans mon conteneur. Il a résolu le problème du « Flash of Unstyled Content » (FOUC) en réinitialisant le décalage lors du redimensionnement. Je dois remercier mon ami de m'avoir aidé à comprendre comment calculer maxOffset, cela a vraiment changé la donne.

Enfin, un merci à tous les développeurs expérimentés : chaque mot que vous partagez aide quelqu'un qui débute dans le domaine. Alors continuez à publier les informations de votre côté, car nous attendons de l’autre côté, impatients d’apprendre. Merci!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn