Carrousel d'images en 3D avec JavaScript et CSS

Carrousel d'images 3en D en Vanilla JS et css sans librairie externe

Introduction

Cette page explique comment créer un carrousel d'images en JavaScript et CSS.

Le carrousel est composé de cinq images visibles et d'une image invisible (utilisée pour charger l'image suivante).

Je sruvole la création dans les grandes lignes, mais si vous souhaitez que je détaille un point, n'hésitez pas à me contacter.

Voici le résultat final :

HTML

Commençons par insérer les images dans le code HTML. Les six images sont encapsulées dans une div principale nommée carousel. Chaque image a un identifiant unique et appartient à la classe carousel-image

<div id="carousel">
    <img src="https://lucidar.me/fr/web-dev/files/img0.svg" id="carousel-image-0" class="carousel-image">
    <img src="https://lucidar.me/fr/web-dev/files/img1.svg" id="carousel-image-1" class="carousel-image">
    <img src="https://lucidar.me/fr/web-dev/files/img2.svg" id="carousel-image-2" class="carousel-image">
    <img src="https://lucidar.me/fr/web-dev/files/img3.svg" id="carousel-image-3" class="carousel-image">
    <img src="https://lucidar.me/fr/web-dev/files/img4.svg" id="carousel-image-4" class="carousel-image">
    <img src="https://lucidar.me/fr/web-dev/files/img5.svg" id="carousel-image-5" class="carousel-image">
</div>

CSS

Ajoutons maintenant la feuilles de style CSS pour placer les images à leurs positions d'origine. Tout d'abord, nous centrons le carrousel au milieu de la page. Bien sûr, vous pouvez modifier cela en fonction de vos besoins.

#carousel {
    width: 100%;
    max-width: 100vw;
    height: 21vh;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    overflow: hidden;
}

Définissons maintenant les attributs généraux de toutes les images :

.carousel-image {
    height: 20vh;
    max-height: 200px;
    position: absolute;
    left: 50%;
    border-radius: 7%;
    box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;

}

Enfin, nous spécifions la position, le z-index et la luminosité de chaque image :

#carousel-image-0 {
    transform: translateX(-50%) translateX(-120%) scale(0.6);
    filter: brightness(40%);
    z-index: 1;
}

#carousel-image-1 {
    transform: translateX(-50%) translateX(-80%) scale(0.8);
    filter: brightness(65%);
    opacity: 1;
    z-index: 2;
}

#carousel-image-2 {
    transform: translateX(-50%) scale(1);
    filter: brightness(100%);
    opacity: 1;
    z-index: 3;
}

#carousel-image-3 {
    transform: translateX(-50%) translateX(80%) scale(0.8);
    filter: brightness(65%);
    opacity: 1;
    z-index: 2;
}

#carousel-image-4 {
    transform: translateX(-50%) translateX(120%) scale(0.6);
    filter: brightness(40%);
    opacity: 1;
    z-index: 1;
}

#carousel-image-5 {
    transform: translateX(-50%) scale(1.5);
    filter: brightness(40%);
    opacity: 0;
    z-index: 1;
}

Voici le résultat intermédiaire :

Animations

Nous définissons une animation pour chaque mouvement. Par exemple, l'animation suivante déplace l'image de la position 0 (l'image de gauche) vers la position 5 (l'image cachée) :

@keyframes mv0to5 {
    0% { transform: translateX(-50%) translateX(-120%) scale(0.6); filter: brightness(40%); opacity: 1; z-index: 2}
    20% { opacity: 0; }
    100% { transform: translateX(-50%) scale(0.6);  filter: brightness(40%); opacity: 0; z-index:1}
}

