Можно ли определить, было ли событие прокрутки выполнено браузером или пользователем? В частности, при использовании кнопки «Назад» браузер может перейти к последней известной позиции прокрутки. Если я привяжусь к событию прокрутки, как я могу определить, было ли это вызвано пользователем или браузером?
$(document).scroll( function(){
//who did this?!
});
Я вижу три типа ситуаций, вызывающих прокрутку в браузере.
- Пользователь выполняет какое-то действие. Например, используется колесо мыши, клавиши со стрелками, клавиши перехода на страницу вверх / вниз, клавиши возврата или окончания.
- Браузер прокручивает автоматически. Например, при использовании кнопки «Назад» в браузере происходит автоматический переход к последней известной позиции прокрутки.
- Прокрутка Javascript. Например,
element.scrollTo(x,y)
.
javascript
jquery
mrtsherman
источник
источник
Ответы:
К сожалению, нет прямого способа сказать это.
Я бы сказал, что если вы можете изменить дизайн своего приложения, чтобы оно не зависело от этого типа потока, сделайте это.
Если нет, то я могу придумать обходной путь - отслеживать прокрутки, инициированные пользователем, и проверять это, чтобы увидеть, была ли прокрутка запущена браузером или пользователем.
Вот пример, который я собрал, который делает это довольно хорошо (за исключением браузеров, в которых история jQuery имеет проблемы с).
Вам нужно запустить это локально, чтобы иметь возможность полностью протестировать (jsFiddle / jsbin не подходят, поскольку они iFrame содержимого).
Вот проверенные мной тестовые примеры :
userScroll
естьfalse
userScroll
становитсяtrue
userScroll
становитсяfalse
userScroll
становитсяfalse
;<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <script src="http://code.jquery.com/jquery-1.6.1.min.js"></script> <script type="text/javascript" src="https://raw.github.com/tkyk/jquery-history-plugin/master/jquery.history.js"></script> </head> <body> <span> hello there </span><br/> <a href="#bottom"> click here to go down </a> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <a name="bottom"> just sitting </a> </body> <script type="text/javascript"> var userScroll = false; function mouseEvent(e) { userScroll = true; } $(function() { // reset flag on back/forward $.history.init(function(hash){ userScroll = false; }); $(document).keydown(function(e) { if(e.which == 33 // page up || e.which == 34 // page dn || e.which == 32 // spacebar || e.which == 38 // up || e.which == 40 // down || (e.ctrlKey && e.which == 36) // ctrl + home || (e.ctrlKey && e.which == 35) // ctrl + end ) { userScroll = true; } }); // detect user scroll through mouse // Mozilla/Webkit if(window.addEventListener) { document.addEventListener('DOMMouseScroll', mouseEvent, false); } //for IE/OPERA etc document.onmousewheel = mouseEvent; // to reset flag when named anchors are clicked $('a[href*=#]').click(function() { userScroll = false; }); // detect browser/user scroll $(document).scroll( function(){ console.log('Scroll initiated by ' + (userScroll == true ? "user" : "browser")); }); }); </script> </html>
Ноты:
event.keyCodes
может отличаться в зависимости от ОС, поэтому вам, возможно, придется изменить это соответствующим образом.Надеюсь это поможет!
источник
event.thrower
собственности ?!).Вместо того, чтобы пытаться поймать все пользовательские события, гораздо проще сделать обратное и обрабатывать только программные события - и игнорировать их.
Например, такой код будет работать:
// Element that needs to be scrolled var myElement = document.getElementById('my-container'); // Flag to tell if the change was programmatic or by the user var ignoreNextScrollEvent = false; function setScrollTop(scrollTop) { ignoreNextScrollEvent = true; myElement.scrollTop = scrollTop } myElement.addEventListener('scroll', function() { if (ignoreNextScrollEvent) { // Ignore this event because it was done programmatically ignoreNextScrollEvent = false; return; } // Process user-initiated event here });
Затем, когда вы вызываете
setScrollTop()
, событие прокрутки будет проигнорировано, в то время как, если пользователь прокручивает с помощью мыши, клавиатуры или любым другим способом, событие будет обработано.источник
Насколько я знаю, невозможно (без какой-либо работы) определить, было ли событие прокрутки инициировано «пользователем» или другими способами.
Вы можете попробовать (как упоминалось другими) поймать события колесика мыши, а затем, вероятно, попытаться поймать событие нажатия клавиши на любых клавишах, которые могут запускать прокрутку (стрелки, пробел и т. Д.), Проверяя, какой элемент в настоящее время сфокусирован, поскольку вы, например, не можете прокручивать, используя клавиши со стрелками при вводе в поле ввода. В общем, это был бы сложный и запутанный сценарий.
В зависимости от ситуации, с которой вы имеете дело, я мог бы предположить, что вы «вернете логику», и вместо того, чтобы обнаруживать выданные пользователем события прокрутки, просто подключитесь к любым прокруткам, созданным программно, и обработайте любые события прокрутки, не созданные вашим кодом, как сделанные пользователем. Как я уже сказал, это зависит от ситуации и от того, чего вы пытаетесь достичь.
источник
Да, это возможно на все 100%. В настоящее время я использую это в приложении, где IE не является обязательным - только для клиента. Когда мое приложение Backbone инициирует анимацию, в которой прокрутка изменяется - прокрутка происходит, но не запускает эти захваты событий. Это проверено в последней версии FF, Safari и Chrome.
$('html, body').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(evt) { // detect only user initiated, not by an .animate though if (evt.type === 'DOMMouseScroll' || evt.type === 'keyup' || evt.type === 'mousewheel') { // up if (evt.originalEvent.detail < 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta > 0)) { // down. } else if (evt.originalEvent.detail > 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta < 0)) { } } });
источник
Попробуйте вместо этого использовать события Mousewheel и DOMMouseScroll. См. Http://www.quirksmode.org/dom/events/scroll.html.
источник
Вы можете проверить положение прокрутки, когда будете готовы. Когда вы запускаете событие при прокрутке, убедитесь, что положение прокрутки отличается от того, которое было при загрузке страницы. Наконец, не забудьте очистить сохраненное значение после прокрутки страницы.
$(function () { var loadScrollTop = ($(document).scrollTop() > 0 ? $(document).scrollTop() : null); $(document).scroll(function (e) { if ( $(document).scrollTop() !== loadScrollTop) { // scroll code here! } loadScrollTop = null; }); });
источник
Относительно:
Это срабатывает очень скоро после рендеринга страницы. Вы можете просто отложить прослушивание события прокрутки примерно на 1 секунду.
источник
Есть еще один способ отделить созданную пользователем прокрутку: вы можете использовать альтернативные обработчики событий, например, 'mousewheel', 'touchmove', 'keydown' с кодами 38 и 40 для прокрутки стрелок, для прокрутки с полосой прокрутки - если Событие 'scroll' запускается одновременно с 'mousedown' до события 'mouseup'.
источник
Нашел это очень полезным. Вот вариант кофе для тех, кто так склонен.
$ -> S.userScroll = false # reset flag on back/forward if $.history? $.history.init (hash) -> S.userScroll = false mouseEvent = (e)-> S.userScroll = true $(document).keydown (e) -> importantKey = (e.which == 33 or # page up e.which == 34 or # page dn e.which == 32 or # spacebar e.which == 38 or # up e.which == 40 or # down (e.ctrlKey and e.which == 36) or # ctrl + home (e.ctrlKey and e.which == 35) # ctrl + end ) if importantKey S.userScroll = true; # Detect user scroll through mouse # Mozilla/Webkit if window.addEventListener document.addEventListener('DOMMouseScroll', mouseEvent, false); # for IE/OPERA etc document.onmousewheel = mouseEvent;
источник
Если вы используете JQuery, то, по-видимому, есть лучший ответ - я просто пробую сам.
см .: Обнаружение триггера события jquery пользователем или вызов по коду
источник
Это может не помочь вашему приложению, но мне нужно было запускать событие при прокрутке пользователя, но не программную прокрутку и публикацию, если это поможет кому-то еще.
Слушайте
wheel
события вместоscroll
,Он запускается всякий раз, когда пользователь использует колесо мыши или трекер (что, как мне кажется, в любом случае прокручивает большинство людей), и не запускается, когда вы программно прокручиваете. Я использовал его, чтобы различать действие прокрутки пользователя и функции прокрутки.
https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
element.addEventListener('wheel', (event) => { //do user scroll stuff here })
Одно предостережение заключается в том, что
wheel
на мобильных устройствах не запускается прокрутка, поэтому я проверил, было ли устройство мобильным, и использовал ли он аналогичные функции.if(this.mobile){ element.addEventListener('scroll', (event) => { //do mobile scroll stuff here }) }
источник