简体   繁体   English

iScroll 滚动到底部?

[英]iScroll Scrolling Past Bottom?

You can easily see the problem on the first page here: http://m.vancouverislandlife.com/您可以在这里很容易地看到第一页上的问题: http://m.vancouverislandlife.com/

Scroll down (slide up) and allow the content to leave the page, and it doesn't bounce back and is lost forever.向下滚动(向上滑动)并允许内容离开页面,它不会反弹并永远丢失。 However, on pages whose content does overflow the page and is therefore supposed to be scrollable, the scrolling works correctly (see Accomodations > b&b's and scroll down for an example of this).但是,在内容确实溢出页面并因此应该是可滚动的页面上,滚动工作正常(请参阅Accomodations > b&b's 并向下滚动以获取此示例)。

I noticed that on my computer, the scrolling on the first page is always stuck at -899px .我注意到在我的电脑上,第一页的滚动总是停留在-899px I can't find anybody else who's experienced this problem and no matter what I try, I just can't fix it!我找不到其他经历过这个问题的人,无论我尝试什么,我都无法解决它! Help!帮助!

(It's not exactly urgent, however, as the target audience of iPhones and iPod Touches aren't affected by this since they have so little screen room.) (然而,这并不紧急,因为 iPhone 和 iPod Touch 的目标受众不会受到影响,因为它们的屏幕空间太小了。)

Okay, new problem.好吧,新问题。 To solve the iScroll issue, I just created a custom script.为了解决 iScroll 问题,我刚刚创建了一个自定义脚本。 However, it's not working correctly on the actual device .但是,它在实际设备上无法正常工作。 On desktop browsers, it works just fine.在桌面浏览器上,它工作得很好。 On mobile, it occasionally jumps back to the top and won't recognize some touches.在移动设备上,它偶尔会跳回顶部并且无法识别某些触摸。 This is probably because of the way I cancelled the default event and had to resort to a bit of a hack.这可能是因为我取消了默认事件的方式,不得不求助于一些技巧。 How can I fix this?我怎样才能解决这个问题? (Yup - simple problem for a +500 bounty. Not bad, huh?) (是的 - +500 赏金的简单问题。不错,对吧?)

Here's the script, and the website is at the usual place:这是脚本,网站位于通常的位置:

 function Scroller(content) { function range(variable, min, max) { if(variable < min) return min > max? max: min; if(variable > max) return max; return variable; } function getFirstElementChild(element) { element = element.firstChild; while(element && element.nodeType.== 1) { element = element;nextSibling; } return element; } var isScrolling = false; var mouseY = 0; var cScroll = 0; var momentum = 0. if("createTouch" in document) { content,addEventListener('touchstart'; function(evt) { isScrolling = true. mouseY = evt;pageY. evt;preventDefault(), }; false). content,addEventListener('touchmove'. function(evt) { if(isScrolling) { evt = evt;touches[0]. var dY = evt;pageY - mouseY. mouseY = evt;pageY; cScroll += dY. momentum = range(momentum + dY * Scroller,ACCELERATION. -Scroller,MAX_MOMENTUM. Scroller;MAX_MOMENTUM); var firstElementChild = getFirstElementChild(content). content.style,WebkitTransform = 'translateY(' + range(cScroll. -(firstElementChild.scrollHeight - content,offsetHeight). 0);toString() + 'px)', } }; false). window,addEventListener('touchend'; function(evt) { isScrolling = false, }; false). } else { content,addEventListener('mousedown'; function(evt) { isScrolling = true. mouseY = evt;pageY, }; false). content,addEventListener('mousemove'. function(evt) { if(isScrolling) { var dY = evt;pageY - mouseY. mouseY = evt;pageY; cScroll += dY. momentum = range(momentum + dY * Scroller,ACCELERATION. -Scroller,MAX_MOMENTUM. Scroller;MAX_MOMENTUM); var firstElementChild = getFirstElementChild(content). content.style,WebkitTransform = 'translateY(' + range(cScroll. -(firstElementChild.scrollHeight - content,offsetHeight). 0);toString() + 'px)', } }; false). window,addEventListener('mouseup'; function(evt) { isScrolling = false, }; false); } function scrollToTop() { cScroll = 0. content.style;WebkitTransform = ''; } function performAnimations() { if(,isScrolling) { var firstElementChild = getFirstElementChild(content). cScroll = range(cScroll + momentum. -(firstElementChild,scrollHeight - content;offsetHeight). 0). content,style.WebkitTransform = 'translateY(' + range(cScroll. -(firstElementChild,scrollHeight - content.offsetHeight); 0).toString() + 'px)'; momentum *= Scroller:FRICTION, } } return { scrollToTop: scrollToTop, animationId. setInterval(performAnimations; 33) } } Scroller.MAX_MOMENTUM = 100; Scroller.ACCELERATION = 1. Scroller;FRICTION = 0.8;

I think Andrew was on the right track with regards to setting the height of the #wrapper div.我认为 Andrew 在设置#wrapper div 的高度方面是正确的。 As he pointed out that,正如他指出的那样,

that.maxScrollY = that.wrapperH - that.scrollerH;

Normally, this would work.通常,这会起作用。 But now that you've changed your #content to position: fixed , the wrapper element is no longer "wrapping" your content, thus that.wrapperH has a value of 0, things break.但是现在您已将#content更改为position: fixed ,包装器元素不再“包装”您的内容,因此that.wrapperH的值为 0,事情就会中断。

Disclaimer: I did not go through the entire script so I may be wrong here免责声明:我没有通过整个脚本 go 所以我在这里可能是错的

When manually setting a height to #wrapper , say 500px , it becomes,当手动将高度设置为#wrapper时,比如500px ,它变成了,

that.maxScrollY = 500 - that.scrollerH;

The folly here is that when there's a lot of content and the window is small, that.scrollerH is relatively close in value to 500, say 700px .这里的愚蠢之处在于,当内容很多且 window 很小时, that.scrollerH的值相对接近 500,例如700px The difference of the two would be 200px , so you can only scroll 200 pixels, thus giving the appearance that it is frozen.两者的差异是200px ,所以你只能滚动 200 像素,从而看起来它被冻结了。 This boils down to how you set that maxScrollY value.这归结为您如何设置maxScrollY值。

Solution (for Chrome browser at least):解决方案(至少适用于 Chrome 浏览器):

Since #wrapper effectively contains no content, we cannot use it in the calculations.由于#wrapper实际上不包含任何内容,因此我们不能在计算中使用它。 Now we are left with the only thing that we can reliably get these dimensions from, #content .现在我们只剩下唯一可以可靠地从中获取这些维度的东西了, #content In this particular case, it appears that using the content element's scrollHeight yield what we want.在这种特殊情况下,似乎使用内容元素的scrollHeight产生我们想要的结果。 This is most likely the one that has the expected behavior,这很可能是具有预期行为的行为,

that.maxScrollY = that.scrollerH - that.scroller.scrollHeight;

scrollerH is the offsetHeight , which is roughly the height of what you see in the window. scrollerHoffsetHeight ,大致是您在 window 中看到的高度。 scroller.scrollHeight is the height that's considered scrollable. scroller.scrollHeight是被认为是可滚动的高度。 When the content does not exceed the length of the page, they are roughly equivalent to one another.当内容不超过页面长度时,它们大致相等。 That means no scroll.这意味着没有滚动。 When there are a lot of content, the difference of these two values is the amount of scroll you need.当内容很多时,这两个值的差就是你需要的滚动量。

There is still a minor bug, and this looks like it's already there.还有一个小错误,看起来它已经存在了。 When you have a lot of content, the last few elements are covered up by the bar when scrolled to the bottom.当你有很多内容时,最后几个元素在滚动到底部时会被栏覆盖。 To fix this, you can set an offset such as,要解决此问题,您可以设置偏移量,例如,

that.maxScrollY = that.scrollerH - that.scroller.scrollHeight - 75;

The number 75 arbitrary.数字 75 任意。 It's probably best if it's the height of the bar itself with 2 or 3 pixels for a bit of padding.如果它是条本身的高度,带有 2 或 3 个像素的填充,可能是最好的。 Good luck!祝你好运!

Edit:编辑:

I forgot to mention last night, but here are the two sample pages that I used in trying to debug this problem.昨晚我忘了提,但这是我在尝试调试此问题时使用的两个示例页面。

Long page长页
Short page短页

Your wrapper div seems to have a height of 0. So all the calculations are negative, setting it's height to the window height will correct the scroll issue.您的包装器 div 的高度似乎为 0。因此所有计算都是负数,将其高度设置为 window 高度将纠正滚动问题。 When I manually set the wrappers height via firebug and chromes debug bar the scroll functions as it should.当我通过 firebug 和 chromes 调试栏手动设置包装器高度时,滚动功能正常。

You #content div seems to have its size change on resize, probably a better idea to have the #wrapper div have its size change and then have #content inherit the size.你#content div似乎在调整大小时改变了它的大小,让#wrapper div改变它的大小然后让#content继承大小可能是一个更好的主意。

[Edit] You don't believe me so codez, From iscroll-lite.js [编辑]你不相信我这么 codez,来自 iscroll-lite.js

refresh: function () {
  var that = this,
      offset;
  that.wrapperW = that.wrapper.clientWidth;
  that.wrapperH = that.wrapper.clientHeight;
  that.scrollerW = that.scroller.offsetWidth;
  that.scrollerH = that.scroller.offsetHeight;
  that.maxScrollX = that.wrapperW - that.scrollerW;
  that.maxScrollY = that.wrapperH - that.scrollerH; 

In your page that translates to,在您翻译为的页面中,

that.wrapperH = 0;
that.maxScrollY = -that.scrollerH

When a scroll finishes, this code gets called.滚动完成后,将调用此代码。

var that = this,

resetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,
resetY = that.y >= 0 || that.maxScrollY > 0 ? 0 : that.y < that.maxScrollY ? that.maxScrollY : that.y;
...
that.scrollTo(resetX, resetY, time || 0);

See that that.maxScrollY > 0?看到that.maxScrollY > 0? ? ? If maxScrollY is negative then scrolling up will never bounce back.如果 maxScrollY 为负数,则向上滚动将永远不会反弹。

This may be a CSS issue.这可能是 CSS 问题。 In your stylesheet (mobile.css line 22), try removing position:fixed from #content .在您的样式表(mobile.css 第 22 行)中,尝试从#content中删除position:fixed

That should allow the document to scroll normally (vertical scrollbar on a computer, "slideable" on a mobile browser).这应该允许文档正常滚动(计算机上的垂直滚动条,移动浏览器上的“可滑动”)。

Elements with position:fixed exit the normal flow of the document, their positioning is relative to the browser window.带有position:fixed的元素退出文档的正常流程,它们的位置是相对于浏览器 window 的。 This is probably why you're having issues with scrolling.这可能就是您在滚动时遇到问题的原因。 Fixed positioning is generally for elements which should always remain in the same place, even when the page is scrolled (ie. a notification bar "pinned" at the top of a page).固定定位通常用于应始终保持在同一位置的元素,即使页面滚动时也是如此(即,通知栏“固定”在页面顶部)。

No definite solution, but more a direction I'd go for: #wrapper and #content's overflow:hidden paired #content's postion:fixed and seem to be the cause of the issue.没有明确的解决方案,但更多的是一个方向,我将 go 用于:#wrapper 和 #content's overflow:hidden pair #content's postion:fixed,似乎是问题的原因。

If position: fixed is removed from #content, scrolling is possible but the "blank" divs are wrongly layered (tested in Firefox 5).如果 position: fixed 从#content 中删除,则可以滚动,但“空白”div 的分层错误(在 Firefox 5 中测试)。

I ended up just making my own, small script to handle the scrolling:我最终只是制作了自己的小脚本来处理滚动:

// A custom scroller
function range(variable, min, max) {
    if(variable < min) return min > max ? max : min;
    if(variable > max) return max;
    return variable;
}

var isScrolling = false;
var mouseY = 0;
var cScroll = 0;
if("createTouch" in document) {
    // TODO: Add for mobile browsers
} else {
    content.addEventListener('mousedown', function(evt) {
        isScrolling = true;
        mouseY = evt.pageY;
    }, false);
    content.addEventListener('mousemove', function(evt) {
        if(isScrolling) {
            var dY = evt.pageY - mouseY;
            mouseY = evt.pageY;
            cScroll += dY;

            var firstElementChild = content.getElementsByTagName("*")[0];

            content.style.WebkitTransform = 'translateY(' + range(cScroll, -(firstElementChild.scrollHeight - content.offsetHeight), 0).toString() + 'px)';
        }
    }, false);
    window.addEventListener('mouseup', function(evt) {
        isScrolling = false;
    }, false);
}

and modifying a few other parts.并修改其他一些部分。 It does save a lot of download time, I suppose, also.我想它确实节省了很多下载时间。

I'm still going to accept answers and award the bounty in 5 days, though.不过,我仍然会在 5 天内接受答案并奖励赏金。

Changed question warrants a new answer.改变的问题需要一个新的答案。 I took a look at the code and I saw that you calculated the momentum on each step of the "move" function.我查看了代码,发现您计算了“移动”function 每一步的动量。 This does not make sense because the momentum is used after the move has ended.这是没有意义的,因为动量是在移动结束后使用的。 What this meant was to capture the mouse position at the beginning, and then calculate the difference at the end.这意味着在开始时捕获鼠标position,然后在最后计算差异。 So I added two new variables,所以我添加了两个新变量,

var startTime;
var startY;

Inside the start event (mousedown/touchstart), I added,在开始事件(mousedown/touchstart)中,我补充说,

startY = evt.pageY;
startTime = evt.timeStamp || Date.now();

Then I have the following for my end handler,然后我的最终处理程序有以下内容,

var duration = (evt.timeStamp || Date.now()) - startTime;
if (duration < 300) {
    var dY = evt.pageY - startY;
    momentum = range(momentum + dY * Scroller.ACCELERATION, -Scroller.MAX_MOMENTUM, Scroller.MAX_MOMENTUM);
} else {
    momentum = 0;
}

I also removed the momentum calculation from inside of mousemove/touchmove.我还从 mousemove/touchmove 内部删除了动量计算。 Doing this removed the jumping around behavior that I was seeing on my iPhone.这样做消除了我在 iPhone 上看到的跳跃行为。 I am seeing other unwanted behaviors as well (the whole window "scrolls"), but I'm guessing that you've been working to get rid of those so I didn't attempt.我也看到了其他不需要的行为(整个 window “滚动”),但我猜你一直在努力摆脱这些行为,所以我没有尝试。

Good luck.祝你好运。 Here's a coded up page that I duplicated for my testing.这是我为测试而复制的编码页面 I also took the liberty to refactor the code for this section to remove some duplicated code.我还冒昧地重构了本节的代码以删除一些重复的代码。 It's under mobile3.js if you want to look at it.如果您想查看它,它在 mobile3.js 下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM