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

标签 javascript html css

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

scrollable div

没什么特别的,这里是 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 解决方案,但它们对性能都非常糟糕。你会如何解决这个问题?

最佳答案

我对您的代码笔进行了一些编辑,并想出了这个解决方案。我刚刚向您的 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, 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>

关于javascript - 如何创建一个无限(在 x 轴上)重复其内容的可滚动元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58694298/

相关文章:

css - 覆盖引导容器宽度

javascript - Backbone.js:获取模型集合并渲染它们

javascript - 使用 jQuery 在下拉菜单中使父链接不可点击

html - 如何使用 svg 在矩形内绘制矩形?

html - 无法控制标签和输入标签之间的垂直间距

html - CSS3 Border-radius 创建一个蛋形

javascript - FB.getLoginStatus 始终返回状态 ='unknown'

javascript - 是否可以更新对象中包含的值

html - 在 Shiny tabpanel 上渲染 HTML

html - 如何使我的下拉列表的边框半径为 :hover?