2014-01-06 5 views
2

У меня есть следующий HTML-дизайн с 4 Divs, как показано на диаграмме.Прокрутка JQuery() слишком медленная

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

Мое требование заключается в том

  1. когда я прокручиваю scrollBody горизонтально scrollHead должен двигаться по горизонтали.
  2. когда я прокручиваю scrollBody вертикально фиксированныйBody должен двигаться вертикально.

Я могу добиться этого, выполнив следующий код, но если таблицы очень большие около 100 столбцов и 100 строк Это становится очень медленным

Есть ли еще более быстрый способ достижения этой

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

медленным, вы имеете в виду это занимает слишком много времени, чтобы оценить это выражение? Сколько времени это занимает? Кроме того, вы могли бы привести пример (например, с помощью JSFiddle)? Трудно себе представить ... –

+0

@CedricReichenbach Мое предположение заключалось в том, что фактическая прокрутка была слишком медленной. –

+0

Вы имеете в виду анимацию? –

ответ

0

Если я правильно понимаю, это должно сделать анимацию последние 100 мс:

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

Так что было бы быстрее анимировать прокрутку, чем просто делать это с помощью нет анимации? – adeneo

+0

Нет, но более плавный ...: P Но я думаю, что я вас неправильно понял, я думал, что вы сражаетесь с некоторыми анимациями по умолчанию. –

+0

Я думаю, что на самом деле это скорее замедлит его: с анимацией jQuery, DOM будет изменяться только в несколько раз, чем сейчас, что, как я подозреваю, является узким местом производительности. – Barney

2

Проблема заключается в том, что событие scroll может происходить очень часто - десятки раз в секунду - и браузер часто будет в конечном итоге перемещать элементы чаще, чем это необходимо.

Обычным решением проблемы такого рода является «дроссельный»:

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

В приведенном выше примере используется Бен Alman-х jQuery throttle/debounce plugin, и в основном означает, что функция не будет выполняться более одного раза каждые 100 миллисекунд - вы может изменить эту цифру, чтобы попытаться найти счастливую отзывчивую среду.

+0

Мне кажется, что я вижу некоторое улучшение, и я играю с фигурой, но все же прокрутка кажется вроде медленной и застрявшей порой –

+0

Возможно, лучше отказаться от ручного дросселирования в пользу более поздних событий. [Я предложил новое решение] (http://stackoverflow.com/questions/20953439/jquery-scroll-too-slow/21050741#21050741), который использует 'requestAnimationFrame' и CSS3' transform' для уменьшения давления на основной нить. – Barney

0

Вы можете быть в состоянии использовать requestAnimationFrame (с пользовательским дросселированием) для предотвращения блокировки и экономии времени картины с репозицией с помощью смещения 3D преобразований вместо модификации scrollLeft и scrollTop.

Код, который я написал, плохо воспроизводился с jsFiddle или jsBin (что немного беспокоит), но работало нормально локально. Таблица довольно большая по размеру, но не содержит очень сложную DOM (каждый элемент содержит только текстовый узел), поэтому его производительность может быть не показательной.

Смотрите, если это работает для вас (Gist) ...

Поток работает следующим образом:

  • Bind scroll событие тела табличной функции, которая запрашивает кадр анимации (а не сразу исполнения) , если мы уже не ожидаем запроса. Запрос кадра анимации означает, что код будет выполняться так же, как и когда браузер имеет перекраску, вместо того, чтобы заставить ее действовать немедленно, а это значит, что он не будет блокировать какой-либо другой код.
  • Когда рамка анимации станет доступной, проверьте смещение каждой оси, чтобы увидеть, изменилось ли оно с последнего раза. Если это так, примените смещение как отрицательное значение перевода на этой оси. Преобразование лучше, чем смещение прокрутки для времени рисования, так как не нужно пересчитывать любой макет CSS: он просто перемещает существующий рендеринг элемента DOM. 3D-перевод еще лучше, поскольку на некоторых системах он может компенсировать всю картину отдельным потоком (графическим процессором), еще больше освобождая основной процессор.

Ключевые элементы кода ниже:

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); 
     } 
    }); 
}(); 
+0

Спасибо, Барни .. Извините, я не смог войти и проверить ваш ответ. Причина заключалась в том, что тот же код был чрезвычайно быстрым с IE10, и клиент отказался от использования только IE10. Но я буду проверять ваше решение и обновить вас. Еще раз спасибо за то, что нашли время и силы –

Смежные вопросы