JQuery scroll()太慢了

时间:2014-01-06 15:37:12

标签: javascript jquery html scroll

我有以下HTML设计,有4个Div,如图所示。

--------------------------
 fixedHead  |  scrollHead
--------------------------
 fixedBody  |  scrollBody
--------------------------

我的要求是

  1. 当我滚动scrollBody时,scrollHead应该移动 水平。
  2. 当我滚动scrollBody垂直fixedTody应该     垂直移动。
  3. 我能够通过执行以下代码来实现这一点,但是如果表格在100列和100行之间非常大 这变得很慢

    还有其他更快的方法来实现这个

    $('.scrollBody').scroll(function() {
        $('.fixedBody').scrollTop($(this).scrollTop()); 
        $(".scrollHead").scrollLeft($(this).scrollLeft());   
    });
    

3 个答案:

答案 0 :(得分:2)

问题在于scroll事件可能经常发生 - 每秒数十次 - 并且浏览器通常最终会重新定位元素而不是严格必要的。

这种问题的一个常见解决方案是“限制”:

$('.scrollBody').scroll( $.throttle( 100, function() {
    $('.fixedBody').scrollTop($(this).scrollTop()); 
    $(".scrollHead").scrollLeft($(this).scrollLeft());   
} ) );

上面的示例使用Ben Alman的jQuery throttle / debounce plugin,基本上意味着该函数每100毫秒不会执行多次 - 您可以更改该数字以尝试找到一个快乐的响应媒体。

答案 1 :(得分:0)

如果我理解正确,这应该使动画持续100毫秒:

var duration = 100;
$('.scrollBody').scroll(function()
    $('.fixedBody').animate({ scrollTop: $(this).scrollTop() }, duration);
    $(".scrollHead").animate({ scrollLeft: $(this).scrollLeft() }, duration);
});

答案 2 :(得分:0)

您可以利用requestAnimationFrame(使用自定义限制)来阻止锁定,并通过使用3D变换偏移重新定位来节省绘画时间,而不是修改scrollLeftscrollTop

我写的代码与jsFiddle或jsBin(这有点令人担忧)不太合适,但在本地工作得很好。该表的大小相当大,但不包含非常复杂的DOM(每个元素只包含一个文本节点),因此其性能可能并不具有指示性。

看看这是否适合您(Gist)...

流程如下:

  • 将表体的scroll事件绑定到请求动画帧(而不是立即执行)的函数,除非我们已经在等待请求。请求动画帧意味着代码将在浏览器重新绘制时执行,而不是强制它立即执行,这意味着它不会阻止任何其他代码。
  • 当动画帧可用时,检查每个轴的偏移量以查看自上次以来它是否已更改。如果有,则将偏移应用为该轴上的负平移值。变换比绘制时间的滚动偏移更好,因为它不需要重新计算任何布局CSS:它只是移动DOM元素的现有渲染。 3D翻译甚至更好,因为在某些系统上它可以将所有绘画偏移到单独的线程(GPU),从而更多地释放主CPU进程。

代码的关键元素如下:

var $scrollBody = $( '.scrollBody' );
var $fixedBody  = $( '.fixedBody' );
var $scrollHead = $( '.scrollHead' );

void function persistScrollState(){
    var previousOffset = {
        x : 0,
        y : 0
    };
    var pendingScroll  = false;

    function persistScroll(){
        var offset = {
            x: -$scrollBody.scrollLeft(),
            y: -$scrollBody.scrollTop()
        };

        if( offset.x !== previousOffset.x ){
            $scrollHead.css( { transform : 'translateX( ' + offset.x + 'px ) translateZ( 0px )' } );
        }
        if( offset.y !== previousOffset.y ){
            $fixedBody.css(  { transform : 'translateY( ' + offset.y + 'px ) translateZ( 0px )' } );
        }

        previousOffset = offset;
        pendingScroll  = false;
    }

    $scrollBody.on( 'scroll', function handleScroll() {    
        // requestAnimationFrame to avoid resource hogging:
        // https://gist.github.com/paulirish/1579671
        // Use polyfill for non-supporting browsers:
        // https://gist.github.com/paulirish/1579671

        if( !pendingScroll ){
            pendingScroll = requestAnimationFrame( persistScroll );
        }
    } );
}();