You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决快速滚动时scrollLeft()值丢失的问题?

无限轮播组件快速滚动时的scrollLeft值间隙问题

我开发可拖拽/滚动的无限轮播组件已经好几个小时了,但遇到一个棘手问题:快速滚动时,carousel.scrollLeft()无法跟上滚动节奏,出现值间隙。为实现无限轮播的“无缝跳转”逻辑,需要carousel.scrollLeft()精准触达设定的触发值,但直接用if (carousel.scrollLeft() <= scrollTriggerStart)会引发诸多异常问题。相关代码如下:

JavaScript 代码

const carousel = $('.carousel');
const carouselCards = carousel.children('.card');

let cardAmount = 3; // 轮播内可见的卡片数量

carouselCards.slice(-cardAmount).get().reverse().forEach((e) => {
  let card = $(e);
  carousel.prepend(card.prop('outerHTML')); // 将最后3张卡片反向插入到第一张卡片前
})

carouselCards.slice(0, cardAmount).get().forEach((e) => {
  let card = $(e);
  carousel.append(card.prop('outerHTML')); // 将前3张卡片追加到最后一张卡片后
})

let scrollTriggerStart = Math.round(carouselCards.outerWidth() + carouselCards.outerWidth() / 2 - carousel.outerWidth() / 2); // 第二张卡片位于轮播中心时的精确scrollLeft值
let scrollTriggerEnd = Math.round(carousel[0].scrollWidth - carouselCards.outerWidth() - carouselCards.outerWidth() / 2 - carousel.outerWidth() / 2); // 倒数第二张卡片位于轮播中心时的精确scrollLeft值
let seamlessPosStart = carouselCards.length * carouselCards.outerWidth() - carouselCards.outerWidth() / 2 - carousel.outerWidth() / 2; // 与倒数第二张卡片对应的目标scrollLeft值
let seamlessPosEnd = carousel[0].scrollWidth - carouselCards.length * carouselCards.outerWidth() + carouselCards.outerWidth() / 2 - carousel.outerWidth() / 2; // 与第二张卡片对应的目标scrollLeft值

infiniteScroll = () => {
  if (carousel.scrollLeft() <= scrollTriggerStart) {
    carousel.addClass('no-transition');
    carousel.scrollLeft(seamlessPosEnd);
    carousel.removeClass('no-transition');
  } else if (carousel.scrollLeft() >= scrollTriggerEnd) {
    carousel.addClass('no-transition');
    carousel.scrollLeft(seamlessPosStart);
    carousel.removeClass('no-transition');
  }
}

carousel.on('scroll', infiniteScroll);

CSS 代码

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

* {
  font: inherit;
}

html,
body {
  min-height: 100vh;
}

ul:has([class]) {
  list-style: none;
}

body {
  font-family: sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
}

.wrapper {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5em;
  width: 100%;
  padding-inline: 10em;
}

.carousel {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc(100% / 2);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  border-radius: .5em;
  scroll-behavior: smooth;
  scrollbar-width: none;
  width: 100%;
}

.carousel::-webkit-scrollbar {
  display: none;
}

.carousel .card {
  aspect-ratio: 1;
  scroll-snap-align: center;
  background: rgba(255, 0, 0, 0.25);
  border-radius: .5rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  scale: 0.95;
  border: 2px solid transparent;
  transition: 250ms ease;
}

.card.selected {
  border: 2px solid red;
  scale: 1;
}

.no-transition {
  scroll-behavior: auto;
}

.no-transition .card {
  scroll-snap-align: unset;
}

/* .slider-interactive {
    display: flex;
    gap: 4em;
}

.slider-interactive > * {
    background: rgba(255,0,0,0.25);
    aspect-ratio: 1;
    border-radius: 50%;
    cursor: pointer;
    transition: 250ms ease;
    width: 1.5rem;
}

.slider-interactive > *.selected {
    background: red;
} */

HTML 代码

<!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>Infinite carousel</title>
</head>

<body>
  <div class="wrapper">
    <ul class="carousel">
      <li class="card">
        <h2>Card 1</h2>
      </li>
      <li class="card">
        <h2>Card 2</h2>
      </li>
      <li class="card">
        <h2>Card 3</h2>
      </li>
      <li class="card">
        <h2>Card 4</h2>
      </li>
      <li class="card">
        <h2>Card 5</h2>
      </li>
    </ul>
  </div>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" integrity="sha512-v2CJ7UaYy4JwqLDIrZUI/4hqeoQieOmAZNXBeQyjo21dadnwR+8ZaIJVT8EE2iyI61OV8e6M8PP2/4hpQINQ/g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="main.js"></script>
</body>

</html>

内容的提问来源于stack exchange,提问作者Itsjul1an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 01:37:12