iScroll 滚动到底部吗?

发布于 2024-11-29 11:25:30 字数 3745 浏览 2 评论 0原文

您可以在此处轻松查看第一页上的问题:http://m.vancouverislandlife.com/

向下滚动(向上滑动)并允许内容离开页面,并且不会反弹并永远丢失。但是,在内容确实溢出页面并因此应该可滚动的页面上,滚动可以正常工作(请参阅住宿> b&b's 并向下滚动以获取相关示例)。

我注意到在我的计算机上,第一页上的滚动始终停留在 -899px 处。我找不到其他经历过此问题的人,无论我尝试什么,我都无法解决它!帮助!

(不过,这并不紧急,因为 iPhone 和 iPod Touch 的目标受众不会受到此影响,因为它们的屏幕空间很小。)

好吧,新问题。为了解决 iScroll 问题,我刚刚创建了一个自定义脚本。但是,它在实际设备上无法正常工作。在桌面浏览器上,它运行得很好。在移动设备上,它偶尔会跳回顶部并且无法识别某些触摸。这可能是因为我取消了默认事件并且不得不采取一些黑客措施。我该如何解决这个问题? (是的 - +500 赏金的简单问题。不错吧?)

这是脚本,网站位于通常的位置:

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;

You can easily see the problem on the first page here: 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).

I noticed that on my computer, the scrolling on the first page is always stuck at -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.)

Okay, new problem. To solve the iScroll issue, I just created a custom script. 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?)

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

遇到 2024-12-06 11:25:30

我认为 Andrew 在设置 #wrapper div 的高度方面是正确的。正如他指出的那样,

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

通常情况下,这是可行的。但现在您已将 #content 更改为 position:fixed,包装器元素不再“包装”您的内容,因此 that.wrapperH 的值为 0,事情就会中断。

免责声明:我没有浏览整个脚本,因此这里可能是错误的

当手动设置 #wrapper 的高度时,请说 500px,就变成了,

that.maxScrollY = 500 - that.scrollerH;

这里的愚蠢之处在于,当内容很多且窗口很小时,that.scrollerH 的值相对接近 500,比如 700px< /代码>。两者的差异为 200px,因此您只能滚动 200 像素,从而使其看起来像是冻结的。这归结为您如何设置 maxScrollY 值。

解决方案(至少对于 Chrome 浏览器):

由于 #wrapper 实际上不包含任何内容,因此我们无法在计算中使用它。现在我们只剩下唯一可以可靠地从中获取这些维度的东西了,#content。在这种特殊情况下,使用内容元素的 scrollHeight 似乎可以产生我们想要的效果。这很可能具有预期的行为,

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

scrollerHoffsetHeight,它大致是您在窗口中看到的高度。 scroller.scrollHeight 是被认为可滚动的高度。当内容不超过页面长度时,它们大致相当。这意味着没有滚动。当内容很多时,这两个值的差就是你需要的滚动量。

还有一个小错误,看起来它已经存在了。当您有很多内容时,滚动到底部时最后几个元素会被栏覆盖。要解决此问题,您可以设置一个偏移量,例如

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

任意数字 75。如果它是条本身的高度,并带有 2 或 3 个像素作为一点填充,那可能是最好的。祝你好运!

编辑:

我昨晚忘了提及,但这是我在尝试调试此问题时使用的两个示例页面。

长页面
短页

I think Andrew was on the right track with regards to setting the height of the #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.

Disclaimer: I did not go through the entire script so I may be wrong here

When manually setting a height to #wrapper, say 500px, it becomes,

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. The difference of the two would be 200px, so you can only scroll 200 pixels, thus giving the appearance that it is frozen. This boils down to how you set that maxScrollY value.

Solution (for Chrome browser at least):

Since #wrapper effectively contains no content, we cannot use it in the calculations. Now we are left with the only thing that we can reliably get these dimensions from, #content. In this particular case, it appears that using the content element's scrollHeight yield what we want. 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. scroller.scrollHeight is the height that's considered scrollable. 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. It's probably best if it's the height of the bar itself with 2 or 3 pixels for a bit of padding. 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

微暖i 2024-12-06 11:25:30

这可能是 CSS 问题。在样式表(mobile.css 第 22 行)中,尝试从 #content 中删除 position:fixed

这应该允许文档正常滚动(计算机上的垂直滚动条,移动浏览器上的“可滑动”)。

position:fixed 的元素退出文档的正常流程,它们的定位是相对于浏览器窗口的。这可能就是您遇到滚动问题的原因。固定定位通常适用于即使页面滚动也应始终保持在同一位置的元素(即“固定”在页面顶部的通知栏)。

This may be a CSS issue. In your stylesheet (mobile.css line 22), try removing position:fixed from #content.

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. 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).

吻安 2024-12-06 11:25:30

没有明确的解决方案,但更多的是我想要的方向:
#wrapper 和#content 的overflow:hidden 与#content 的postion:fixed 配对,似乎是问题的原因。

如果从 #content 中删除了position:fixed,则可以进行滚动,但“空白”div 的分层错误(在 Firefox 5 中测试)。

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.

If position: fixed is removed from #content, scrolling is possible but the "blank" divs are wrongly layered (tested in Firefox 5).

等待我真够勒 2024-12-06 11:25:30

您的包装器 div 的高度似乎为 0。因此所有计算都是负数,将其高度设置为窗口高度将纠正滚动问题。当我通过 firebug 和 chromes 调试栏手动设置包装器高度时,滚动功能按其应有的方式运行。

#content div 的大小似乎在调整大小时发生了变化,可能更好的主意是让 #wrapper div 的大小发生变化,然后让 #content 继承该大小。

[编辑]
你不相信我,所以 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; 

在你的页面中翻译为,

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

当滚动完成时,此代码被调用。

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);

看到 that.maxScrollY > 0??如果 maxScrollY 为负数,则向上滚动将永远反弹。

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. When I manually set the wrappers height via firebug and chromes debug bar the scroll functions as it should.

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.

[Edit]
You don't believe me so codez, From 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 ? ? If maxScrollY is negative then scrolling up will never bounce back.

同展鸳鸯锦 2024-12-06 11:25:30

我最终只是制作了自己的小脚本来处理滚动:

// 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);
}

并修改了其他一些部分。我想,它确实也节省了大量的下载时间。

不过,我仍然会接受答案并在 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.

生生不灭 2024-12-06 11:25:30

改变的问题需要新的答案。我查看了代码,发现您计算了“移动”函数每一步的动量。这是没有意义的,因为动量是在移动结束后使用的。这意味着在开始时捕获鼠标位置,然后在结束时计算差异。所以我添加了两个新变量,

var startTime;
var startY;

在开始事件(mousedown/touchstart)内,我添加了,

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

然后我的结束处理程序有以下内容,

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;
}

我还从 mousemove/touchmove 内部删除了动量计算。这样做消除了我在 iPhone 上看到的跳跃行为。我还看到其他不需要的行为(整个窗口“滚动”),但我猜您一直在努力消除这些行为,所以我没有尝试。

祝你好运。这是我为测试而复制的编码页面。我还冒昧地重构了本节的代码,删除了一些重复的代码。如果你想查看的话,它位于 mobile3.js 下。

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. 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. So I added two new variables,

var startTime;
var startY;

Inside the start event (mousedown/touchstart), I added,

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. Doing this removed the jumping around behavior that I was seeing on my 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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文