双向无限滚动-向上和向下

21

我正在尝试创建一个无限向上和向下滚动的页面。

目前,我正在使用jQuery将内容从页面顶部重新定位到底部。这样当您向下滚动时就会创建一个很好的无缝循环,但我也希望在用户向上滚动时能够实现。

问题似乎是即使内容定位在页面的负垂直空间上,滚动也不会延伸到那个空间。据我所知,没有办法覆盖这个问题,所以我正在寻找某种解决方法。

我考虑使用JavaScript来禁用滚动,并使用滚动事件重新定位元素,但页面上已经有很多绝对定位的元素和动画效果,因此我担心这样做会影响性能。

还有其他的想法吗?


你好。我想知道你是如何实现你已经拥有的滚动循环的。谢谢。 - Alejo Dev
6个回答

4

好的...我解决了。

我改编了这个脚本,当你滚动到页面底部时,它会立即将滚动位置重新定位到页面顶部,并在到达页面顶部时将其定位到底部。

$(window).scroll(function() {
    if ( $(window).scrollTop() >= 18830 ) {
        $(window).scrollTop(201);
    }
    else if ( $(window).scrollTop() == 0 ) {
        $(window).scrollTop(18629);
    }    
});

然后,我确保页面底部和顶部的内容完全相同。我认为当这种重定位发生时会有闪烁或其他东西,但它是平稳的!


12
我写了这个脚本。你意识到这是我发布的那个代码吗? - jon
6
抱歉,我刚刚才注意到这个问题。我并没有故意让人们误以为是我从头开始编写了脚本,这只是一个诚实的错误。 - Joe Hamilton

3
我最喜欢的解决方案是这个代码),因为它在底部添加元素,到达底部之前,确保滚动保持连续(即使在平滑滚动时)。但是,在移动电话上,滚动可能非常快,所以它的效果不那么好。我建议您阅读Marijn Haverbeke的精彩文章,其中他处理了类似的问题,介绍了CodeMirror中的虚拟滚动条。
以下是一些片段:

首先,一些背景知识。为什么我们要伪造滚动条呢?

为了在加载大文档时保持响应性,CodeMirror不会渲染整个文档,而只会渲染当前滚动到视图中的部分。这意味着它创建的DOM节点数量受到视口大小的限制,并且由文本更改触发的浏览器重排相对便宜。

接下来是更深入的内容...

然后,它监听滚轮事件,但从不在这些事件上调用preventDefault或响应它们进行滚动。相反,它通过设置超时来响应滚轮事件,以观察滚动内容的像素量,并使用它来在运行时调整其增量到像素率。


2

将HTML body克隆两次(或三次)(使用JavaScript或其他方式)。从中间副本开始页面而不是顶部,然后您可以按照您喜欢的方式处理滚动。


哦...但是即使您有元素放置在那个位置之外,似乎滚动超过top:0px位置是不可能的。 - Joe Hamilton
你将不再使用那种语法。暂时放下你的方法,想象一下一个简单的、没有JS的页面,有几个HTML元素。克隆内容。滚动到第一份副本的末尾(第二份的开头)。你不能上下滚动吗? - Mahmoud Al-Qudsi
用户开始滚动后,您将从底部向上移动数据。但由于您并不是从顶部开始的,因此用户不会到达滚动限制。 - Mahmoud Al-Qudsi

1

正如许多人建议的那样,如果您的页面在顶部和底部看起来不完全相同,您需要克隆您的内容以使其看起来像是一样的。我使用了这种技术制作了一个示例,效果非常流畅:

/*
Ininite looping scroll.
Tested and works well in latest Chrome, Safari and Firefox.
*/

