2013-03-08 4 views
6

Мне нужно сохранить смещение прокрутки элемента в синхронизации с другим (фактически на самом деле), и у меня возникают проблемы с этим во время инерциальной фазы «свернуть» прокрутки на Mobile Safari (iPad).Как синхронизировать смещение прокрутки двух элементов во время инерционной прокрутки

У меня есть несколько дивы с position:fixed; overflow:hidden и мне нужно, чтобы держать их свиток смещение в синхронизации с одним окна Обычно я его код, как это (JQuery) (то есть весь свиток тела.):

var $win = $(window), 
    $div1 = $(...) 

$win.scroll(function() { 
    $div1.scrollTop($win.scrollTop()) 
}) 

Но, тестируя интерфейс на iPad, я заметил, что div не обновлялся ни во время сенсорной фазы, когда вы перетаскиваете виртуальную страницу пальцем, так и во время инерциальной фазы, когда вы отпускаете страницу замедляется до остановки.

Я решил это для фазы перетаскивания, зарегистрировав обработчик для события touchmove, а также scroll.

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

Here's a working demo.

Попробуйте прокрутить его на IPad, чтобы увидеть "инерционный scolling" проблемы. К сожалению, я не мог заставить его работать на jsFiddle, из-за странного поведения iPad с прокруткой iframe.

Если бы я мог просто запустить опрос на этом этапе, я мог бы сохранить видимость синхронизации между двумя элементами. Я пробовал с setTimeout, setInterval и requestAnimationFrame, но ни один из них не срабатывает во время фазы инерциальной прокрутки. Кажется, что все Javascript останавливаются на этом этапе.

Вопросы:

  • Есть ли прикосновение или свиток событие выстрелило во инерциальной фазе прокрутки?
  • Есть ли какой-либо способ запустить обратный вызов Javascript на этом этапе?
  • Есть ли способ синхронизировать смещение прокрутки двух элементов (либо X, либо Y, а не обоих) с использованием CSS или другой технологии, отличной от JS?
+0

Было бы целесообразным добавить элементы div в качестве дочерних элементов в слой прокрутки? –

+0

Что вы подразумеваете под словом «прокрутки»? Прокручиваемый элемент - это окно, то есть все тело. Фиксированные divs находятся внутри тела, да, но у них есть «позиция: фиксированная». – Tobia

+0

Я в основном собираюсь получить информацию, которую я получаю здесь http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/UIScrollView_pg/CreatingBasicScrollViews/CreatingBasicScrollViews.html # // apple_ref/doc/uid/TP40008179-CH101-SW1 –

ответ

4

OldDrunkenSailor избил меня, предложив iScroll.

К сожалению, из коробки iScroll просто реплицирует ту же проблему, что и родная инерциальная прокрутка - на инерциальной фазе нет обработки событий.

Вот версия вашего демо с обезьяной-заплата iScroll добавить пользовательское событие, которое стреляет даже в инерциальной стадии: https://dl.dropbox.com/u/15943645/scrollingdemo.html

отлично работает на моем 2-го поколения IPad.

JS:

// Disable touch events 
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); 

// Patch iScroll for position change custom event 
iScroll.prototype._oldPos = iScroll.prototype._pos; 
iScroll.prototype._pos = function(x, y) { 
    this._oldPos(x, y); 
    if (this.options.onPositionChange) this.options.onPositionChange.call(this); 
} 

$(function() { 
    var $win = $(window), 
     $div_cols = $('#cols'), 
     $div_rows = $('#rows'), 
     $div_body = $('#body') 

    // attach scrolling sync handler and execute it once 
    function sync_scroll(e) { 
     $div_cols.scrollLeft(0 - $div_body.position().left); 
     $div_rows.scrollTop(0 - $div_body.position().top); 

    }   

    // initialize iScroll on wrapper div, with position change handler 
    var myScroll = new iScroll('iscroll_wrapper', { 
     bounce: false, 
     onPositionChange: sync_scroll 
    }); 
}) 

CSS:

#iscroll_wrapper { 
    position:absolute; 
    z-index: 1; 
    left: 168px; 
    top:77px; 
    bottom:0px; 
    right:0; 
    overflow:auto; 
} 

#body { 
    position:absolute; 
    z-index: 1; 
    width: 2046px; 
    height: 3376px; 

} 

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

+0

Я не думал полностью заменить естественную прокрутку библиотекой, но это обходное решение, которое имеет прекрасный смысл. Благодарю вас обоих: @OldDrunkenSailor и Nick. Баунти присуждена Нику за рабочую демонстрацию! – Tobia

0

Триггеры, когда начинается свиток. Обратите внимание, что iOS-устройства блокируют DOM-манипуляцию во время прокрутки, ставя их в очередь, когда прокрутка заканчивается. В настоящее время мы изучаем способы применения DOM-манипуляций до начала прокрутки.

http://jquerymobile.com/demos/1.0rc1/docs/api/events.html#/demos/1.0rc1/docs/api/events.html

То, что они должны были сказать под прокрутки начальной секции

+0

Спасибо, но это исправление не связано с моей проблемой. Это не ошибка аппаратного ускорения. Нет исчезающих элементов. Это проблема с событиями Javascript, которые не запускаются во время автоматической «инерциальной» фазы прокрутки. – Tobia

+0

О, я был под впечатлением, что они просто отставали –

+0

- это ваш полный призыв к win.scroll? –

4

IOS фактически замерзает DOM манипуляции и Javascript, а инерционный скроллинг происходит. Вот простая демонстрация, которую я сделал, чтобы проиллюстрировать разницу между прокруткой в ​​обычной среде рабочего стола и iPad: http://jsfiddle.net/notjoelshapiro/LUcR6/.Этот код имеет только этот JS в нем:

var num = 0; 
function updateNum(){ 
    num++; 
    $('#awesomeDiv').text(num); 
} 
$(window).scroll(updateNum); 

На свитке он увеличивает число и выводит его на нижней части страницы. Вы увидите, что номер прокрутки в нижней части экрана увеличивается только тогда, когда инерционная прокрутка остановлена. Если Javascript действовал в фоновом режиме, он не обновлялся до тех пор, пока прокрутка не закончилась, а число должно увеличиваться выше.

Так, чтобы ответить на ваши вопросы конкретно:

Есть ли прикосновение или свиток событие выстрелило во инерциальной фазе прокрутки?

Отрицательный, ghostrider.

Есть ли способ запустить обратный вызов Javascript на этом этапе?

См. Выше.

Есть ли способ синхронизировать смещение прокрутки двух элементов (либо X, либо Y, а не обоих) с использованием CSS или другой технологии, отличной от JS?

Не совсем уверен, что вы имеете в виду здесь, JS может выполнять всю математику, которая вам нужна, но это должно быть, когда инерционный свиток завершен. Если честно, это может быть симптомом tl; dr, так как я сейчас работаю.

Вы просмотрели библиотеку iScroll? Он имитирует временную (или неинерциальную) прокрутку для сенсорной и не касательной среды и дает вам обратные вызовы JS во время/после «прокрутки» и «инерциальной прокрутки» и предоставляет много информации, которую вы можете использовать для расчета, где вы находитесь на стр.

+0

Спасибо за ваши исследования. Я не думал полностью заменить родную прокрутку библиотекой, но это обходное решение, которое имеет смысл. Надеюсь, это нормально, что я наградил Ник за щедрость за его рабочую демонстрацию. – Tobia

+0

Я никогда не прощу вас, но учитывая, что это интернет ..... – OldDrunkenSailor