iScroll с собственной прокруткой на одной оси - PullRequest
13 голосов
/ 18 октября 2011

Я использую самый замечательный инструмент javascript iScroll4 http://cubiq.org/iscroll-4 на мобильном сайте для iOS и Android. Вот как выглядит мой макет:

layout problem

Область с горизонтальной прокруткой использует iScroll4 со следующими настройками:

   var myScroll = new iScroll('frame',  { hScrollbar: false, vScrollbar: false, vScroll: false })

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

Что я пробовал до сих пор: Удаление e.preventDefault () в коде iScroll (допускает собственную прокрутку, но в обоих направлениях). Удалите e.preventDefault () и затем отключите горизонтальную прокрутку страницы с помощью этого:

var touchMove;

document.ontouchstart = function(e){
    touchMove = e.touches[0];
}

document.ontouchmove = function(e){
    var theTouch = e.touches[0] || e.changedTouches[0];
    var Xer      = rs(touchMove.pageX - theTouch.pageX).toPos();
    var Yer      = rs(touchMove.pageY - theTouch.pageY).toPos();        
    touchMove    = theTouch;
    if(Yer > Xer){ e.preventDefault(); }
}

который, похоже, ничего не делает. Как можно разрешить собственную вертикальную прокрутку в области горизонтальной прокрутки, не теряя при этом горизонтальную прокрутку iScroll? Я действительно в тупик здесь. Заранее спасибо.

(только для записи rs (foo) .toPos () - это функция, которая делает foo положительным числом независимо от его значения).

Ответы [ 7 ]

12 голосов
/ 18 мая 2012

Если вы хотите добиться эффекта, описанного в Fresheyeball, не взламывая ядро ​​и не переключаясь с iScroll на swipeview, то iScroll 4 действительно предлагает вам прослушиватели событий для работы.

myScroll = new iScroll('scrollpanel', {
    // other options go here...
    vScroll: false,
    onBeforeScrollMove: function ( e ) {
        if ( this.absDistX > (this.absDistY + 5 ) ) {
            // user is scrolling the x axis, so prevent the browsers' native scrolling
            e.preventDefault();
        } else {
            // delegate the scrolling to window object
        window.scrollBy( 0, -this.distY );
    }
    },
});

Таким образом, onBeforeScrollMove -Handler проверяет, кажется ли направление прокрутки горизонтальным, а затем предотвращает использование обработчика по умолчанию, таким образом, эффективно блокируя действие прокрутки для оси X (попробуйте закомментировать его, вы увидеть разницу). В противном случае, если направление прокрутки должно быть вертикальным, мы выполняем прокрутку браузера с помощью метода window.scrollBy(). Это не совсем нативно, но отлично справляется с работой.

Надеюсь, что поможет

Lukx

[EDIT] Мое оригинальное решение, в котором не использовался window.scrollBy(), не работало на более медленных телефонах Samsung, поэтому мне нужно было адаптировать ответ.

10 голосов
/ 30 октября 2012

Рекомендуется отредактировать отличное решение @ Lukx.Новые версии iScroll4 помещают e.preventDefault() в onBeforeScrollMove, который можно переопределить.Помещая блок if в эту опцию, по умолчанию вертикальная прокрутка не предотвращается, а вертикальная может прокручиваться изначально.

myScroll = new iScroll('scrollpanel', {
    // other options go here...
    vScroll: false,
    onBeforeScrollStart: function ( e ) {
        if ( this.absDistX > (this.absDistY + 5 ) ) {
            // user is scrolling the x axis, so prevent the browsers' native scrolling
            e.preventDefault();
        }
    },
});
4 голосов
/ 18 сентября 2014

С помощью iscroll 5 вы можете установить eventPassthrough: true для достижения этой цели. Смотри http://iscrolljs.com/#configuring

1 голос
/ 18 ноября 2011

СТАРЫЙ ОТВЕТ

ОБНОВЛЕНИЕ Специальный плагин был написан только для решения этой проблемы: http://cubiq.org/swipeview

Я нашел способ!

добавить переменную в начало документа: если android равен 15, а iOS - 3

 var scrollTolerance = ( rs().isDevice('android') )?15:3;

, отключите оригинальный e.preventDefault ();для прокрутки.Это в onBeforeScrollStart:

в _move чуть ниже

 timestamp = e.timeStamp || Date.now();

добавить эту строку

if( Math.sqrt(deltaX*deltaX) > scrollTolerance){e.preventDefault();}

Что это делает следующим образом: scrollTolerance устанавливает, как вы уже догадалисьэто, допуск для направления пальца.Мы не хотим требовать идеального вертикального угла, чтобы получить верхнюю прокрутку.Также iOS не определяет должным образом и никогда не будет больше 4 по какой-то причине, поэтому я использовал 3. Затем мы отключаем стандартную функцию iScroll e.preventDefault ();что предотвращает естественную вертикальную прокрутку в нашей области с двойной прокруткой.Затем мы вставляем e.preventDefault ();только при движении и на основе направления пальца от допуска.

Это не работает идеально.Но это приемлемо и работает на iOS и Android.Если кто-то видит лучшие способы, пожалуйста, напишите здесь.Это то, что я (и предполагаю, что другие) должны регулярно использовать, и у нас должно быть идеальное твердое решение.

Спасибо.

0 голосов
/ 19 сентября 2017

на iScroll5 просто установите для eventPassthrougt значение true.Это исправляет.

0 голосов
/ 20 марта 2014

iScroll 5 поддерживает собственную прокрутку любой оси!

http://iscrolljs.com/

0 голосов
/ 09 октября 2013

Пожалуйста, проверьте это решение от Адама.https://gist.github.com/hotmeteor/2231984

Я думаю, что хитрость заключается в том, чтобы добавить проверку в BeforeScrollMove.Сначала получите начальную позицию касания в onBeforeScrollTouchStart, а затем в onBeforeScrollMove проверьте новую позицию и затем отключите требуемую прокрутку на основе разницы.

...