(function (window) {
  'use strict';

  var doc = document,
    body = doc.body,
    html = doc.documentElement,
    startElement = doc.getElementsByClassName('is-start')[0],
    clones = doc.getElementsByClassName('is-clone'),
    disableScroll = false,
    docHeight,
    scrollPos,
    clonesHeight,
    i;

  function getScrollPos() {
    return (window.pageYOffset || html.scrollTop)  - (html.clientTop || 0);
  }

  function getDocHeight() {
    return Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
  }

  function getClonesHeight() {
    i = 0;
    clonesHeight = 0;

    for (i; i < clones.length; i += 1) {
      clonesHeight = clonesHeight + clones[i].offsetHeight;
    }

    return clonesHeight;
  }

  docHeight = getDocHeight();
  clonesHeight = getClonesHeight();

  window.addEventListener('resize', function () {
    scrollPos = getScrollPos();
    docHeight = getDocHeight();
    clonesHeight = getClonesHeight();

    if (scrollPos <= 0) {
      window.scroll(0, 1); // Scroll 1 pixel to allow upwards scrolling.
    }
  }, false);

  window.addEventListener('scroll', function () {
    if (disableScroll === false) {
      scrollPos = getScrollPos();

      if (clonesHeight + scrollPos >= docHeight) {
        // Scroll to the top when you’ve reached the bottom
        window.scroll(0, 1); // Scroll 1 pixel to allow upwards scrolling.
        disableScroll = true;
      } else if (scrollPos <= 0) {
        // Scroll to the top of the clones when you reach the top.
        window.scroll(0, docHeight - clonesHeight);
        disableScroll = true;
      }

      if (disableScroll) {
        // Disable scroll-repositioning for a while to avoid flickering.
        window.setTimeout(function () {
          disableScroll = false;
        }, 100);
      }
    }
  }, false);

  // Needs a small delay in some browsers.
  window.setTimeout(function () {
    if (startElement) {
      // Start at the middle of the starting block.
      window.scroll(0, Math.round(startElement.getBoundingClientRect().top + document.body.scrollTop - (window.innerHeight - startElement.offsetHeight) / 2));
    } else {
      // Scroll 1 pixel to allow upwards scrolling.
      window.scroll(0, 1);
    }
  });

}(this));
section {
  position: relative;
  text-align: center;
  height: 80vh;
}

.red {
  background: #FF4136;
}
.green {
  background: #2ECC40;
}
.blue {
  background: #0074D9;
}
.orange {
  background: rebeccapurple;
}

h1 {
  margin: 0;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 100%;

  font-size: 5vw;
  color: #fff;
  text-transform: uppercase;
}

body {
  font-family: "Avenir Next", Montserrat, Helvetica, sans-serif;
  font-weight: normal;
  font-size: 100%;
}

::scrollbar {
  display: none;
}
<section class="green">
  <h1>One</h1>
</section>
<section class="red">
  <h1>For</h1>
</section>
<section class="blue">
  <h1>All</h1>
</section>
<section class="orange">
  <h1>And</h1>
</section>
<section class="blue">
  <h1>All</h1>
</section>
<section class="red">
  <h1>For</h1>
</section>

<!--
These following blocks are the same as the first blocks to get that looping illusion going. You need to add clones to fill out a full viewport height.
-->
<section class="green is-clone is-start">
  <h1>One</h1>
</section>
<section class="red is-clone">
  <h1>For</h1>
</section>


1

5
这些都没有无限向上和向下滚动。 - Mahmoud Al-Qudsi

0
在Mahmoud的回答基础上,我在几分钟内编写了这个程序。它可以在使用键盘或鼠标滚轮滚动时正常工作(至少在Firefox上),但是当拖动滚动条时会出现各种故障。根据
高度与视口高度的关系,也可能会发生各种问题。尽管如此,我仍然希望这可以帮助您朝着正确的方向前进。

function onScroll(){
    var SAFETY_MARGIN = 50,
        scrollPos = $(this).scrollTop(),
        docHeight = $(document.body).height(),
        winHeight = $(window).height(),
        firstDiv = $('body>div:first-child')[0],
        lastDiv = $('body>div:last-child')[0],
        lowerLimit = SAFETY_MARGIN,
        higherLimit = docHeight - SAFETY_MARGIN;

    // Scrolling too high
    if( scrollPos <= lowerLimit ){

        // Move content to top;
        $(lastDiv).prependTo(document.body);

        // Adjust scroll position to compensate
        // for the new content at the top
        $(window).scrollTop(scrollPos + $(lastDiv).height());

    }

    // Scrolling too low
    else if( scrollPos + winHeight >= higherLimit ){

        // Move content to bottom
        $(firstDiv).appendTo(document.body);

        // Adjust scroll position to compensate
        // for the missing content at the top
        $(window).scrollTop(scrollPos - $(firstDiv).height());
    } 
}


$(window).scroll(onScroll);

$(window).load(function(){
    var $body = $(document.body);
    $(window).scrollTop($body.height() / 2);
});

</script>
</head>
<body>

<div style="height: 600px; background-color: red">&nbsp;</div>
<div style="height: 600px; background-color: green">&nbsp;</div>
<div style="height: 600px; background-color: blue">&nbsp;</div>

</body>
</html>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接