Синхронизация прокрутки div, чтобы не прокручивать див



У меня есть веб-страница с тремя дивами, которые синхронизируются вместе.

    +----------+
    |   TOP    |
+---+----------+
|   |         ||
| L | CENTER  ||
|   |_________||
+---+----------+

<!--Rough HTML-->
<div>
  <div class="topbar-wrapper">
    <div class="topbar"></div>
  </div>
  <div class="container">
    <div class="sidebar-wrapper">
      <div class="sidebar"></div>
    </div>
    <div class="center-wrapper"> <!-- Set to the window size & overflow:scroll -->
      <div class="center"></div> <!-- Has the content -->
    </div>
  </div>
</div>
Центральный div имеет полосы прокрутки, как горизонтальные, так и вертикальные. Верхний и левый дивы не имеют полос прокрутки. Вместо этого, когда горизонтальная полоса прокрутки перемещается, событие прокрутки обновляет верхний div margin-left соответствующим образом. Аналогично, когда вертикальная полоса прокрутки перемещается, margin-top обновляется. В обоих случаях они имеют отрицательное значение.
$('.center-wrapper').scroll(function(e) {
  $('.sidebar').css({marginTop: -1 * $(this).scrollTop()});
  $('.topbar').css({marginLeft: -1 * $(this).scrollLeft()});
});

Это прекрасно работает в Chrome и Firefox. Но в сафари, существует задержка между перемещением полосы прокрутки и правильной установкой отрицательного поля.

Есть ли лучший способ сделать это? Или есть какой-то способ избавиться от отставания в сафари?

Правка:

Проверьте эту скрипку, чтобы увидеть отставание в Safari: http://jsfiddle.net/qh2K3/

134   4  

4 ответов:

Дайте мне знать, еслиЭтот JSFiddle работает лучше. Я тоже испытал такое же "отставание" на своем конце (Safari 7 на OS X), и эти небольшие изменения CSS значительно улучшили его. Моя лучшая догадка заключается в том, что Safari ленив и не включил свои высокопроизводительные двигатели. Мы можем заставить Safari включить его, используя простой CSS:

.topbar-wrapper, .sidebar-wrapper, .center-wrapper {
    -webkit-transform: translateZ(0);
    -webkit-backface-visibility: hidden;
    -webkit-perspective: 1000;
}

Это позволяетаппаратно ускорить CSS в Safari, выгрузив часть работы на GPU. Это улучшает визуализацию в браузере, что, возможно, и было причиной задержки.

У меня была эта проблема несколько раз, когда safari, кажется, отстает при постепенном перемещении элементов, основанных на событиях, подобных этому.

Вот как я решал эту проблему в прошлом.

В браузерах, поддерживающих аппаратное ускорение, использование любого свойства CSS "3d"позволит включить аппаратное ускорение.

Если 3D-преобразования поддерживаются, мы можем также использовать translate3d для перемещения элементов, так как это делает движения более плавными, чем перемещение пикселей.

Это означает, что мы сначала нужно определить правильный префикс для свойства CSS transform, а затем проверить поддержку 3D-преобразований. Если у нас есть поддержка, переводите элементы, если нет сдвига пикселей.

Выясняя префиксы и поддержку 3D без библиотек, он должен быть настолько быстр, насколько это возможно, и не имеет зависимостей.

var parent     = document.querySelector('.center-wrapper'),
    sidebar    = document.querySelector('.sidebar'),
    topbar     = document.querySelector('.topbar'),
    has3D      = false,
    transform  = null,
    transforms = {
            'webkitTransform' : '-webkit-transform',
            'OTransform'      : '-o-transform',
            'msTransform'     : '-ms-transform',
            'MozTransform'    : '-moz-transform',
            'transform'       : 'transform'
    };

for (var k in transforms) if (k in parent.style) transform = k;

if ( transform !== null ) {
    sidebar.style[transform] = 'translate3d(0,0,0)'; // start hardware acc
    topbar.style[transform]  = 'translate3d(0,0,0)'; // start hardware acc
    // check support
    var s = window.getComputedStyle(sidebar).getPropertyValue(transforms[transform]);
    has3D = s !== undefined && s.length > 0 && s !== "none";
}

