0

編集:

問題の原因がわかりました。スクロールバーでスクロールし、プログラムでスクロールを設定すると、スクロールバーが移動し、ブラウザは新しいスクロールバーの位置に対するマウスの位置に基づいてスクロール位置を再計算します。今、私は解決策を探しています。 これは、以下の回答のいずれかからのコードを使用した問題の Youtube ビデオです。

元の投稿:

スクロールがスムーズに見えるように、ウィンドウがグリッド内の要素のサイズに等しい増分でスクロールする効果を達成しようとしています。要素は 40 ピクセルの正方形で、4 ピクセルのパディングがあるため、ページを 44 ピクセルずつスクロールしようとしています。私はいくつかのコードを書きましたが、ページが垂直方向にスクロールするときにうまく機能します。水平スクロール用にまったく同じ操作 (またはそう思う) をセットアップしましたが、水平スクロールすると、ページが前後に揺れます。私はそれをデバッグしようとしましたが、スクロールハンドラーが呼び出されるたびに、ウィンドウの左スクロールが一見ランダムな値に設定されるようです。

ここにコード(およびフィドル)があります:

$(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 がゼロで、ロジックに問題を引き起こして いる場合があります。

これらの2行を参照してください

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))。これらの 2 つの式は、スクロール位置が変更されていない場合でも同じには評価されません。

これを試して。

$(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

したがって、質問の上部に記載されている問題の原因に基づいて、コード内のメソッドを使用してこの問題を直接解決する方法はないと思います。私が最終的に使用した解決策は、一種の仮想スクロールを実装することでした。スクロールする要素を「viewport」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 に答える