iScroll滚动过去的底部?

时间:2011-08-15 23:22:45

标签: javascript xhtml mobile-website iscroll4

您可以在此处的第一页轻松查看问题: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;

6 个答案:

答案 0 :(得分:4)

我认为安德鲁在设置#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像素的一点填充。祝你好运!

编辑:

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

Long page
Short page

答案 1 :(得分:1)

你的包装div似乎高度为0.所以所有的计算都是负数,将它的高度设置为窗口高度将纠正滚动问题。当我通过firebug和chromes调试条手动设置包装器高度时,滚动按原样运行。

你#content div似乎在调整大小时会改变它的大小,可能更好的想法让#wrapper div改变它的大小,然后让#content继承大小。

<强> [编辑] 你不相信我这么编码,来自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为负数,则向上滚动永远不会反弹。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

没有明确的解决方案,但更多的方向我会去: #wrapper和#content的溢出:隐藏配对#content的位置:固定并且似乎是问题的原因。

如果从#content中移除了position:fixed,则可以滚动,但“blank”divs错误地分层(在Firefox 5中测试)。

答案 4 :(得分:0)

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

// 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天内接受答案并奖励赏金。

答案 5 :(得分:0)

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

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上看到的跳跃行为。我也看到了其他不受欢迎的行为(整个窗口“滚动”),但我猜你一直在努力摆脱那些,所以我没有尝试。

祝你好运。这是我为我的测试重复的coded up page。我还冒昧地重构了本节的代码,以删除一些重复的代码。如果你想查看它,它在mobile3.js下。