IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Carrousel Infini « responsive »


Sujet :

JavaScript

  1. #1
    Candidat au Club
    Homme Profil pro
    Dessinateur
    Inscrit en
    Septembre 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Dessinateur

    Informations forums :
    Inscription : Septembre 2022
    Messages : 3
    Par défaut Carrousel Infini « responsive »
    Bonjour à tous,

    J’espère être dans la bonne section

    Je me permets de poster ici, je débute dans le JS, après plusieurs recherches sur internet je n'ai pas vraiment trouver de code pour un carrousel en JS (je suis peut-être passé à coté).

    Bref, j'ai trouvé un vieux code JS que j'ai voulu adapter, mon problème et qu'il ne s'adapte pas très bien lorsque je réduit la fenêtre de navigation, mais si j'actualise la page il n'y a plus de problème.

    Je ne vois pas d'où vient de problème exactement mais ça viendrait du JS, j'ai bien checké le CSS ça ne vient pas de là, voici les codes HTML, CSS et JS :

    Mon code sur codepen.io codepen.io/Connerieman/pen/PoLrPbN

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <html lang="fr">
    <head>
    	<meta charset="UTF-8">
    	<title>TITRE</title>
        <link rel="stylesheet" type="text/css" href="CSS/Carrousel-Cliquable-Défilement.css">
    	<script src="JS/Carrousel-Cliquable-Défilement.js" defer></script>
    </head>
        <body>
            <div class="carrousel">
                <div class="cadre">
                    <img class="fleche precedant" src="https://cypherspirit.fr/SVG/Chevron.svg" onclick="changerSlide('precedant')" />
                    <div class="diaporama">
                        <a href=""><img src="https://cypherspirit.fr//IMG/TEST/slide-1.jpg"/></a>
                        <a href=""><img src="https://cypherspirit.fr//IMG/TEST/slide-2.jpg"/></a>
                        <a href=""><img src="https://cypherspirit.fr//IMG/TEST/slide-3.jpg"/></a>
                        <a href=""><img src="https://cypherspirit.fr//IMG/TEST/slide-4.jpg"/></
                          a>
                        <a href=""><img src="https://cypherspirit.fr//IMG/TEST/slide-5.jpg"/></a>
                    </div> 
                    <img class="fleche suivant" src="https://cypherspirit.fr/SVG/Chevron.svg" onclick="changerSlide('suivant')" />
                </div>
                <span class="point"></span>
                <span class="point"></span>
                <span class="point"></span>
                <span class="point"></span>
            </div>
        </body>
    </html>

    Code CSS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    html, body {height: 100%; /*hauteur*/}
     
    body {
    	width: 100%; /*largeur*/
    	margin: 0; /*marge extérieur*/
    	padding: 0; /*marge intérieur*/
    	display: flex; /*apparition des balises :block, inline, inline-block, flex, grid, none*/
    	flex-direction: column; /*direction des balises :column, column-reverse, row, row-reverse*/
    }
     
    /*----------------CARROUSEL----------------*/
     
    .carrousel {
        width: 100%; /*largeur*/
        margin: 80px auto; /*marge extérieur*/
        padding: 0; /*marge intérieur*/
        text-align: center; /*alignement : left, right, center, justify*/
    }
     
    .cadre {
        margin: 0; /*marge extérieur*/
    	padding: 0; /*marge intérieur*/
        display: flex; /*apparition des balises :block, inline, inline-block, flex, grid, none*/
        justify-content: center; /*centre horizontalement le contenu*/ 
    }
     
    .diaporama {
        width: 100%; /*largeur*/
        max-width: 1100px; /*largeur maximum*/
        max-height: 700px; /*hauteur maximum*/
        margin: 0; /*marge extérieur*/
    	padding: 0; /*marge intérieur*/
        display: flex; /*apparition des balises :block, inline, inline-block, flex, none*/
        overflow: hidden; /*dépassement du contenant : visible, hidden, clip, scroll, auto*/
    }
     
    .diaporama a {
        width: 100%; /*largeur*/
        margin: 0; /*marge extérieur*/
    	padding: 0; /*marge intérieur*/
        position: relative; /*type de positionnement*/ 
        text-decoration: none; /*texte decoration*/
        flex-shrink: 0; /*reduction du contenant*/
        transition: transform 0.5s ease; /*transition*/
        transform: translateX(-100%);/**/
    }
     
    .diaporama img {
        width: 100%; /*largeur*/
        height: 100%; /*hauteur*/
        object-fit: cover; /*ajuster à la taille de son contenant*/
        object-position: center; /*position du contenu*/
    }
     
     
    /*----------------FLÈCHE----------------*/
     
    .cadre:hover .fleche {
        opacity: 1; /*opacité*/
    }
     
    .fleche {
        width: 125px; /*largeur maximum*/
        margin: 0; /*marge extérieur*/
    	padding: 0; /*marge intérieur*/
        user-select: none; /*opération de sélection*/
        flex-shrink: 0; /*reduction du contenant*/
        opacity: 1; /*opacité*/
        cursor: pointer; /*type de curseur : default, pointer, help, wait, crosshair, not-allowed, zoom-in, grab, etc...*/
        transition: all 0.5s ease; /* Ajoutez une transition*/
        color: blue; /*couleur de la flèche*/
     
        z-index: 3;
    }
     
    .fleche:hover {
        color: red; /*couleur de la flèche*/
    }
     
    .suivant {
        transform: scaleX(-1) /*transforme*/
    }
     
     
    /*----------------POINT----------------*/
     
    .point {
        width: 15px; /*largeur*/
        height: 15px; /*hauteur*/
        margin: 20px 7px 16px 7px; /*marge extérieur*/
        border-radius: 50%; /*bordure arrondi*/
        display: inline-block; /*apparition des balises :block, inline, inline-block, flex, grid, none*/
        cursor: pointer; /*type de curseur : default, pointer, help, wait, crosshair, not-allowed, zoom-in, grab, etc...*/
        transition: all 0.5s ease; /*temps de changement*/
        background-color: blue; /*couleur non selectionner*/
    }
     
    .point:hover {
        box-shadow: 0px 0px 20px 4px rgb(0, 0, 255); /*couleur de l'ombre*/
    }
     
    .point.active {
        background-color: red; /*couleur selectionner*/
    }
     
    .point.active:hover {
        box-shadow: 0px 0px 20px 4px rgb(255, 0, 0); /*couleur de l'ombre*/
    }

    Code JS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    /* Variable */
    const diaporama = document.querySelector('.diaporama');
    const slides = document.querySelectorAll(".diaporama a")
    let largeur = diaporama.offsetWidth; // problème
    console.log('largeur :' ,largeur);
     
    let index = 0;
    let transition = [];
    let transitionTerminer = true;
     
    // initialisation du carrousel
    for (let i = 0; i < slides.length; i++) {
        transition[i] = -largeur;
        slides[i].addEventListener("transitionend", () => transitionTerminer = true, true);
    }
     
    // mise à jour de la variable en fonction de la taille de la fenêtre
    window.addEventListener('resize', () => {
        largeur = diaporama.offsetWidth;
        for (let i = 0; i < slides.length; i++) {
            transition[i] = -largeur;
        }
    });
     
    // déplacement de la dernière slide en première position
    diaporama.insertBefore(document.querySelector(".diaporama a:last-child"), slides[0]);
     
    // fonction pour changer de slide
    function changerSlide(direction) {
        if (transitionTerminer) {
            transitionTerminer = false;
     
            if (direction === 'suivant') {
                transitionTerminer = false;
                // index de la position actuelle
                let interieur = index % slides.length;
                // ajoute 1 à l'index
                index++;
                //  manipuler chaque élément individuellement
                document.querySelectorAll(".diaporama a").forEach((a, i) => {
                    // rend visible
                    a.style.opacity = '1';
                    // transistion
                    a.style.transform = `translateX(${transition[i] - largeur}px)`;
                    // mets à jour de la position de chaque slide dans le carrousel
                    transition[i] -= largeur;
                });
     
                // élément extérieure de la vue du carrousel
                let exterieur = document.querySelectorAll(".diaporama a")[interieur];
                // transistion
                exterieur.style.transform = `translateX(${transition[interieur] + (largeur * slides.length)}px)`;
                // rend invisible
                exterieur.style.opacity = '0';
                // met à jour la position de l'élément extérieure lors de la transition
                transition[interieur] += largeur * slides.length;
     
     
            } else if (direction === 'precedant') {
                // retire 1 à l'index ou passe à la position du dernier élément
                index = (index === 0) ? slides.length - 1 : index - 1;
                // index de la position actuelle
                let interieur = index % document.querySelectorAll(".diaporama a").length;
                //  manipuler chaque élément individuellement
                document.querySelectorAll(".diaporama a").forEach((a, i) => {
                    a.style.opacity = '1';
                    // transistion
                    a.style.transform = `translateX(${transition[i] + largeur}px)`;
                    // mets à jour de la position de chaque slide dans le carrousel
                    transition[i] += largeur;
                });
                // élément dehors de la vue du carrousel
                let exterieur = document.querySelectorAll(".diaporama a")[interieur];
                // transistion
                exterieur.style.transform = `translateX(${transition[interieur] - (largeur * slides.length)}px)`;
                // rend invisible
                exterieur.style.opacity = '0';
                // met à jour la position de l'élément extérieure lors de la transition
                transition[interieur] -= largeur * slides.length;
            }
        }
    }
     
    // utilisation des flèches du clavier
    document.addEventListener("keydown", function (touche) {
        if (touche.key === "ArrowRight") {
            changerSlide("suivant");
        } else if (touche.key === "ArrowLeft") {
            changerSlide("precedant");
        }
    });


    Il y a juste les flèches format SVG qui ne sont pas afficher mais les cliques à droite et gauche de l'image fonctionnent.

    J'espère que vous pourrait m'aider à mieux comprendre ce code et à trouver une solution, si vous avez un code mieux que celui-ci je suis preneur.

    Bien sûr avant de vous solliciter j'ai cherché et essayé plusieurs solutions sans grand résultat.

    Merci et bonne journée !

  2. #2
    Membre chevronné Avatar de ASCIIDEFOND
    Homme Profil pro
    Autodidacte
    Inscrit en
    Novembre 2002
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Autodidacte

    Informations forums :
    Inscription : Novembre 2002
    Messages : 235
    Par défaut
    Salut Connerieman,

    Un carrousel comme ça ?

    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    <!DOCTYPE html>
    <html lang="en">
     
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <style>
        .container {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
        }
     
        .container img {
          width: 100%;
          height: 100%;
          border-radius: .5em;
        }
     
        .arrow {
          position: absolute;
          cursor: pointer;
          top: 42%;
          padding: 0.4em;
          color: #ffffffae;
          border: 1px solid #ffffff00;
          font-weight: bold;
          font-size: 1.8em;
          transition: 0.2s ease;
          border-radius: .5em;
          user-select: none;
          background-color: rgba(204, 204, 204, 0.15);
          opacity: 0.7;
        }
     
        .arrow:active {
          background-color: rgba(255, 246, 246, 0.345);
          color: #ffffff;
          border: 1px solid #fff;
        }
     
        .arrow:hover {
          background-color: rgba(255, 246, 246, 0.267);
          opacity: 1;
        }
     
        .hide {
          transition: 2s ease;
          opacity: 0;
        }
     
        .prev {
          left: 5px;
        }
     
        .next {
          right: 5px;
        }
     
        .prev::before {
          content: "\0023F4";
        }
     
        .next::before {
          content: "\0023F5";
        }
     
        #nombre-dots {
          position: absolute;
          bottom: 0.1em;
          height: 28px;
          width: auto;
          transform: translate(-50%, -50%);
          left: 50%;
        }
     
        #nombre-dots:hover {
          background-color: #00000054;
          border-radius: 10px;
        }
     
        .dot {
          cursor: pointer;
          height: 14px;
          width: 14px;
          margin: 7px 10px 0px 10px;
          background-color: #fff;
          border-radius: 50%;
          display: inline-block;
          opacity: 0.5;
        }
     
        .dot:hover,
        .active {
          background-color: #ffffffea;
          transform: scale(1.6);
          transition: transform .2s;
          opacity: 0.8;
        }
     
        .dot:hover {
          box-shadow: 0 0 5px #fff;
        }
      </style>
    </head>
     
    <body>
      <div class="container">
     
        <img src="" class="carrousel-img" height="420" width="600">
        <div>
          <a class="prev arrow hide"></a>
          <a class="next arrow hide"></a>
        </div>
        <div id="nombre-dots" class="hide"></div>
      </div>
     
      <script>
        //Le nom et extension des images
        const slides = [
          { nameimg: "slide-1.jpg"},
          { nameimg: "slide-2.jpg"},
          { nameimg: "slide-3.jpg"},
          { nameimg: "slide-4.jpg"},
          { nameimg: "slide-5.jpg"}
        ]
     
        let arrows = document.querySelectorAll('.arrow'),
          hide = document.querySelectorAll('.hide'),
          bannerImg = document.getElementsByClassName('carrousel-img')[0],
          i = 0,
          baliseSpan = ""
     
     
        function actualisation() {
          for (let dot of dots) {
            dot.classList.remove('active')
          }
          bannerImg.src = `https://cypherspirit.fr//IMG/TEST/${slides[i].nameimg}` // Adresse des images
          dots[i].classList.add('active');
        }
     
        // création des dots
        for (let nbdot of slides) {
          baliseSpan += '<span class="dot"></span>'
        }
     
        document.getElementById('nombre-dots').innerHTML = baliseSpan
        let dots = document.querySelectorAll('.dot')
        dots[i].classList.add('active')
        actualisation()
     
        //opacity default arrows and dots
        bannerImg.addEventListener('mouseenter', () => {
          for (const className of hide) {
            className.classList.remove('hide')
          }
        })
     
        //opacity 0 arrows and dots
        document.body.addEventListener('mouseleave', () => {
          for (const className of hide) {
            className.classList.add('hide')
          }
        })
     
        document.addEventListener("keydown", function (touche) {
          if (touche.key === "ArrowLeft" || touche.key === "ArrowRight") {
            touche.key === "ArrowLeft" ? slides[i - 1] ? i -= 1 : i = slides.length - 1 : slides[i + 1] ? i += 1 : i = 0
            actualisation()
          }
        })
     
        for (let arrowSelect of arrows) {
          arrowSelect.addEventListener('click', () => {
            arrowSelect.classList.contains('prev') == true ? slides[i - 1] ? i -= 1 : i = slides.length - 1 : slides[i + 1] ? i += 1 : i = 0
            actualisation()
          })
        }
     
        // Dot position
        dots.forEach((dot, dotPosition) => {
          dot.addEventListener('click', () => {
            i = dotPosition
            actualisation()
          })
        })
     
      </script>
    </body>
     
    </html>

  3. #3
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Vu d'ici, et pour faire un carousel avec des déplacements horizontaux,
    il faut surtout configurer la structure HTML de manière appropriée
    pour pouvoir développer la mécanique de déplacement facilement.

    Il faut un div général dans lequel on va disposer un viewport et les contrôles.
    Dans le viewport on y met un conteneur dont la largeur sera variable, donc en débrdement du viewport, en fonction des items,
    et dans lequel les items seront disposés en colonne, typiquement display: flex; width: fit-content;.

    Le viewport va contraindre l'affichage avec la propriété overflow.
    Le conteneur va se déplacer de gauche à droite en jouant sur la propriété margin-left en négatif.
    Les items doivent cependant être d'une largeur égal au viewport, il faut utiliser une variable css.

    Pour faire un carousel "infini", qui se répète du premier au dernier et du dernier au premier,
    l'astuce consiste à dupliquer le premier et le dernier de manière à les
    insérer respectivement à la fin et au début des items.
    Cela permettra de faire du repositionnement instantané lorsque le carousel défile.

    Dans le cadre d'un simple passage d'un slide à l'autre, keydown/mousewheel,
    lorsque l'utilisateur aura transité sur l'un des items dupliqué,
    il faudra modifier la valeur de margin-left de manière instantanée pour la faire correspondre au véritable premier et dernier élément.
    En fait il faudra, durant la conception, prévoir de faire des déplacements avec transition et sans transitions.
    Par exemple en utilisant une classe spécifique qui ne sert qu'à définir la transition,
    et qui n'est active sur l'élément que lorsqu'on en a besoin.
    Celle ci sera adéquatement retirée lors du transitionend.

    Dans le cadre d'un drag, lorsque l'utilisateur sera entrain de défiler vers la gauche, en partant du premier,
    lorsque margin-left>-(viewport.width/2), on le ramène directement sur le dernier élément en
    faisant jouer la valeur de margin-left et en y incluant le delta d'affichage.
    De la même manière lorsque l'utilisateur déborde par la droite, et qu'il affiche donc
    le pseudo dernier-élément (qui est une copie du premier, pour rappel), on change la valeur
    du margin-left lorsque marginLeft<-(conteneur.width-(viewport.width+(viewport.width/2)) (prendre en compte le premier faux élément, et la moitié du dernier faux élément).
    Il faut faire cela en prenant garde à ne pas utiliser de transtion css, il faut que ce soit instantané lors du redraw.

    Penser aussi à clamper la valeur du margin-left dans l'intervalle [-(conteneur.width-viewport.width), 0]

    Après faut adapter les calculs car margin-left est négatif, ne pas se tromper sinon c'est pénible.

    Pour les évènements, penser à utiliser un booleen pour prévenir le chevauchement de transition lors des keydown et wheel.
    Tant qu'une transition est active, ne rien faire.
    Avec les transitions, plus que probable qu'il y en ait, c'est préférable.

    ----

    Quand je regarde ton code, je retrouve les éléments du viewport, du conteneur, etc
    Mais ce n'est pas tout à fait pareil, la mécanique est un peu différente.
    Au lieu de jouer sur la position du conteneur, tu joues sur la position de tous les items via la transform/translate.
    A mon avis il y a là une petite erreur de conception. Mais je me trompe sûrement, pleins de choses sont possible.
    Quoi qu'il en soit tu pourras tout de même reprendre l'idée consistant à re configurer l'interface de manière instantanée
    lorsque l'utilisateur aura débordé dans la liste des items.

    ----

    Bon sinon des carousels, je suis à peu près certain qu'il y en a 3 millions sur le web.
    A commencer par cette lib https://swiperjs.com/ ça fonctionne, l'effet 3d est sympa,
    mais bon après c'est comme toute ces libs, à vouloir tout faire, c'est (objectivement) lourd et (subjectivement) compliqué.

  4. #4
    Candidat au Club
    Homme Profil pro
    Dessinateur
    Inscrit en
    Septembre 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Dessinateur

    Informations forums :
    Inscription : Septembre 2022
    Messages : 3
    Par défaut
    Merci d'avoir pris du temps pour me répondre et rapidement en plus.

    Citation Envoyé par ASCIIDEFOND Voir le message
    Salut Connerieman,

    Un carrousel comme ça ?
    Merci pour le code du carrousel mais il n'y a plus l'effet de transition sur les slides, je regarderai si je peux ajouter l'effet.

    Citation Envoyé par unanonyme Voir le message
    Vu d'ici, et pour faire un carousel avec des déplacements horizontaux,
    il faut surtout configurer la structure HTML de manière appropriée
    pour pouvoir développer la mécanique de déplacement facilement.

    (...)

    Quand je regarde ton code, je retrouve les éléments du viewport, du conteneur, etc
    Mais ce n'est pas tout à fait pareil, la mécanique est un peu différente.
    Au lieu de jouer sur la position du conteneur, tu joues sur la position de tous les items via la transform/translate.
    A mon avis il y a là une petite erreur de conception. Mais je me trompe sûrement, pleins de choses sont possible.
    Quoi qu'il en soit tu pourras tout de même reprendre l'idée consistant à re configurer l'interface de manière instantanée
    lorsque l'utilisateur aura débordé dans la liste des items.

    (...)
    J'avais a peu près saisie les grandes lignes que tu viens d'expliquer (sans pour autant être capable de le coder) et effectivement la mécanique que tu as d'écrite est différente de mon code actuelle.

    Je vais regarder ce que vous m'avez fournir comme code et explication en détail prochainement, pour être capable d'y arrive seul si possible.

    Pour ce qui est des librairies, effectivement j'en ai vu énormément mais on ne peux pas récupérer le JS directement c'est un import (ou j'ai rien compris), dans mon cas je ne souhaite pas utiliser de lib.

    Ce que je souhaite réaliser c'est rien de nouveau n'y d'extraordinaire, je souhaite surtout apprendre à coder correctement, dans ce contexte avoir un carrousel fonctionnel puis le décortiquer pour en comprendre les étapes. C'est pour ça que je chercher un carrousel avec un code JS accessible et modifiable.

    PS : merci au modo pour avoir corrigé mon premier message

  5. #5
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    n'hésites pas à reposter du code.

    Dans l'immédiat, à mon avis, quelques suggestions.

    Simplifies ton html/css. vas à l'essentiel. Les boutons, osef, la décoration, osef.
    T'as le keydown, le wheel event, bien assez pour commencer.

    Tant que faire ce peut évite l'écoute de l'évènement resize pour venir trifouiller le state.
    Travail autour avec du HTML/Css qui s'adapte naturellement et du javascript
    qui ne mémoïse pas des valeurs.
    De temps en temps c'est vraiment difficile de faire autrement,
    ré étudies pour l'éviter.

    Commences par un code lent, tu verras à la fin si c'est inacceptable,
    et alors, seulement, tu optimises et tu commenceras à faire des choses
    peu recommandable, comme s'appuyer sur l'évènement resize pour trifouiller
    le state. Premature optimization is the root of all evil

    A mon humble avis, pour le js, tu pourrais t'inspirer d'un code comme ça pour démarrer,
    plutôt que des fonctions, et des abonnements, déclarées sur le top level.

    Code js : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    const carousel = (el) => {
     
    	const state = {
    		// des propriétés d'état...
    	};
     
     
    	state.maFunc = () => {
    		// des bidules ici.
    	}
     
    	let listenTarget;
    	state.attach = (target) => {
    		listenTarget = target || document.body;
    		listenTarget.addEventListener(...
    	}
    	state.detach = () => {
    		listenTarget.removeEventListener(...
    	}
     
    	// de l'init ici, si besoin.
     
    	el.carousel = state; // Attache le state à l'élément pour pouvoir y accéder, éventuellement.
     
    	return state;
    };
     
    [...document.body.querySelectorAll(".carousel")].map(carousel).forEach(state => {
    	state.attach(document.body);
    });

    En procédant de la sorte tout est encapsulé dans une fonction unique, facile à exporter,
    le state n'est pas this, pas de confusion, pas de constructeur, donc pas d'usage de new.
    Ici le attach est effectué sur le body pour tirer parti de la délégation d'évènement, pas obligé à toi de voir.

  6. #6
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    Bonjour,
    j'ai regardé ton code et ton approche est originale.

    Le principal point est que tu gères tes translations en px, alors qu'il te faut les exprimer en %.

    Cela se résume à définir la largeur comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //let largeur = diaporama.offsetWidth;
    let largeur = 100;   // cela vaut pour 100% de l'élément
    Important : Lors d'un translation du type transform:translateX(value), le pourcentage se réfère à la dimension de l'élément translaté.


    ...ensuite pour toutes tes lignes du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    element.style.transform = `translateX(${...}px)`;
    il te faut mettre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    element.style.transform = `translateX(${...}%)`;
    si j'ai bien compté c'est 4 lignes à modifier.

    Et dernier point, supprime la fonction sur le resize, elle ne sert plus à rien.

  7. #7
    Candidat au Club
    Homme Profil pro
    Dessinateur
    Inscrit en
    Septembre 2022
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Dessinateur

    Informations forums :
    Inscription : Septembre 2022
    Messages : 3
    Par défaut
    Merci pour ta réponse NoSmoking, ce n'est pas mon approche vu que j'ai récupéré ce code sur internet

    Ta solution fonctionne parfaitement merci, je me doutais que c'était un truc a la noix que j'avais raté ^^'

    J'ai mis à jour le codepen si quelqu'un à besoin du code fonctionnel, je vais quand même faire comme ma conseillé Unanonyme et réécrire un code plus propre (faut que je me trouve un moment pour le faire).

    Encore merci à vous, je suppose que si je passe le sujet en résolu je ne pourrais plus y répondre ?

  8. #8
    Expert confirmé
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 124
    Par défaut
    Salut
    Citation Envoyé par Connerieman Voir le message
    Merci pour ta réponse NoSmoking, .... je suppose que si je passe le sujet en résolu je ne pourrais plus y répondre ?
    Le passage en résolut n’empêche aucunement de continuer à répondre à la discussion.
    A savoir que vous pouvez basculer de et inversement.
    :whistle:pourquoi pas, pour remercier, un :plusser: pour celui/ceux qui vous ont dépannés.
    saut de ligne
    OOOOOOOOO👉 → → Ma page perso sur DVP ← ← 👈

  9. #9
    Membre chevronné Avatar de ASCIIDEFOND
    Homme Profil pro
    Autodidacte
    Inscrit en
    Novembre 2002
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Autodidacte

    Informations forums :
    Inscription : Novembre 2002
    Messages : 235
    Par défaut
    J'avais une autre solution avec cloneNode.

    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <!DOCTYPE html>
    <html lang="en">
     
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="style.css">
        <title>Carrousel</title>
    </head>
     
    <body>
        <div id="container">
            <div id="div-images">
                <img class="li-image" src="https://cypherspirit.fr/IMG/TEST/slide-1.jpg" />
                <img class="li-image" src="https://cypherspirit.fr/IMG/TEST/slide-2.jpg" />
                <img class="li-image" src="https://cypherspirit.fr/IMG/TEST/slide-3.jpg" />
                <img class="li-image" src="https://cypherspirit.fr/IMG/TEST/slide-4.jpg" />
                <img class="li-image" src="https://cypherspirit.fr/IMG/TEST/slide-5.jpg" />
            </div>
            <span id="precedent" class="directions precedent"></span>
            <span id="suivant" class="directions suivant"></span>
            <div id="div-indicateur"></div>
        </div>
        <script>
            let spanElem
     
            for (let x = 0; x < document.getElementById('div-images').children.length; x++) {
                spanElem = document.createElement('span')
                spanElem.setAttribute('class', 'position')
                x == 0 ? spanElem.setAttribute('style', 'opacity: 1;') : spanElem.setAttribute('style', 'opacity: 0.35;')
                document.getElementById('div-indicateur').appendChild(spanElem)
            }
        </script>
     
        <script src="script.js" defer></script>
    </body>
     
    </html>

    Code css : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    * {
      box-sizing: border-box;
    }
     
    :root {
      --main-width: 800px;
      --main-height: 500px;
      --main-transition: 0.6s ease 0s;
    }
     
    body {
      background-color: #282828;
    }
     
    #container {
      position: absolute;
      max-width: var(--main-width);
      max-height: var(--main-height);
      overflow: hidden;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      margin: auto;
      width: 100%;
      height: max-content;
    }
     
    #div-images {
      display: flex;
      position: relative;
      left: calc(var(--main-width) * -1);
    }
     
    #div-images.transition-image {
      transition: var(--main-transition);
    }
     
    .li-image {
      max-width: 100%;
    }
     
    .directions {
      position: absolute;
      width: 50px;
      height: 50px;
      background-color: rgba(0, 0, 0, 0.15);
      border-radius: 50px;
      transition: var(--main-transition);
      cursor: pointer;
      color: #ffffff38;
      opacity: 0;
      font-size: 3em;
      text-align: center;
     top:44%;
    }
     
    .precedent {
      left: 8px;
      line-height: 1em;
    }
     
    .suivant {
      right: 8px;
      line-height: 1em;
    }
     
    .precedent::before {
      content: "\0023F4";
    }
     
    .suivant::before {
      content: "\0023F5";
    }
     
    .precedent:hover,
    .suivant:hover {
      opacity: 0.75;
      box-shadow: 0px 0px 10px 0px rgb(184, 184, 184);
    }
     
    .precedent:active,
    .suivant:active {
      transition: none;
      box-shadow: 0px 0px 10px 4px rgb(255, 255, 255);
      opacity: 1;
    }
     
    .disabled-directions {
      transition: none;
      box-shadow: 0px 0px 10px 4px rgb(255, 255, 255);
      opacity: 0.5;
      pointer-events: none;
    }
     
    #div-indicateur {
      position: absolute;
      left: 0;
      right: 0;
      bottom: 5px;
      padding: 1px 2px;
      width: max-content;
      background-color: #00000047;
      border-radius: 17px;
      margin: 0 auto;
      opacity: 0;
      transition: var(--main-transition);
    }
     
    .position {
      height: 16px;
      width: 16px;
      border-radius: 100%;
      display: inline-block;
      cursor: pointer;
      opacity: 0.35;
      margin: 3px 3px 0 3px;
      background-color: #fafafa;
    }
     
    #container:hover #div-indicateur,
    #container:hover .directions {
      transition: none;
      opacity: 0.65;
    }

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    let divImages = document.getElementById('div-images'),
        directions = document.querySelectorAll('.directions'),
        liImages = divImages.getElementsByClassName('li-image'),
        imageLenght = liImages.length,
        imageSize = divImages.getElementsByClassName('li-image')[0].offsetWidth,
        index = 0
     
    divImages.appendChild(liImages[0].cloneNode(true));
    divImages.insertBefore(liImages[imageLenght - 1].cloneNode(true), liImages[0])
     
    function indicateur(i) {
        let indicateurlPosition = document.querySelectorAll('.position')
     
        for (let x = 0; x < imageLenght; x++) {
            i == x ? indicateurlPosition[i].style.opacity = '1' :
                indicateurlPosition[x].style.opacity = '0.35'
        }
    }
     
    function changeImage(touche, i) {
        let posInitial = divImages.offsetLeft
        imageSize = divImages.getElementsByClassName('li-image')[0].offsetWidth
     
        directions[i].classList.add('disabled-directions')
        divImages.classList.add('transition-image')  
     
        touche == 'droite' ? [
            divImages.style.left = `${posInitial - imageSize}px`,
            index += 1
        ] : [
            divImages.style.left = `${posInitial + imageSize}px`,
            index -= 1
        ]
     
        divImages.addEventListener("transitionend", function (event) {
            directions[i].classList.remove('disabled-directions')
            divImages.classList.remove('transition-image')
            indicateur(index)
            document.getElementById('div-indicateur').removeAttribute('style')
        }, false);
    }
     
    function deplacement() {
         index == -1 ? [
            divImages.style.left = `-${(imageLenght * imageSize)}px`,
            index = imageLenght - 1
        ] : index == imageLenght ? [
            divImages.style.left = `-${(imageSize)}px`,
            index = 0
        ] : []
    }
     
    window.addEventListener('resize', () => {
        let posImg = divImages.getElementsByClassName('li-image')[index+1].offsetLeft
         divImages.style.left = `-${posImg}px` 
    });
     
    divImages.addEventListener('transitionend', deplacement)
     
    document.getElementById('precedent').addEventListener('click', () => changeImage('gauche', 0))
    document.getElementById('suivant').addEventListener('click', () => changeImage('droite', 1))
     
    // Défilement avec les touches ArrowRight ou ArrowLeft
    document.addEventListener('keydown', function (e) {
        let dirs = [directions[0].classList.contains('disabled-directions'), directions[1].classList.contains('disabled-directions')]
        document.getElementById('div-indicateur').style.opacity = 1
        !e.repeat ? [
            e.key === 'ArrowRight' && !dirs[0] && !dirs[1] ? changeImage('droite', 1) :
                e.key === 'ArrowLeft' && !dirs[0] && !dirs[1] ? changeImage('gauche', 0) : null
        ] : [null]
    })

  10. #10
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 198
    Par défaut
    Citation Envoyé par Connerieman
    je vais quand même faire comme ma conseillé Unanonyme et réécrire un code plus propre
    Sans vouloir entrer dans une polémique interminable il faudrait déjà définir ce qu'est un code propre
    Lorsque l'on regarde ce que « tu » as fait on ne peut pas dire que l'on soit en présence d'un code « sale » !

    Le reproche que l'on pourrait faire est que tu exposes tout dans le scope global.
    Pour remédier à cela tu peux utiliser les namespaces ou si tu as besoin de plusieurs carrousels les classes(class) en JavaScript moderne ou même les modules.
    Il y a aussi, peut-être, l'écouteur du keydown sur le document qui me chagrine et qui pourrait enter en conflit avec ta page.

    Si tu souhaites réaliser un carrousel, « complet », avec gestion des touches flèches (up, down, home, end ...) voir drag ou plus ..., il va te falloir bien structurer ton code afin d'en facilité les évolutions/modifications sans tout casser.

    C'est ton besoin final qui doit déterminer jusqu'où tu veux aller.

    Ceci étant il existe moult façons de concevoir des carrousels, tu en as un exemple avec les réalisations de ASCIIDEFOND.

    Je ne résiste donc pas à l'envie de partager, après mise au propre, une expérimentation que j'avais réalisée, et partagée ici même, dans le cadre de : Diaporama en 3 lignes de code.
    C'est encore une autre approche, une de plus donc, où l'on manipule le DOM et où on laisse faire le CSS via les keyframes. C'est du basique mais très souvent suffisant.

    Le JavaScript se résume à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function moveSlide(e) {
      const btn = e.target;
      const action = btn.dataset.action;
      const idSlide = btn.dataset.diapo;
      const elemSlide = document.getElementById(idSlide);
      elemSlide.classList["right" == action ? "add" : "remove"]("reverse");
      switch (action) {
        case "right":
          elemSlide.append(elemSlide.firstElementChild);
          break;
        case "left":
          elemSlide.prepend(elemSlide.lastElementChild);
          break;
      }
    }
    il y aurait matière à ajouter des verrous quand même !

    Concernant le CSS, tout est sur base de translation qui reste plus efficace que la modification des propriétés margin ou autre left.


    Le fichier test en ligne :

  11. #11
    Membre chevronné Avatar de ASCIIDEFOND
    Homme Profil pro
    Autodidacte
    Inscrit en
    Novembre 2002
    Messages
    235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Landes (Aquitaine)

    Informations professionnelles :
    Activité : Autodidacte

    Informations forums :
    Inscription : Novembre 2002
    Messages : 235
    Par défaut
    Beau boulot NoSmoking, ton code est bien plus compréhensible et concis.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Servlet] response.getWriter()
    Par phoebe dans le forum Servlets/JSP
    Réponses: 6
    Dernier message: 18/05/2004, 11h36
  2. Response.BinaryWrite dans un formulaire
    Par faamugol dans le forum ASP
    Réponses: 4
    Dernier message: 12/05/2004, 12h45
  3. [LG]tableau infini et fonction longueur
    Par dsr57 dans le forum Langage
    Réponses: 8
    Dernier message: 13/12/2003, 13h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo