复刻ClickUp居中轮播组件遇阻,求前端技术解决方案
无法复刻ClickUp轮播组件求助
我尝试复刻ClickUp SaaS平台的轮播组件但一直失败,恳请各位帮忙解决!
轮播效果说明:同时显示7个元素,中心元素放大高亮,点击左右元素时,该元素会平滑移动到中心位置,保持元素顺序不变。
具体需求
- 轮播始终显示7个元素,第4个元素固定处于居中位置
- 点击中心左侧或右侧的任意元素,该元素需平滑移动至中心,其他元素跟随位移,保持顺序不变
- 效果需与ClickUp官网的轮播完全一致
已尝试的方案及问题
- 基于初始与目标索引移动:移动步长固定为7个元素,导致位移不一致,元素无法正确居中
- 绝对像素值计算移动:使用固定像素值,显示错位,居中元素对齐错误
- 使用currentOffset计算位置:初始定位错误,元素错位、居中不当
- CSS像素移动动画:CSS动画与JavaScript计算不同步,引发显示问题
- 基于点击重新计算:像素移动量计算错误,居中与对齐失效
- 初始居中与移动计算:初始居中错误,错误元素被居中显示
- 直接操作translateX:translateX值设置错误,移动与居中不一致
当前代码
HTML
<div class="carousel-wrapper"> <div class="fade-left"></div> <div class="carousel-container"> <div class="carousel"> <div class="carousel-item"><i class="fa-duotone fa-solid fa-image"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-subtitles" style="--fa-primary-color: #000;"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-link"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-file-code"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-file-pen"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-wand-magic-sparkles"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-circle-question"></i></div> <!-- Dupliquer les éléments pour créer un effet continu --> <div class="carousel-item"><i class="fa-duotone fa-solid fa-image"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-subtitles" style="--fa-primary-color: #000;"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-link"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-file-code"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-file-pen"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-wand-magic-sparkles"></i></div> <div class="carousel-item"><i class="fa-duotone fa-solid fa-circle-question"></i></div> </div> </div> <div class="fade-right"></div> </div>
CSS
body { font-family: Arial, sans-serif; background-color: #f0f0f5; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; } .carousel-wrapper { position: relative; width: 70%; margin: 0 auto; display: flex; align-items: center; } .carousel-container { overflow: hidden; width: 100%; display: flex; justify-content: center; position: relative; padding-left: 100px; padding-right: 100px; } .carousel { display: flex; transition: transform 0.5s ease-in-out; position: relative; } .carousel-item { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; margin: 0 30px; padding: 20px; background-color: #fff; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); opacity: 0.6; transition: opacity 0.3s ease, transform 0.3s ease-in-out; cursor: pointer; width: 150px; } .carousel-item:hover { transform: translateY(-5px); } .carousel-item.active { opacity: 1; transform: scale(1.1); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2); } .fade-left, .fade-right { position: absolute; top: 0; bottom: 0; width: 100px; pointer-events: none; } .fade-left { left: 0; background: linear-gradient(to right, rgba(240, 240, 245, 1), rgba(240, 240, 245, 0)); } .fade-right { right: 0; background: linear-gradient(to left, rgba(240, 240, 245, 1), rgba(240, 240, 245, 0)); } .fa-duotone { font-size: 50px; color: #333; }
JavaScript
const carousel = document.querySelector('.carousel'); const items = document.querySelectorAll('.carousel-item'); const visibleItems = 7; // Le nombre d'éléments visibles let currentIndex = Math.floor(items.length / 3); // Index de l'élément central initial function updateCarousel(newIndex) { const middleIndex = Math.floor(visibleItems / 2); const offset = newIndex - currentIndex; if (newIndex < 0 || newIndex >= items.length) return; const itemWidth = items[0].offsetWidth + 60; // Déplacer le carrousel pour centrer le nouvel élément cliqué carousel.style.transform = `translateX(${-(newIndex - middleIndex) * itemWidth}px)`; // Mettre à jour la classe active items[currentIndex].classList.remove('active'); items[newIndex].classList.add('active'); currentIndex = newIndex; // Mettre à jour l'index courant } // Ajouter l'événement de clic à chaque élément du carrousel items.forEach((item, index) => { item.addEventListener('click', () => { updateCarousel(index); }); }); // Initialiser la position du carrousel items[currentIndex].classList.add('active'); carousel.style.transform = `translateX(${-(currentIndex - Math.floor(visibleItems / 2)) * (items[0].offsetWidth + 60)}px)`;
内容的提问来源于stack exchange,提问作者bobi bob boby
相关产品推荐
相关产品推荐

