3

您可以在这里轻松地在第一页上看到问题:http: //m.vancouverislandlife.com/

向下滚动(向上滑动)并允许内容离开页面,它不会反弹并永远丢失。但是,在内容确实溢出页面并因此应该是可滚动的页面上,滚动工作正常(请参阅Accomodations > 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;
4

6 回答 6

4

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

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

通常,这会起作用。但是现在你已经改变了#contentto position: fixed,包装元素不再“包装”你的内容,因此that.wrapperH它的值为 0,事情就会中断。

免责声明:我没有通读整个脚本,所以我在这里可能是错的

当手动将高度设置为 时#wrapper500px它变成,

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 个像素的填充,可能是最好的。祝你好运!

编辑:

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

长页
短页

于 2011-08-25T06:26:53.687 回答
1

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

如果 position: fixed 从#content 中删除,滚动是可能的,但“空白”的 div 被错误地分层(在 Firefox 5 中测试)。

于 2011-08-23T20:04:37.690 回答
1

您的包装器 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 为负数,则向上滚动将永远不会反弹。

于 2011-08-23T19:28:58.447 回答
1

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

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

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

于 2011-08-23T19:42:40.357 回答
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 上看到的跳跃行为。我也看到了其他不需要的行为(整个窗口“滚动”),但我猜你一直在努力摆脱这些行为,所以我没有尝试。

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

于 2011-08-31T06:28:44.087 回答
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 天内接受答案并奖励赏金。

于 2011-08-25T21:35:44.427 回答