Code carousel

Html

				
					<div class="layout">
    <div class="carousel">
        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 1</div>
                <div class="num">01</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div>

        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 2</div>
                <div class="num">02</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div>

        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 3</div>
                <div class="num">03</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div>

        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 4</div>
                <div class="num">04</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div>

        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 5</div>
                <div class="num">05</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div>

        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 6</div>
                <div class="num">06</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div>

        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 7</div>
                <div class="num">07</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div>

        <div class="carousel-item">
            <div class="carousel-box">
                <div class="title">Titre 8</div>
                <div class="num">08</div>
                <img decoding="async" src="liendetonimage.png" alt="liendetonimage" title="Code carousel 1">
            </div>
        </div> 
        
    </div>
</div>


<div class="cursor"></div>
<div class="cursor cursor2"></div>
				
			

CSS

				
					  .layout {
    overflow: hidden;
    font-family: "Roboto", serif;
    background: white;
  }
  
  .carousel {
    position: relative;
    z-index: 1;
    height: 100vh;
    overflow: hidden;
    pointer-events: none;
  }
  
  .carousel-item {
    --items: 8; /* A changer selon le nombre */
    --width: clamp(150px, 30vw, 300px);
    --height: clamp(200px, 40vw, 400px);
    --x: calc(var(--active) * 800%);
    --y: calc(var(--active) * 200%);
    --rot: calc(var(--active) * 120deg);
    --opacity: calc(var(--zIndex) / var(--items) * 3 - 2);
    overflow: hidden;
    position: absolute;
    z-index: var(--zIndex);
    width: var(--width);
    height: var(--height);
    margin: calc(var(--height) * -0.5) 0 0 calc(var(--width) * -0.5);
    border-radius: 10px;
    top: 50%;
    left: 50%;
    -webkit-user-select: none;
       -moz-user-select: none;
        -ms-user-select: none;
            user-select: none;
    transform-origin: 0% 100%;
    box-shadow: 0 10px 50px 10px rgba(0, 0, 0, 0.5);
    background: black;
    pointer-events: all;
    transform: translate(var(--x), var(--y)) rotate(var(--rot));
    transition: transform 0.8s cubic-bezier(0, 0.02, 0, 1);
  }
  .carousel-item .carousel-box {
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    transition: opacity 0.8s cubic-bezier(0, 0.02, 0, 1);
    opacity: var(--opacity);
    font-family: "Orelo-sw-db", serif;
  }
  .carousel-item .carousel-box:before {
    content: "";
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0) 30%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.5));
  }
  .carousel-item .title {
    position: absolute;
    z-index: 1;
    color: #fff;
    bottom: 20px;
    left: 20px;
    transition: opacity 0.8s cubic-bezier(0, 0.02, 0, 1);
    font-size: clamp(20px, 3vw, 30px);
    text-shadow: 0 4px 4px rgba(0, 0, 0, 0.1);
  }
  .carousel-item .num {
    position: absolute;
    z-index: 1;
    color: #fff;
    top: 10px;
    left: 20px;
    transition: opacity 0.8s cubic-bezier(0, 0.02, 0, 1);
    font-size: clamp(20px, 10vw, 80px);
  }
  .carousel-item img {
    width: 100%;
    height: 100%;
    -o-object-fit: cover;
       object-fit: cover;
    pointer-events: none;
  }
  
  .layout {
    position: absolute;
    z-index: 0;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
  }
  .layout:before {
    content: "";
    position: absolute;
    z-index: 1;
    top: 0;
    left: 90px;
    width: 10px;
    height: 100%;
    border: 1px solid #fff;
    border-top: none;
    border-bottom: none;
    opacity: 0.15;
  }
  .layout .box {
    position: absolute;
    bottom: 0;
    left: 30px;
    color: #fff;
    transform-origin: 0% 10%;
    transform: rotate(-90deg);
    font-size: 9px;
    line-height: 1.4;
    text-transform: uppercase;
    opacity: 0.4;
  }
  
  .cursor {
    position: fixed;
    z-index: 10;
    top: 0;
    left: 0;
    --size: 40px;
    width: var(--size);
    height: var(--size);
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.2);
    margin: calc(var(--size) * -0.5) 0 0 calc(var(--size) * -0.5);
    transition: transform 0.85s cubic-bezier(0, 0.02, 0, 1);
    display: none;
    pointer-events: none;
  }
  @media (pointer: fine) {
    .cursor {
      display: block;
    }
  }
  
  .cursor2 {
    --size: 2px;
    transition-duration: 0.7s;
  }
  
  @media screen and (max-width: 1024px) {
    .carousel-item {
        width: clamp(150px, 80vw, 500px) !important;
        height: clamp(200px, 80vw, 600px) !important;
        top: 35%;
      }
  }
				
			

JS

				
					/*--------------------
Vars
--------------------*/
let progress = 50
let startX = 0
let active = 0
let isDown = false

/*--------------------
Contants
--------------------*/
const speedWheel = 0.02
const speedDrag = -0.1

/*--------------------
Get Z
--------------------*/
const getZindex = (array, index) => (array.map((_, i) => (index === i) ? array.length : array.length - Math.abs(index - i)))

/*--------------------
Items
--------------------*/
const $items = document.querySelectorAll('.carousel-item')
const $cursors = document.querySelectorAll('.cursor')

const displayItems = (item, index, active) => {
  const zIndex = getZindex([...$items], active)[index]
  item.style.setProperty('--zIndex', zIndex)
  item.style.setProperty('--active', (index-active)/$items.length)
}

/*--------------------
Animate
--------------------*/
const animate = () => {
  progress = Math.max(0, Math.min(progress, 100))
  active = Math.floor(progress/100*($items.length-1))
  
  $items.forEach((item, index) => displayItems(item, index, active))
}
animate()

/*--------------------
Click on Items
--------------------*/
$items.forEach((item, i) => {
  item.addEventListener('click', () => {
    progress = (i/$items.length) * 100 + 10
    animate()
  })
})

/*--------------------
Handlers
--------------------*/
const handleWheel = e => {
  const wheelProgress = e.deltaY * speedWheel
  progress = progress + wheelProgress
  animate()
}

const handleMouseMove = (e) => {
  if (e.type === 'mousemove') {
    $cursors.forEach(($cursor) => {
      $cursor.style.transform = `translate(${e.clientX}px, ${e.clientY}px)`
    })
  }
  if (!isDown) return
  const x = e.clientX || (e.touches && e.touches[0].clientX) || 0
  const mouseProgress = (x - startX) * speedDrag
  progress = progress + mouseProgress
  startX = x
  animate()
}

const handleMouseDown = e => {
  isDown = true
  startX = e.clientX || (e.touches && e.touches[0].clientX) || 0
}

const handleMouseUp = () => {
  isDown = false
}


function togglePlay() {
  const video = document.getElementById('videoPlayer');
  const playButton = document.getElementById('playButton');

  if (video.style.display === 'none') {
      video.style.display = 'block'; // Show video
      playButton.style.display = 'none'; // Hide button
      video.src += "?autoplay=1"; // Autoplay video
  }
}

/*--------------------
Listeners
--------------------*/
document.addEventListener('mousewheel', handleWheel)
document.addEventListener('mousedown', handleMouseDown)
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
document.addEventListener('touchstart', handleMouseDown)
document.addEventListener('touchmove', handleMouseMove)
document.addEventListener('touchend', handleMouseUp)