De même, l'animation suivante est l'inverse de la précédente. Elle déplace l'image de la position 5 (l'image cachée) à la position 0 (l'image de gauche) :

@keyframes mv5to0 {
    0% { transform: translateX(-50%) scale(0.6);  filter: brightness(40%); opacity: 0; z-index:1}    
    80% {opacity:0;}
    100% { transform: translateX(-50%) translateX(-120%) scale(0.6);  filter: brightness(40%); opacity: 1; z-index:2}    
}

Il y a douze animations, une par image pour chaque mouvement (avant et arrière).

Pour chaque animation, nous créons une classe CSS qui exécute le mouvement :

.mv0to5 {
    animation: 0.3s ease-out mv0to5;
    animation-iteration-count: 1;
    animation-fill-mode: forwards;
}

Pour animer le carrousel, il suffit d'ajouter la classe appropriée à chaque image.

JavaScript

Bien entendu, pour l'instant, l'animation n'est réalisée qu'une seule fois. Pour gérer notre carrousel, nous écrivons une classe JavaScript comme suit :

// Class that manage the carousel
class Carousel {

    // Constructor, initialise the carousel
    constructor() {

    // Set a new image (src) to image at given position (pos)
    setImage(pos, src)

    // Hide an image at given position (pos)
    hideImage(pos)

    // Show an image at given position (pos)
    showImage(pos) 

    // Reset carousel, set image 2 in the middle
    reset()

    // Animate one image forward
    next(nextImage)

    // Animate one image backward
    previous(previousImage) {
}

Le constructeur

// Constructor, initialise the carousel
constructor() {
    // Get image elements
    this.img = [];
    this.img[0] = document.getElementById("carousel-image-0");
    this.img[1] = document.getElementById("carousel-image-1");
    this.img[2] = document.getElementById("carousel-image-2");
    this.img[3] = document.getElementById("carousel-image-3");
    this.img[4] = document.getElementById("carousel-image-4");
    this.img[5] = document.getElementById("carousel-image-5");

    // Set animation key frames forward and backward
    this.animForward  = ['mv0to5', 'mv1to0', 'mv2to1', 'mv3to2', 'mv4to3', 'mv5to4'];
    this.animBackward = ['mv0to1', 'mv1to2', 'mv2to3', 'mv3to4', 'mv4to5', 'mv5to0'];

    // Reset carousel 
    this.reset();
}

La fonction reset() supprime toute les animations et écrit l'index de image principale sur l'image 2 (à la position 2) :

// Reset carousel, set image 2 in the middle
reset() {
    // Remove animations
    this.img.forEach((image) => {
        this.animForward.forEach((animation) => {
            image.classList.remove( animation );            
        })
        this.animBackward.forEach((animation) => {
            image.classList.remove( animation );            
        })
    })
    this.currentImage=2;
}

La fonction next(nextImage) anime le carrousel d'une image vers l'avant. Elle met à jour l'image cachée si nécessaire, supprime toutes les classes d'animation avant d'en ajouter une nouvelle. Notez que les classes d'animation peuvent être en avant ou en arrière en fonction de la dernière animation. Ici, nous supprimons les deux.

// Animate one image forward
// If nextImage is defined, replace the hidden image (at position 5) with the new image
next(nextImage) {

    // Set new image if requested
    if (nextImage !== undefined) this.setImage( 5 , nextImage );

    //  Animate    
    this.img.forEach((image, i) => {    

        // Remove animation
        this.animForward.forEach((animation) => { image.classList.remove( animation ); });
        this.animBackward.forEach((animation) => { image.classList.remove( animation ); });

        // Animate to next image
        image.classList.add( this.animForward[(-this.currentImage+i+8)%6] );
    })

    // Increase index to next image
    this.currentImage = (this.currentImage+1)%6;
}

La fonction permettant d'animer un retour en arrière est similaire à celle décrite ci-dessus.

Nous avons également ajouté des fonctions pour cacher, afficher ou remplacer une image :

setImage(pos, src) {
    this.img[(pos+this.currentImage+4)%6].src = src;
}

// Hide an image at given position (pos)
hideImage(pos) {
    this.img[(pos+this.currentImage+4)%6].style.visibility = 'hidden';
}

// Show an image at given position (pos)
showImage(pos) {
    this.img[(pos+this.currentImage+4)%6].style.visibility = 'visible';
}

Voici le résultat final :

Voir aussi


Dernière mise à jour : 07/03/2023