0

编辑:

我弄清楚了问题的原因。当您使用滚动条滚动,然后以编程方式设置滚动时,滚动条会移动,这会导致浏览器根据鼠标相对于新滚动条位置的位置重新计算滚动位置。现在我正在寻找解决方案。 是使用来自以下答案之一的代码的问题的 Youtube 视频。

原帖:

我试图实现窗口以等于网格中元素大小的增量滚动的效果,以便滚动看起来平滑。元素是 40px 正方形,有 4px 的填充,所以我试图以 44px 的增量滚动页面。我写了一些代码,当页面垂直滚动时效果很好。我已经为水平滚动设置了完全相同的操作(或者我认为),但是当我水平滚动时,页面来回抖动。我已经尝试过调试它,似乎每隔一秒或第三次调用滚动处理程序时,向左滚动的窗口就会被设置为一些看似随机的值。

这是代码(和小提琴):

$(function(){

    // Here is the scroll function in question

    $(window).scroll(function(){

        var lastScrollTop = $(window).scrollTop();
        var lastScrollLeft = $(window).scrollLeft();

        return function(){
            var scrollTop = $(this).scrollTop();
            var scrollLeft = $(this).scrollLeft();
            var yDir = scrollTop - lastScrollTop > 0 ? 1 : -1;
            var xDir = scrollLeft - lastScrollLeft > 0 ? 1 : -1;
            $(this).scrollTop(~yDir ? scrollTop + ((44 - ((scrollTop + 44) % 44))) : scrollTop - (scrollTop % 44));
            $(this).scrollLeft(~xDir ? scrollLeft + ((44 - ((scrollLeft + 44) % 44))) : scrollLeft - (scrollLeft % 44));
            scrollTop = lastScrollTop = $(this).scrollTop();
            scrollLeft = lastScrollLeft = $(this).scrollLeft();
        }
    }());
});

编辑:

我正在 Chrome 26.0.1410.65 btw 中对此进行测试。

编辑:

垂直滚动也会出现问题,但仅在使用滚动条而不是鼠标滚轮时才会出现。

4

2 回答 2

0

在某些情况下scrollTop - lastScrollTopscrollLeft - lastScrollLeft 为零并且会导致您的逻辑出现问题。

看到这两行

var yDir = scrollTop - lastScrollTop > 0 ? 1 : -1;
var xDir = scrollLeft - lastScrollLeft > 0 ? 1 : -1;

假设差异大于 0,您的xDir变量将具有 1,并且您将 scrollLeft 设置为scrollTop + ((44 - ((scrollTop + 44) % 44))

下一次迭代差异为 0,您的xDir变量将具有 -1,您现在将使用 scrollLeft - (scrollLeft % 44)). 即使滚动位置没有改变,这两个等式的计算结果也不相同。

试试这个。

$(function(){

    // Here is the scroll function in question

    $(window).scroll(function(){

        var lastScrollLeft = $(window).scrollLeft();
        var lastScrollTop = $(window).scrollTop();

        return function(){
            var scrollLeft = $(this).scrollLeft();
            var scrollTop = $(this).scrollTop();

            if (lastScrollLeft !== scrollLeft) {
                lastScrollLeft = scrollLeft - (scrollLeft % 44);
                $(this).scrollLeft(lastScrollLeft);               
            } 

            if (lastScrollTop !== scrollTop) {
                lastScrollTop = scrollTop - (scrollTop % 44);
                $(this).scrollTop(lastScrollTop);   
            }

       }
    }());

    // Generates the grid, ignore this part

    for(var i=0;i<50;i++){
        var row = $('<div></div>').addClass('row').appendTo('body');
        for(var j=0; j<50; j++)
            $('<span></span>').appendTo(row).addClass('cell').text(50*i+j);
    }
});
于 2013-04-19T19:05:09.630 回答
0

因此,根据问题顶部所述的问题原因,我认为使用代码中的方法无法直接解决此问题。我最终使用的解决方案是实现一种虚拟滚动。我将要滚动的元素放入“视口”div 中,固定位置填充窗口区域。然后我使用'scrollTarget' div 扩展了窗口大小,并根据窗口的滚动位置以44 为增量滚动视口。看到这个小提琴

Javascript

$(function(){

    // Here is the scroll function in question

    $(this).scroll(function(){
        var scrollTop = $(this).scrollTop();
        var scrollLeft = $(this).scrollLeft();
        $('#viewport').scrollTop(scrollTop - (scrollTop % 44));
        $('#viewport').scrollLeft(scrollLeft - (scrollLeft % 44));
    });


    // Generates the grid, ignore this part

    for(var i=0;i<50;i++){
        var row = $('<div></div>').addClass('row').appendTo('#viewport');
        for(var j=0; j<50; j++)
            $('<span></span>').appendTo(row).addClass('cell').text(50*i+j);
    }

    $('#scrollTarget').height((50 * 44) + 48)
        .width((50 * 44) + 48);
});

HTML

<div id="viewport"></div>
<div id="scrollTarget"></div>

CSS

#viewport{
    position:fixed;
    height:100%;
    width:100%;
    overflow:hidden;
}

#scrollTarget{
    position:absolute;
}

.row{
    height:44px;
    width:2204px;
}

.row:first-child{
    height:40px;
}

.cell{
    display:inline-block;
    height:40px;
    width:40px;
    margin-top:4px;
    margin-right:4px;
    background-color:#859DE1;
    color:#0F1219;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    border-radius: 5px;
}

.row:first-child .cell{
    margin-top:0px;
}
于 2013-04-19T20:20:42.713 回答