#javascript #jquery #iscroll
#javascript #jquery #iscroll
Вопрос:
Я создал следующее приложение, используя iScroll: http://preview.na-software.co.uk/Demo/FutureLearning4/#/section-0
Когда пользователь щелкает влево и вправо или щелкает стрелки в нижних углах, приложение перемещает разделы содержимого. Оно обновляет историю, изменяя хэш, Чтобы пользователь мог переходить к другим разделам и добавлять в них закладки и т. Д.
Однако! Если вы получаете доступ к хэшу, например: http://preview.na-software.co.uk/Demo/FutureLearning4/#/section-2 а затем перейдите по нескольким разделам, а затем используйте кнопки назад, возникают две проблемы:
1.) Он прокручивается до первого экрана (даже если currentSection
он правильный, и iScroll указал правильный раздел).
2.) Если вы нажмете кнопку назад или вперед несколько раз, вы остановите анимацию и заставите ее запутаться и застрять между двумя разделами.
Изучив код и увидев, что правильные индексы и элементы передаются в iScroll при hashchange, а консоль выводит из системы смещения, я обнаружил, что проблема вызвана тем, что смещения установлены неправильно… однако простое выполнение refresh()
не решит проблему, так как затем сбросит позицию.
Кто-нибудь может увидеть, в чем проблема, или найти способ исправить это?
Я должен отметить, что эта ошибка возникает ТОЛЬКО в том случае, если вы заходите в приложение по URL-адресу, который не является разделом 0, а затем прокручиваете приложение. Это потому, что смещения будут созданы правильно вашими взаимодействиями. Но если вы перейдете на URL, подобный разделу 3, то смещения будут неверными, и поэтому хэш-изменения будут работать некорректно, если это имеет смысл.
Метод hashchange выглядит следующим образом:
// handle hashchange events
$(window).hashchange( function(){
// read the hash to find out what the new section number is
var nums = location.href.match(/(section)-d /g).map(
function(x){ return x.replace(/D/g,"") }
);
// set currentSection
currentSection = nums[0];
// if the hashchange was called by user scrolling
if(hashCalledByScroll){
// no need to anything as they have already updated hash and scrolled
hashCalledByScroll = false;
} else {
// find the section to scrollTo
sectionToScrollTo = $('#horizontal > .sections > .section').eq(currentSection).attr('id');
// tell iscroll to scroll to the section
horizontal.scrollToElement( '#' sectionToScrollTo, null, null, true );
}
// hide the menu on hashchange
hideMenu();
});
Ответ №1:
Тестируя ваш сайт, я заметил следующее: всякий раз, когда я захожу на сайт через раздел-3, а затем ввожу URL-адрес для раздела-2, навигация вместо этого отправляет меня в раздел-0.
Я считаю, что это то же поведение, что и в 1).
Итак, я исследовал и пришел к следующему анализу:
В функции horizontal.scrollToElement( '#' sectionToScrollTo, null, null, true )
iScroll извлекает utils.offset(el)
[iScroll.js#772] для данного el
элемента. Это смещение сообщает ему, где находится элемент для прокрутки.
iScroll просматривает элемент и все его родительские значения offsetParents, чтобы сложить их смещения. Вот где все ломается: <div class="sections">
имеет отрицательное смещение к своему родительскому элементу, которого, по-моему, у него не должно быть.
Это, в свою очередь, приводит к путанице в scrollTo
-coordinates .
Чтобы понять, о чем я говорю: document.querySelector('.sections').offsetLeft
Все это было просто анализом. Мой подход к исправлению этого состоял бы в том, чтобы избегать scrollToElement()
и вместо этого использовать scrollTo()
:
...
} else {
// find the section to scrollTo
sectionToScrollTo = $('#horizontal > .sections > .section').eq(currentSection).attr('id');
// tell iscroll to scroll to the section
var posLeft = -$('#' sectionToScrollTo)[0].offsetLeft;
var posTop = -$('#' sectionToScrollTo)[0].offsetTop;
horizontal.scrollTo(posLeft, posTop, 1000);
}
// hide the menu on hashchange
hideMenu();
});
Таким образом, просто вычислите местоположение раздела, в который вы хотите перейти, самостоятельно.
Около 2) Я не уверен, что с этим можно что-то сделать. Быстрое переключение приводит к разрыву множества каруселей. Возможно, отложенный обратный scrollEnd
вызов, проверяющий правильность текущего состояния.
Еще одна вещь, которую я заметил, это то, что вы можете случайно остановить переход. Попробуйте щелкнуть, удерживать и отпускать курсор в середине перехода — вам нужно действовать быстро.
Надеюсь, это поможет.
Комментарии:
1. Не могли бы вы собрать скрипку, чтобы объяснить это? Спасибо за помощь.
2. Я пришел к тому же выводу. Я думаю, что наименее проблематичным способом исправить это было бы вычислить местоположения самостоятельно.
Ответ №2:
Найдено не лучшее решение, и оно не решает основную проблему, но оно работает.
$(window).hashchange(function () {
if (hashCalledByScroll) {
hashCalledByScroll = false;
} else {
var hpage = window.location.hash;
var hpage = hpage.replace('#/section-', ''); //get number of target page
var cpage = currentSection; //number of current page
var count = parseInt(hpage) - parseInt(cpage); //difference
while (count > 0) { //if difference positive: go forward count-times
horizontal.next();
count--;
}
while (count < 0) { //if difference negative: go backward count-times
horizontal.prev();
count ;
}
}
hideMenu();
});
Комментарии:
1. Если это работает (еще не полностью протестировано), что вы имеете в виду, что это не решает основную проблему? Спасибо.
2. Я имею в виду, что это решение решает вашу проблему с кнопкой возврата истории, но оно не решает конфликт iScroll с хэшем