Подтвердить что ты не робот

Сконфигурировать панель прокрутки для прокрутки div

У меня есть веб-страница с тремя 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 есть полосы прокрутки, как горизонтальные, так и вертикальные. Верхний и левый divs не имеют полос прокрутки. Вместо этого, когда перемещается горизонтальная полоса прокрутки, событие прокрутки обновляет верхний 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 существует задержка между перемещением полосы прокрутки и заданного отрицательного поля.

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

EDIT:

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

4b9b3361

Ответ 1

Сообщите мне, если этот 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. Это улучшает рендеринг в браузере, что, возможно, было проблемой при задержке.

Ответ 2

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

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

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

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

Это означает, что сначала нужно выяснить правильный префикс для свойства преобразования CSS, а затем проверить поддержку 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';
    }
}

FIDDLE

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

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

Ответ 3

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

Изменение:

$('.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)); });

})();

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


Но поскольку я вижу, что .sidebar-wrapper и .topbar-wrapper уникальны, mabye.center-wrapper тоже уникален.

Итак, как насчет окончательного использования 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;
    }; 

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


Ответ 4

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

Демо-скрипт

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

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