javascript 双向无限滚动 - 向上和向下
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10570684/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Infinite scrolling in both directions - Up and down
提问by Joe Hamilton
I am trying to create a page that is an endless scrolling loop both up and down.
我正在尝试创建一个向上和向下无限滚动循环的页面。
At the moment I am using jquery to relocate content from the top of the page to the bottom. This creates a nice seemless loop when you scroll down but I would like it to work when the user scrolls up too.
目前我正在使用 jquery 将内容从页面顶部重新定位到底部。当您向下滚动时,这会创建一个很好的无缝循环,但我希望它在用户向上滚动时也能工作。
The problem seems to be that even if content is positioned in negative vertical space on the page the scroll will not extend to that space. As far as I am aware there is no way to override this so I am looking for some type of work around.
问题似乎是,即使内容位于页面上的负垂直空间,滚动也不会延伸到该空间。据我所知,没有办法覆盖它,所以我正在寻找某种类型的解决方法。
I have thoughts of using javascript to disable the scrolling and using the scroll event to reposition the elements but there are already lots of absolute positioned elements and animation happening on the page so I'm concerned about performance taking that route.
我想使用 javascript 来禁用滚动并使用滚动事件来重新定位元素,但是页面上已经有很多绝对定位的元素和动画发生,所以我担心采用该路线的性能。
Any other leads?
还有其他线索吗?
采纳答案by jon
Any other leads?
还有其他线索吗?
Seen these?
看到这些了吗?
5 jQuery infinite Scrolling Demos
jsfiddle that I cannot find origin of.(I didn't write and don't know who did)
我找不到来源的 jsfiddle。(我没有写,也不知道是谁写的)
回答by Joe Hamilton
OK... I worked it out.
好的...我解决了。
I adapted this scriptwhich instantly relocates the scroll location to the top of the page when you get to the bottom and to the bottom when you reach the top.
我改编了这个脚本,当你到达底部时,它会立即将滚动位置重新定位到页面顶部,当你到达顶部时,它会立即将滚动位置重新定位到页面底部。
$(window).scroll(function() {
if ( $(window).scrollTop() >= 18830 ) {
$(window).scrollTop(201);
}
else if ( $(window).scrollTop() == 0 ) {
$(window).scrollTop(18629);
}
});
And then I made sure that the content at the bottom and the top of the page was identical. I thought that there would be a flash or something when this relocation happened but it's smooth!
然后我确保页面底部和顶部的内容相同。本以为搬迁时会出现闪退什么的,结果很顺利!
回答by Andres Riofrio
The solution I like the best is this one(code), because it adds elements at the bottom beforethe bottom is reached, making sure that scrolling remains continuous (even with smoothscrollingon). However, it doesn't work that well on mobile phones where scrolling can happen pretty quickly. I recommend Marijn Haverbeke's wonderful articleon fake scrollbars in CodeMirror where he deals with similar issues.
我最喜欢的解决方案是这个(代码),因为它在到达底部之前在底部添加元素,确保滚动保持连续(即使平滑滚动)。但是,它在滚动可能很快发生的手机上效果不佳。我推荐 Marijn Haverbeke在 CodeMirror 中关于假滚动条的精彩文章,他在那里处理了类似的问题。
I leave you with some snippets.
我给你留下了一些片段。
First, some background. Why would we want to fake a scrollbar to begin with?
In order to remain responsive when huge documents are loaded in, CodeMirror does not render the whole document, but only the part of it that is currently scrolled into view. This means that the amount of DOM nodes it creates is limited by the size of the viewport, and the browser relayouts triggered by changes to the text are relatively cheap.
首先,一些背景。为什么我们首先要伪造滚动条?
为了在加载大量文档时保持响应,CodeMirror 不会渲染整个文档,而只会渲染当前滚动到视图中的部分。这意味着它创建的 DOM 节点数量受到视口大小的限制,并且由文本更改触发的浏览器重新布局相对便宜。
And further down...
再往下...
Then, it listens to wheel events, but never calls preventDefault on them or does scrolling in response to them. Instead, it responds by setting a timeout to observe the amount of pixels that the wheel event did scroll the content, and uses that to tweak its delta-to-pixel rate at run-time.
然后,它侦听滚轮事件,但从不对其调用 preventDefault 或滚动以响应它们。相反,它通过设置超时来响应滚轮事件确实滚动内容的像素数量,并在运行时使用它来调整其增量到像素的比率。
回答by Mahmoud Al-Qudsi
Clone your HTML body two (or three) times (in javascript or otherwise). Start the page in the middle copy instead of the top, and then you can handle scrolling however you like.
克隆您的 HTML 正文两(或三)次(在 javascript 或其他方式中)。从中间副本而不是顶部开始页面,然后您可以随心所欲地处理滚动。
回答by Zecc
Building up on Mahmoud's answer, I hacked up this in a few minutes.
基于 Mahmoud 的回答,我在几分钟内解决了这个问题。
It works somewhat (at least on Firefox) when scrolling either with keys or with mouse wheel, but it gets all glitchy when dragging the scrollbar. Depending on how the div
heights relate to the viewport height, all kinds of fireworks can happen too.
当使用按键或鼠标滚轮滚动时,它有点工作(至少在 Firefox 上),但是在拖动滚动条时它会出现问题。根据div
高度与视口高度的关系,各种烟花也可能发生。
Still, I hope this can help you get on the right direction.
不过,我希望这可以帮助您找到正确的方向。
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"> </div>
<div style="height: 600px; background-color: green"> </div>
<div style="height: 600px; background-color: blue"> </div>
</body>
</html>
回答by Vincent Orback
As many have suggested, if your page doesn't look exactly the same at the top and at the bottom you'll need to clone your content to make it look like it does. I've made an example using this technique that works pretty smooth:
正如许多人所建议的那样,如果您的页面在顶部和底部看起来不完全相同,则您需要克隆您的内容以使其看起来如此。我已经使用这种技术制作了一个非常流畅的示例:
/*
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>