Javascript - Album photo reproduisant l'effet domino

In this French‑language tutorial, the presenter walks through building a dynamic photo‑album that displays images using a domino‑style wave transition. Starting from a simple HTML container, he creates a configurable number of div elements (default 20) that each show a slice of a background image. He explains how to calculate each div’s width, height, and background‑position so the slices reassemble the full picture. He then adds a per‑slice rotation using CSS 3D transforms (perspective and rotateY) and builds a recursive animation with setTimeout to animate the slices, toggling visibility to create a propagating wave effect. The tutorial covers cycling through multiple images, handling edge cases with try/catch when removing previously created divs, and fine‑tuning the animation speed and angle increments. Throughout, the instructor demonstrates live coding, debugging, and iterative refinement, ending with a working album that continuously cycles through five images with a smooth wave transition.
Chapters
Bonjour à tous et bienvenue dans cette nouvelle leçon de JavaScript. Aujourd'hui, nous allons mettre en pratique ce que nous avons appris jusqu'ici et nous allons essayer de créer un album photo dont les transitions reproduisent l'effet domino ou bien l'effet de vagues comme ceci. Alors commençons. Alors j'ai déjà préparé ce code. Dans la balise body, j'ai prévu une div, une identifiée par container et j'ai appliqué 2 styles. Bon, un style qui va s'appliquer sur le container, celui qui va contenir l'album, et une classe que je n'ai pas encore utilisée. Quand je me rends sur le navigateur, le résultat est le suivant. L'élément qui est encadré en noir, c'est la balise div identifiée par container. L'objectif maintenant, c'est de créer beaucoup de balises div à l'intérieur de celle-ci, de telle sorte à les animer indépendamment l'une de l'autre pour avoir l'effet vague souhaité. Alors pour commencer, nous allons prévoir ici un événement au chargement de la page. Donc window.onload égale à function, ça veut dire au chargement de la page, le traitement à faire est le suivant. Je vais d'abord initialiser quelques paramètres, par exemple je vais mettre nbr égale à 20 pour dire le nombre de divs, c'est-à-dire le nombre d'éléments que je vais intégrer pour constituer ma vague, c'est 20 éléments. Ensuite, je vais créer une variable qui va cibler l'objet container. Je vais l'appeler par exemple count, voilà, comme ça, égal document.getElementById container. Voilà, parce que j'aurai besoin par la suite d'utiliser cet objet. Bon, au lieu de répéter cette syntaxe entière, je vais tout simplement la mettre dans la variable count. Bien sûr, j'aurais peut-être besoin d'autres choses que je vais déclarer ici dans cette fonction, mais pour le moment, je vais appeler une autre fonction qui s'appelle init. Cette fonction, c'est elle qui va se charger de créer mes 20 divs au chargement de la page. Alors ici je vais mettre function init et voilà. Maintenant on va essayer de créer des éléments, par exemple un élément que j'appellerai div égale document.createElement. L'élément à créer c'est la balise div. La largeur de cette div sera la largeur du conteneur divisée par le nombre d'éléments. Ça veut dire, bon, alors je mettrai ici div .style.width égal à la largeur du conteneur, c'est-à-dire count.clientWidth divisé par le nombre d'éléments, à savoir nbr. Bon, je mettrai ça entre parenthèses et ensuite je vais concaténer avec px, ça veut dire l'unité. De la même manière, je vais spécifier la hauteur qui sera égale à la hauteur du conteneur. Alors là, je mettrai div.style.height égal à count.clientHeight concaténé avec l'unité px. Et pour pouvoir distinguer cette div, je vais la doter de la classe ma-classe. Donc je mettrai div.className égal ma-classe. Voilà, ensuite je vais ajouter cette div au conteneur. Bon, count .appendChild div. Maintenant j'exécute. Alors j'ai bien la div qui a été créée. Bien sûr, moi j'ai besoin de 20 divs, alors il suffit de boucler sur ce traitement. Je vais mettre donc for i= 0, i inférieur strictement à nbr et plus plus. Bon, je mettrai des accolades ici. Et voilà, donc maintenant quand j'actualise, alors j'ai 20 divs qui ont été créés. Bien sûr, remarquez qu'il y a une div qui a débordé, c'est normal, bon, parce que j'ai appliqué une bordure et du coup donc ça a élargi davantage la div. Bon, il suffit d'enlever la bordure. Alors maintenant je n'en ai plus besoin, c'est-à-dire que je peux éliminer ce style. J'actualise. Bon, maintenant mes 20 divs sont bien ici à l'intérieur, mais je veux pas les voir. Bon, ce que je vais faire maintenant, c'est leur appliquer une image d'arrière-plan. Bon, tout d'abord on va voir quelles sont les images que je vais charger dans mon album. Je les ai stockées dans le dossier qui s'appelle images. Bon, je dispose de 5 images nommées ainsi: chat.jpg, chien.jpg, ibis.jpg, phare et romarin. Elles ont toutes l'extension .jpg. Bon, tout d'abord je vais déclarer ces images dans un tableau. Bon, c'est un travail à faire, par exemple ici dans cette fonction images égale, moi directement je mettrai des crochets, je mettrai les chemins. Donc images slash, bon, la première image s'appelle chat.jpg, deuxième image c'est chien.jpg. Troisième image, c'est ibis.jpg. La quatrième, c'est phare.jpg. Et la dernière, c'est rond-marin.jpg. Maintenant, mes images, elles ont été créées. Bon, ce que je vais faire maintenant, c'est appliquer la première image déjà en tant qu'arrière-plan du div que je viens de créer. Alors là, je vais faire, bon, avant d'intégrer, je mettrai div.style.background-image égal, et comme chaîne de caractères, je vais spécifier l'URL qui est dans ce cas image avec l'index. Je mettrai par exemple im, bon, sachant que im, ça sera une variable, bon, que je vais déclarer ici. De préférence, je vais faire l'appel de la fonction init en dernier. Donc avant, je vais mettre par exemple im égal à 0 pour spécifier donc le premier index de l'image. Maintenant j'actualise. Voilà, donc maintenant j'ai mes 20 divs qui contiennent la même portion d'image qui a été appliquée. Mais bien sûr, pour que l'image soit adaptée avec le conteneur, il faut la redimensionner. C'est-à-dire qu'il faut que la largeur de l'image soit égale à la largeur du conteneur. Alors je mettrai ici, bon avant ou après peu importe, div.style.backgroundColor égal, voyez comme valeur je vais spécifier par exemple donc la largeur de l'image ça sera la largeur du container, donc cont.clientWidth concaténé avec px, et pour la hauteur je vais mettre juste auto, c'est-à-dire je vais laisser le navigateur la deviner automatiquement. Maintenant j'actualise. Alors il n'y a pas un grand changement, mais l'image a bien été redimensionnée. Donc maintenant j'ai la même portion d'image qui se répète, c'est normal. Maintenant je vais jouer sur background-position afin de décaler l'image de div en div, et le résultat sera comme un puzzle, c'est-à-dire une image qui a été constituée de plusieurs morceaux. Alors je mettrai ici div.style.background-position Égal. Alors pour la position des X, bon ça sera juste, c'est une valeur en pourcentage, donc je mettrai l'index i qui multiplie la valeur en pourcentage, voilà 100 divisé par le nombre d'images. Bon je mettrai ici des parenthèses parce que je vais faire la concaténation par la suite. Donc là le nombre d'images c'est nbr. Voilà et là je vais concaténer avec le pourcentage. Et pour la position verticale, je mettrai 50%, c'est-à-dire pour prendre le centre de l'image au niveau vertical. Maintenant j'actualise. Bon, j'ai l'image qui a été constituée, mais en réalité, bon, l'image n'a pas été bien constituée. Regardez, donc il y a bien des traits que je peux voir ici parce que le calcul n'est pas tout à fait correct. En réalité, il fallait mettre ici nbr- 1. Donc maintenant, si on regarde bien, le résultat maintenant est net. Bon, l'image est bien claire, donc il n'y a plus ces petites coupures. En fait, comment ça se fait? Bon, Pour mieux expliquer ça, bon, je vais réduire le nombre à 2. Donc maintenant j'ai 2 portions d'image. Bon, j'actualise. Maintenant j'ai 2 divs, une div ici, une div ici. Alors là, donc la portion de gauche, la position horizontale sera 0%, et la portion de droite, la position de X sera 100%. Maintenant si j'ai 3 portions, maintenant j'ai 3 divs. Bon, j'actualise. La première div, la deuxième div et la troisième ici. La première, la position horizontale sera 0%, la dernière toujours 100% et celle du milieu c'est 50%. Alors ce qu'on constate c'est que toujours je commence par 0 et je finis par 100. Et du coup donc il faut faire en sorte que le calcul colle bien avec le résultat souhaité. Donc là i qui multiplie 100 et qui divise un nombre de telle sorte à ce que le maximum que peut atteindre i corresponde à ce nombre pour avoir la valeur 100 à la fin. Et du coup donc i on sait que ça commence à 0 et ça finit dans ce cas, bon pour la valeur 3 ça va finir à 2. Il faut bien que les dénominateurs soient égaux à 2 aussi, donc c'est 3- 1= 2. Donc maintenant je vais remettre la valeur 20. Mon image est bien reconstituée, c'est bon. Bon, maintenant j'ai plus besoin de ce cadre du container, je peux l'éliminer du CSS comme ça. Alors mon image a bien été constituée. Maintenant nous allons essayer d'appliquer une petite rotation pour chacune des portions de l'image. Alors là, avant la fonction init, bon, je vais créer une autre variable que j'appellerai angle pour dire l'angle. Égal à un tableau. Bon, je mets soit new Array comme ça, ou bien directement des crochets vides pour dire que c'est une variable de type tableau. Voilà. Et maintenant, à chaque fois, donc à chaque itération de i, je vais calculer la nouvelle valeur de angle. Donc angle égale, je mettrai par exemple une valeur négative qui va changer en fonction de i, je mettrai donc -i, donc multiplié par exemple 15 pour dire 15 degrés. Voilà, comme ça. Maintenant, je vais appliquer cet angle à ma portion, c'est-à-dire à mon image actuelle. Bon, je mettrai donc div.style.transform égal, et comme valeur je vais mettre perspective. Je vais spécifier une valeur, par exemple 1000 pixels. Bon, c'est la distance référentielle de l'observateur en quelque sorte. Et là on mettra rotateY Et comme valeur, je vais tout simplement concaténer avec ang . Et bien sûr, il faut spécifier la valeur en degrés. Maintenant, je vais voir le résultat. Ah oui, j'ai une erreur ici dans perspective. Voilà, j'actualise. C'est bien, donc maintenant j'ai bien la rotation qui est appliquée sur chacune des portions. Donc là, c'est la valeur 0, là c'est -15, -30, -45, etc. Donc là on s'est retrouvé avec la valeur -90 qui est perpendiculaire à l'écran, du coup elle n'est pas visible. Même chose ici, c'est un multiple de la valeur -90. Jusqu'ici c'est bon. Donc maintenant on va essayer d'animer ces différentes divs. On va par exemple les faire tourner. Alors là on va prévoir une autre fonction que j'appellerai animer et que j'appellerai d'ailleurs après la création de chacune des portions de l'image. Donc là, function animer. Et vous avez sans doute deviné qu'il s'agit d'une fonction récursive, donc on mettra par exemple t= setTimeout animé. Donc là, la vitesse, bon, ça dépend ce que vous voulez, par exemple 20 millisecondes. Et on va voir ce que ça va donner à la fin. Et ensuite, on va cibler chacune des divs qu'on a créées, on va lui appliquer donc la rotation souhaitée. Bien sûr, on va faire ce traitement 20 fois, donc for i= 0 égal à 0, i inférieur à nbr, i++. Et là on va faire ce traitement. Il y a juste un truc, c'est que bon, n'oubliez pas que le div que j'ai créé ici, bon, il va être écrasé à chaque itération. Bon, ça veut dire quand i égal à 0, donc div, il va indexer la première balise div. Quand i égal à 1, div, il va indexer la deuxième. Du coup, la première maintenant elle est perdue. Alors ce qu'il faut faire, c'est qu'on va ajouter un attribut. Par exemple, je mettrai div.set Attribute. Bon, je peux ajouter id et je lui donne la valeur i. Par exemple, la première portion est identifiée par 0, la deuxième c'est 1 et la dernière c'est 19. Alors là, donc déjà pour voir un petit peu à quoi ça va ressembler, je vais mettre inspecter. Bon, maintenant le code que j'ai c'est ça. Donc la première div, donc elle est identifiée par 0, la deuxième c'est 1, la troisième c'est 2, etc. Donc maintenant je vais prendre cet objet, ça veut dire document.getElementById.style. Donc là je prendrai directement ce style, voilà, parce que c'est le même que je vais appliquer. Et je vais changer la valeur de i, donc angle i, bon je vais par exemple incrémenter de 1. On va voir maintenant ce que ça donne. C'est bien, donc maintenant on a bien l'animation. Donc ça veut dire que toutes les divs maintenant sont en train de tourner. Si on veut accélérer un petit peu le mouvement, alors soit on va diminuer donc le délai, ou bien un incrément d'une valeur supérieure à 1, par exemple 2. Donc là c'est un peu plus rapide qu'avant. Alors maintenant c'est bon pour cette partie, c'est-à-dire celle qui concerne l'animation des objets. Bon, maintenant ce qu'on va essayer de faire, c'est masquer quelques divs parce que l'objectif c'est de créer une sorte de vague. Alors on va pas tout afficher comme ça, mais on va afficher de gauche à droite. Alors premièrement, on va d'abord tout masquer. Bon, c'est-à-dire la création, on fera quelque chose du genre par exemple div.style.visibility hidden. Bon, rien n'est visible dans un premier temps et on va les afficher au fur et à mesure. Là par exemple, on va mettre une condition, par exemple if angle i est supérieur à -90 degrés, parce que figurez-vous que les valeurs sont négatives. Voilà, dans ce cas on va afficher la div en cours, mon document. Alors je copie ça, ou bien je peux faire un truc, je vais faire comme ça, par exemple objet égal, au lieu de répéter ce code à chaque fois. Donc là c'est obj Même chose, donc la orb.style.visibility égale à visible. On va voir maintenant ce que ça donne. Je crois que j'ai une erreur quelque part. Ah oui, voilà, donc là il fallait mettre ça à l'intérieur de la boucle, non pas à l'extérieur, parce que la variable i n'a pas encore été créée. Voilà, maintenant j'actualise. Et voilà, donc ça me donne bien le résultat. Donc en fait, c'est une vague Voilà, comme ça. Bien que c'est une vague qui se propage, mais le mouvement est perpétuel. Bon, il faut bien que ça s'arrête quand l'angle deviendra égal à zéro. J'arrête le mouvement. Donc ce que je vais faire ici, c'est que je mettrai une condition. Donc par exemple, if angle de i est strictement inférieur à zéro, c'est à ce moment-là que je vais incrémenter. Je prends ce code et je mets ici. Voilà, on va voir maintenant ce que ça donne. C'est bon, donc ça commence à ressembler à quelque chose. Bon, on voit bien que la vague pour la première image a bien été créée. Bon, si on veut accélérer un peu le mouvement, alors on va mettre par exemple 10 ici, et là on mettra l'incrémentation par 3. Donc c'est bon pour la première, maintenant c'est bien créé. Si on veut avoir plus d'éléments qui qui bougent en même temps. Alors on va mettre ici, on va réduire, on va mettre par exemple la valeur 10. C'est bon, donc ça donne un petit peu ça. Donc il y a juste un truc, bon si vous regardez encore ici, il y a des petits traits qui s'affichent parce que soit on n'a pas encore atteint la valeur 0, soit on l'a dépassée de peu. En fait c'est normal parce que quand on incrémente la valeur de l'angle, nous ne sommes pas sûrs que l'on va tomber dans la valeur 0. Parce que si on commence de la valeur initiale et qu'on incrémente de 3, est-ce qu'on va vraiment tomber dans la valeur 0? On peut tomber dans une valeur avant ou bien après. Alors on va corriger ça, on va mettre un truc comme ça, donc else, alors angleY, bon ça veut dire si la condition n'est plus vraie, donc on va corriger l'angleY, on va mettre 0. Donc on a forcé la valeur, on va voir maintenant ce que ça donne. C'est bon, maintenant il n'y a plus de trait, on voit bien que ça marche bien. Donc maintenant je peux changer de valeur, je peux mettre n'importe quoi. Bon si je mets 10, le mouvement sera plus rapide, mais On aura toujours pas de problème. Voilà. Alors là, on mettra la valeur 2 comme tout à l'heure. Donc ce qui donne ça. Bon, jusqu'ici c'est bien. Mais maintenant, il faut quand même changer l'image. C'est-à-dire que quand on aura affiché tous les objets, que la dernière div atteint la valeur 0, dans ce cas, il faut changer d'image. Bon, on va mettre ici une condition. Voilà. If ang de la dernière div, à savoir nbr moins un est égal à zéro. Dans ce cas, ce qu'on va faire c'est incrémenter im, donc l'index de l'image. Voilà, on va l'incrémenter de un. Plus égal à un. Mais n'oubliez pas que nous avons un nombre limité d'images. Bon, c'est-à-dire on commence à zéro. Voilà. Et on finit à cinq moins un, c'est-à-dire à quatre. Donc on mettrait ici une condition. Voilà, if im est supérieur à la longueur du tableau, donc à image.length- 1. Donc si c'est supérieur, alors dans ce cas on va remettre im= 0, c'est-à-dire que la valeur de im va toujours être comprise entre 0 et 4. OK, bon, au même moment, ça veut dire que quand je change l'image, ce qu'il faut faire c'est arrêter le compteur. Donc on va mettre clearTimeout. Et quand on arrête le compteur, on va rappeler la fonction init pour qu'il refasse le même traitement en appliquant une autre image. Bon, je mettrai donc ici encore init. Voyons d'abord ce que ça va donner quand j'actualise. En fait, ce n'est pas vraiment ce qui est prévu et c'est tout à fait naturel. Regardez, En effet, nous avons créé 20 divs dans ce cas et à chaque fois on met appendChild, c'est-à-dire on va ajouter un enfant. Du coup, nous avons déjà créé 20 éléments et quand on va créer les 20 prochains, on va les ajouter, on va pas écraser ceux qui existent déjà. Alors ce qu'on va faire, c'est éliminer donc les divs qui existent déjà. Alors tout simplement, avant de créer les 20 divs, on va d'abord supprimer les 20 divs qui existent avant. On mettra donc dans la fonction init, un truc du genre par exemple for i= 0, i< nbr et++. C'est le même intervalle. Et on va cibler l'objet count.removeChild. On va supprimer l'enfant qui n'est rien d'autre que la div qui a été créée. On va la cibler grâce à ID. Donc document.getElementById. Si on fait ça, on va générer une erreur. Pourquoi? Parce qu'à la première exécution, je n'ai pas encore créé aucune div. Alors cet élément n'existe pas et du coup je tente de supprimer un élément qui n'a pas encore été créé. La meilleure solution c'est de faire ce qu'on appelle la gestion des exceptions. On va donc mettre un try. JavaScript supporte bien la gestion des exceptions comme les autres langages comme Java, C++. Et on va mettre catch. En fait, la syntaxe est vraiment très simple. Donc try, c'est-à-dire on va essayer de faire ce code. Bon, sinon on mettra juste true ou bien n'importe quoi. C'est-à-dire que si cette instruction retourne une erreur, comme c'est le cas à la première exécution, dans ce cas on va exécuter juste true, c'est-à-dire juste n'importe quoi pour ne pas laisser de vide. Et sinon, alors la suppression sera effectuée. Ici, bon, ce qu'on appelle l'exception qui a été générée automatiquement par le JavaScript Alors donc vous la nommez comme vous souhaitez, e ou bien peu importe. Donc maintenant on actualise, on va voir ce que ça donne. La première image, deuxième image, troisième, quatrième, cinquième, première. Et voilà, donc ça fait le tour, bon parce qu'on a bien 5 images qui vont défiler de cette manière. Bon, on voit juste que donc la première div, bon on sent pas vraiment l'animation. Alors on va ajouter une autre valeur négative au début, donc Par exemple, on mettra comme valeur initiale, on mettra par exemple -90 degrés pour dire qu'au début c'est perpendiculaire à l'écran, c'est pas visible, et ensuite ça fait le mouvement entier. On va voir maintenant. Maintenant c'est mieux. Alors j'espère que vous avez apprécié cet exercice. Merci pour votre attention et à la vidéo prochaine.
More from Yamossoun

Algorithme de calcule de la racine carrée par dichotomie #dichotomy #squareroot #algorithm









