Проверить scrollTop на сенсорном устройстве
У меня есть следующая функция, которая проверяет положение прокрутки пользователя так, чтобы меню фиксировалось после прокрутки мимо мачты
function checkScrolling() {
if( $(window).scrollTop() > $('.masthead').height() ) { // we check against ACTUAL height
$('.menu').addClass('fixed');
}else {
$('.menu').removeClass('fixed');
}
}
и здесь прослушиватели событий на рабочем столе и сенсорном экране:
$(document).bind('touchstart touchend touchcancel touchleave touchmove', function(e){
checkScrolling();
});
$(window).scroll(function(){
checkScrolling();
});
Однако события касания только делают меню фиксированным во время сенсорной навигации надежно. Если я прокручиваю очень быстро, прокручивая вверх или вниз, происходит задержка до того, как меню станет фиксированным или незафиксированным.
Любые идеи о том, как это исправить? См. пример кода здесь: http://dev.driz.co.uk/mobileMasthead.html (был изменен на основе некоторых ответов ниже, но все еще не работает правильно на iPad или iPhone)
Обновление:
И чтение по теме показывает, что JS, как проверка положения прокрутки, не происходит во время прокрутки... НО... Я заметил, что http://www.facebook.com/home/ не имеет этой проблемы при тестировании на моем iPad. Таким образом, это определенно возможно для достижения этого эффекта без использования каких-либо пользовательских полос прокрутки JavaScript, таких как iScroll или аналогичных.
Ответы
Ответ 1
Возможно, я понимаю, что вопрос неправильный, но чтобы обеспечить функциональность с высокой скоростью прокрутки, почему бы вам не заняться чистым стилем CSS (иначе он притворяется "причудливым" эффектом):
Старая школа (быстрая, но примитивная)
HTML
<div id="menu2"></div>
<div class="scroll" id="scroller">
<div id="overlay"></div>
<div id="menu"></div>
</div>
С помощью простого CSS:
html, body { overflow: hidden; height: 100% }
body { margin:0; padding:0; }
.scroll {
-webkit-overflow-scrolling: touch;
height:960px;
width:640px;
}
#menu2 {
width:640px;
height:20px;
background:red;
position:absolute;
z-index:-1;
}
#menu {
width:100%;
height:20px;
background:red;
z-index:0;
}
Вы можете увидеть рабочий пример ЗДЕСЬ.
Это может быть немного примитивно: но эй! Оно работает!:)
Новая школа (фантазия, но медленная)
Проверьте все остальные ответы.
Но обратите внимание, что "известно", что использование JavaScript в сочетании с прокруткой на мобильных устройствах вызывает много проблем в скорости.
Вот почему я думаю, что простой подход CSS может быть лучше.
Если вы хотите узнать о JavaScript и прокрутке на мобильных устройствах (и других функциях), то есть две статьи, которые я настоятельно рекомендую читать:
Ответ 2
Facebook не использует JavaScript, но чистый css:
position: -webkit-sticky;
Если я правильно его помню, это заставляет элемент придерживаться в верхней части родительского контейнера при прокрутке.
Ответ 3
Вам просто нужно было прикрепить свои события прокрутки, а не к окну, документу или телу, но к пользовательскому контейнеру.
В iOS вы не можете программно реагировать во время этих прокрутки окна с аппаратным ускорением.
Здесь скрипка:
обертка:
<div id="content">
некоторые не очень релевантные css:
html,body,#content {
width:100%;
height:100%;
}
#content {
background-color: lightblue;
overflow:scroll;
}
прикрепление слушателей к контейнеру:
function checkScrolling() {
if ($('#content').scrollTop() > mastheadHeight) {
menu.addClass('fixed');
} else {
menu.removeClass('fixed');
}
}
$('#content').scroll(function () {
checkScrolling();
});
Вы можете увидеть, как он работает здесь для резервного копирования только JS:
http://jsfiddle.net/jaibuu/YqPzS/
прямой URL: http://fiddle.jshell.net/jaibuu/YqPzS/show/
Ответ 4
Однажды я попытался реализовать липкие заголовки на мобильной версии сайта, но столкнулся с целым набором проблем.
Во-первых, самое главное, что событие scroll
не срабатывает на мобильных устройствах так часто, как на рабочем столе. Обычно он срабатывает при остановке страницы. Я не знаю точной причины этого, но могу предложить, потому что браузеры на мобильных устройствах "отправляют" такие задачи на GPU, в то время как ЦП не может обновлять объекты JS до того, что происходит с холстом (но это только мое предложение). Более новая версия iOSs делает ее лучше для нас, и, возможно, scroll
будет работать на iPhone.
Вы должны использовать события touch
. Это заставляет вас написать отдельную версию кода для устройств, поддерживающих сенсорный ввод. Поэтому нужно искать надежные способы тестирования для платформы.
Но события touch
также сложны, особенно на Android. Я думал, что в обратном вызове для события touchmove
я смогу вычислить текущие координаты и пойти дальше от этой точки.
Но вот этот вопрос https://code.google.com/p/android/issues/detail?id=5491 на Android, в итоге touchmove
срабатывает один или два раза в самом начале действия касания и не срабатывает снова. Это делает его совершенно бесполезным. Люди предлагают preventDefault(), но вы больше не можете прокручивать с этим.
Итак, у меня появилась идея переопределить прокрутку с нуля с помощью CSS-преобразований. И вот мои результаты до сих пор:
http://jsbin.com/elaker/23
Откройте эту ссылку на своем устройстве и http://jsbin.com/elaker/23/edit на своем рабочем столе: вы сможете редактировать код и обновлять его на вы устройство, очень удобно.
Примечание:
Я хотел бы предупредить вас о том, что эта прокрутка CSS является необработанной, и есть некоторые известные проблемы, которые еще не решены: например, вы иногда можете прокручивать верхнюю или нижнюю границу, или если вы просто касаетесь (не двигаетесь), она все равно будет прокручиваться. Также пресловутая строка URL-адресов не будет скрываться. Итак, есть работа.
Ответ 5
Вам нужны события касания, чтобы это вообще упустить? Современные устройства должны возвращать события $(window).scroll()
и значения scrollTop
. На старых Android и пре-ios5 (я думаю), position:fixed:
работал не так, как ожидалось, из-за работы видового экрана. Но он был исправлен во всех новых выпусках.
Для дальнейшего отладки устройств я настоятельно рекомендую Adobe Edge Inspect. Вы можете console.log
scrollTop и посмотреть, действительно ли устройства, о которых вы заботитесь, действительно работают с любыми обманами. Вы получите все, что вам нужно, с их бесплатной версией.
Ответ 6
Отличный способ справиться с событиями прокрутки - не прикреплять ваши чеки к событию прокрутки
занимает много ресурсов и не очень хорошо работает со старыми браузерами.
к счастью, у вас может быть намного больше контроля, если вы просто выполняете цикл времени для этого.
это выглядит так:
(Используется твиттером)
var MyMenu = $('#menu'),
didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
//Do your check here
checkScrolling();
}
}, 180);
Вы должны поместить свой $('. masthead'). height() вне этой функции checkScrolling вашего (в более высокой области), так как этот вид операций требует много ресурсов и всегда запрашивает jquery для "выбора вашего элемента", и вычислить его размер, в конечном итоге сделает ваше приложение лагги:
var headerHeight = $('.masthead').height()
function checkScrolling()
.....
Последнее, вы можете изменить значение атрибута interval (прямо сейчас он 180 (бит больше, чем 60hz - время обновления экрана), вы можете сделать это значение больше, если вы хотите, чтобы ваше приложение было более эффективным но немного менее точный)
Спасибо, Джон Ресиг и твиттер:
http://ejohn.org/blog/learning-from-twitter/
Надеюсь, что это помогло
Ajios!
Ответ 7
setScrollTop: function(inTop) {
var top = Math.max(0,inTop);
if (wm.isMobile) { // should always be true for touch events
top = Math.min(top, this.listNode.clientHeight - this.listNodeWrapper.clientHeight);
if (dojo.isWebKit) {
this.listNode.style.WebkitTransform = "translate(0,-" + top + "px)";
} else if (dojo.isMoz) {
this.listNode.style.MozTransform = "translate(0,-" + top + "px)";
} else if (dojo.isOpera) {
this.listNode.style.OTransform = "translate(0,-" + top + "px)";
} else if (dojo.isIE) {
this.listNode.style.MsTransform = "translate(0,-" + top + "px)";
}
this.listNode.style.transform = "translate(0,-" + top + "px)";
this._scrollTop = top;
this._onScroll();
} else {
this.listNode.scrollTop = top + "px";
}
},
Ответ 8
Я только что проверил ваши функции на эффективность. Вы должны попробовать это
function checkScrolling() {
if( $(window).scrollTop() > mastheadHeight )menu.css('position','fixed');
else menu.css('position','');
}
Это уменьшит вызов функции addClass и RemoveClass, и ваше время выполнения вступит в силу. Если вы хотите сократить время выполнения, то лучше использовать чистый JavaScript
Ответ 9
$(document).ready(function(){
var p = $("#stop").offset().top;
$(window).scroll(function(){
if(p<$(window).scrollTop()){
console.log("div reached");
$("#stop").css({position:"fixed",top:0});
}
else{
console.log("div out");
$("#stop").css({position:"static"});
}
})
});
Я думаю, это поможет вам.
Полный код здесь в jsfiddle.net.
Я тестировал его для ipad, используя сафари онлайн-симулятора ipad2 в http://alexw.me/ipad2/, и он там работал, Итак, я думаю, что он будет работать и на реальном ipad.