if (has3D) {
    parent.onscroll = function (e) {
        sidebar.style[transform] = 'translate3d(0px, '+ (this.scrollTop * -1) +'px, 0px)';
        topbar.style[transform]  = 'translate3d('+ (this.scrollLeft * -1) +'px, 0px, 0px)';
    }
}else{
    parent.onscroll = function (e) {
        sidebar.style.marginTop = (this.scrollTop  * -1) + 'px';
        topbar.style.marginLeft = (this.scrollLeft * -1) + 'px';
    }
}

Скрипка

Не забудьте поставить это после элементов в DOM, как в прямо перед </body>, или если это невозможно, это должно быть завернутый в обработчик DOM ready.

В качестве боковой заметки querySelector не поддерживается в IE7 и ниже,если это проблема, вы должны заполнить ее.

Селекторы кэширования помогут.

Изменение:

$('.center-wrapper').scroll(function(e) {
  $('.sidebar').css({marginTop: -1 * $(this).scrollTop()});
  $('.topbar').css({marginLeft: -1 * $(this).scrollLeft()});
});

Кому:

var _scroller = $('.center-wrapper'),
    _swrapper = $('.sidebar-wrapper'),
    _twrapper = $('.topbar-wrapper');

_scroller.scroll(function (e) {
    _swrapper.scrollTop(_scroller.scrollTop());
    _twrapper.scrollLeft(_scroller.scrollLeft());
});

.scroll() будет очень тяжело работать, если ему придется каждый раз воссоздавать объекты jquery $(this).

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

Мы можем попробовать его - здесь


Еще / Методы-делая их тоже родными

Есть также другие вызовы метода jquery, которые мы тоже можем вырезать. .scrollTop() и .scrollLeft() путем кэширования и возврата собственного _scrollernative = _scroller.get(0), чтобы использовать легкодоступные свойства scrollLeft.

Например:

var _scroller = $('.center-wrapper'),
    _scrollernative = _scroller.get(0),
    _swrapper = $('.sidebar-wrapper').get(0),
    _twrapper = $('.topbar-wrapper').get(0);

_scroller.scroll(function (e) {
    _swrapper.scrollTop = _scrollernative.scrollTop;
    _twrapper.scrollLeft = _scrollernative.scrollLeft;
});

Мы можем попробовать это здесь



Я понимаю, что ваш код может смотреть на более чем один из этих элементов управления на странице, и именно поэтому вы использовали классы и необходимость найти S(this) вместо использования идентификаторов.

Для этого я бы все еще использовал вышеупомянутые методы кэширования, но перед этим нам нужно создать их один за другим. (кэширование перед инициализацией функции scroll () для каждого экземпляра)

(function() {
    var _scroller = $('.center-wrapper'),
    _swrapper = $('.sidebar-wrapper').get(0),
    _twrapper = $('.topbar-wrapper').get(0);

    function setScrollers(_thisscroller) {
        _scrollernative = _thisscroller.get(0);
        /* start the scroll listener per this event */
        _thisscroller.scroll(function (e) {
            _swrapper.scrollTop = _scrollernative.scrollTop;
            _twrapper.scrollLeft = _scrollernative.scrollLeft;
        }); 
    }

    _scroller.each(function() { setScrollers($(this)); });

})();

Мы можем попробовать это здесь


Но как я это вижу .панели-оболочки и .верхней панели-оболочки являются уникальными, возможно .центр-обертка тоже уникальна.

Так как насчет того, чтобы, наконец, использовать id для этих элементов, чтобы сократить все вверх.

var _scroller = document.getElementById('center-wrapper'),
    _swrapper = document.getElementById('sidebar-wrapper'),
    _twrapper = document.getElementById('topbar-wrapper');

    _scroller.onscroll = function() {
      _swrapper.scrollTop = _scroller.scrollTop;
      _twrapper.scrollLeft = _scroller.scrollLeft;
    }; 

Мы можем попробовать это здесь


Вместо того, чтобы использовать marginTop & marginLeft для изменения полей .sidebar & .topbar Используйте scrollTop & scrollLeft для переполненных дивов .sidebar-wrapper & .topbar-wrapper и посмотрите, работает ли он теперь в Safari :

Демо-Скрипка

$('.center-wrapper').scroll(function(e) {
   $('.sidebar-wrapper').scrollTop($(this).scrollTop());
   $('.topbar-wrapper').scrollLeft($(this).scrollLeft());
});

Попробуйте эту скрипку, сделанную для смотри лучше всех в сафари и проверено

    Ничего не найдено.

Добавить ответ:
Отменить.