我如何创建一个无限(在x轴上)滚动的元素来重复其内容

我已经创建了一个div,可以像在移动设备上一样用鼠标来滚动它,即,您单击容器,移动鼠标,元素就会被滚动。

我如何创建一个无限(在x轴上)滚动的元素来重复其内容

没什么,这里是codepen的链接:https://codepen.io/kulaska/pen/xxKdRGw

这是HTML结构:

<div class="container">
  <div class="child"></div>
  ...
  <div class="child"></div>
</div>

这是JS文件的主要块:

container.addEventListener("mousemove",({clientX: newX}) => {
  if (!firing) return; 

  let newPos = currPos - (newX - prevX);
  let availableOffset = container.scrollWidth -  container.clientWidth;

  if (newPos > availableOffset)
    newPos = availableOffset;

  if (newPos < 0)
    newPos = 0;

  prevX = newX;
  container.scrollTo(newPos,0);
  currPos = newPos;
})

我使用flex容器创建一个不包装内容的容器:

.container {
  display: flex;
  flex-wrap: nowrap;
..
}

想象一下,该容器中有20张图像。问题是,如何使该div无限滚动,就像将其滚动到末尾一样(直到显示20号图片),然后再显示1,2,3,4等图片,因此重复所有内容。

它可以持续不断地运行,因此仅在容器中放置许多DOM节点是不可行的,因为这在性能方面会太昂贵。

我想到了一些JS解决方案,但它们的性能都相当差。您将如何解决这个问题?

yyfyxzt 回答:我如何创建一个无限(在x轴上)滚动的元素来重复其内容

我对您的Codepen进行了一些编辑,然后我想到了这个解决方案。我刚刚在您的mousemove事件中添加了几行代码。您已经检查了到达容器的开头还是结尾,对吗?因此,让我们扩展这些内容,只添加几行代码,如下所示:

  • 当您尝试降低到零以下时(例如,从索引为0到-1的孩子),您只是剪切了容器的最后一个子元素并粘贴在第一个元素之前。

  • 到达容器末尾时(也就是索引为19的元素,尝试达到20的元素)是同样的事情

这是我编辑的代码:

if (newPos > availableOffset){
  elementToCut = container.querySelector('.child:first-child')
  container.appendChild(elementToCut)
  newPos = availableOffset - elementToCut.offsetWidth;
  elementToCut.removeChild
}

if (newPos < 0){
  firstElement = container.querySelector('.child:first-child')
  elementToCut = container.querySelector('.child:last-child')
  container.insertBefore(elementToCut,firstElement);
  newPos = 0 + elementToCut.offsetWidth;
  elementToCut.removeChild
}

然后添加或删除(取决于您是滚动到开始还是结束)“已移动”元素到当前newPos的宽度。让我知道它是否适合您的需求或是否有帮助!

编辑:我将创建几个函数来在此代码中进行排序(例如,剪切和粘贴元素的代码)

const container = document.querySelector(".container");
const children = document.querySelector(".child");

let [firing,currPos,prevX] = [false,0];

container.addEventListener("mousedown",e => {
  prevX = e.clientX;
  e.preventDefault();
  firing = true;
});

container.addEventListener("mousemove",({
  clientX: newX
}) => {
  if (!firing) return;

  let newPos = currPos - (newX - prevX);
  let availableOffset = container.scrollWidth - container.clientWidth;

  if (newPos > availableOffset) {
    elementToCut = container.querySelector('.child:first-child')
    container.appendChild(elementToCut)
    newPos = availableOffset - elementToCut.offsetWidth;
    elementToCut.removeChild
  }

  if (newPos < 0) {
    firstElement = container.querySelector('.child:first-child')
    elementToCut = container.querySelector('.child:last-child')
    container.insertBefore(elementToCut,firstElement);
    newPos = 0 + elementToCut.offsetWidth;
    elementToCut.removeChild
  }

  prevX = newX;
  container.scrollTo(newPos,0);
  currPos = newPos;
})

container.addEventListener("mouseup",() => {
  firing = false;
})

container.addEventListener("mouseleave",() => {
  firing = false;
})
.container {
  display: flex;
  flex-wrap: nowrap;
  white-space: nowrap;
  overflow-x: scroll;
  overflow-y: hidden;
  -ms-overflow-style: none;
  scrollbar-width: none;
}

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

.child {
  flex: 1 0 200px;
  height: 200px;
  margin: 10px;
}

.green {
  background: green;
}

.blue {
  background: blue;
}
<div class="container">
  <div class="child green">1</div>
  <div class="child blue">2</div>
  <div class="child green">3</div>
  <div class="child blue">4</div>
  <div class="child green">5</div>
  <div class="child blue">6</div>
  <div class="child green">7</div>
  <div class="child blue">8</div>
  <div class="child green">9</div>
  <div class="child blue">10</div>
  <div class="child green">11</div>
  <div class="child blue">12</div>
  <div class="child green">13</div>
  <div class="child blue">14</div>
</div>

本文链接:https://www.f2er.com/3166459.html

大家都在问