¿Es posible saber si un evento de desplazamiento fue realizado por el navegador o por el usuario? Específicamente, cuando se usa el botón Atrás, un navegador puede saltar a la última posición de desplazamiento conocida. Si me vinculo al evento de desplazamiento, ¿cómo puedo saber si esto fue causado por el usuario o el navegador?
$(document).scroll( function(){
//who did this?!
});
Veo tres tipos de situaciones que provocan el desplazamiento en un navegador.
- El usuario realiza alguna acción. Por ejemplo, utiliza la rueda del mouse, las teclas de flecha, las teclas de avance / retroceso de página, las teclas de inicio / fin.
- El navegador se desplaza automáticamente. Por ejemplo, cuando utilice el botón Atrás en su navegador, saltará automáticamente a la última posición de desplazamiento conocida.
- Se desplaza Javascript. Por ejemplo
element.scrollTo(x,y)
,.
javascript
jquery
mrtsherman
fuente
fuente
Respuestas:
Desafortunadamente, no hay una forma directa de decirlo.
Yo diría que si puedes rediseñar tu aplicación para que no dependa de este tipo de flujo, hazlo.
Si no es así, una solución alternativa en la que puedo pensar es realizar un seguimiento de los desplazamientos iniciados por el usuario y comprobarlo para ver si el desplazamiento fue activado por el navegador o por el usuario.
Aquí hay un ejemplo que reuní y que hace esto bastante bien (excepto para los navegadores con los que jQuery history tiene problemas).
Debe ejecutar esto localmente para poder probarlo completamente (jsFiddle / jsbin no se ajustan bien ya que iFrame el contenido).
Aquí están los casos de prueba que validé:
userScroll
esfalse
userScroll
conviertetrue
userScroll
convierte enfalse
userScroll
convierte enfalse
;<!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>
Notas:
event.keyCodes
puede variar según el sistema operativo, por lo que es posible que deba cambiarlo de forma adecuada.¡Espero que esto ayude!
fuente
event.thrower
propiedad ?!).Hasta donde yo sé, es imposible (sin ningún trabajo) saber cuándo el "usuario" ha emitido un evento de desplazamiento o por otros medios.
Puede intentar (como otros mencionaron) capturar eventos de rueda del mouse, y luego probablemente intentar capturar el evento de pulsación de tecla en cualquier tecla que pueda activar el desplazamiento (flechas, espacio, etc.) mientras verifica qué elemento está enfocado actualmente, ya que, por ejemplo, no puede desplazarse usando teclas de flecha mientras escribe en un campo de entrada. En general, sería un guión complejo y desordenado.
Dependiendo de la situación con la que esté lidiando, supongo que podría "revertir la lógica", y en lugar de detectar eventos de desplazamiento emitidos por el usuario, simplemente conéctese a cualquier desplazamiento realizado mediante programación y trate cualquier evento de desplazamiento no creado por su código como hecho por un usuario. Como dije, depende de la situación y de lo que intentas lograr.
fuente
En lugar de intentar capturar todos los eventos del usuario, es mucho más fácil hacer lo contrario y manejar solo los eventos programáticos, e ignorarlos.
Por ejemplo, este tipo de código funcionaría:
// 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 });
Luego, cuando llame
setScrollTop()
, se ignorará el evento de desplazamiento, mientras que si el usuario se desplaza con el mouse, el teclado o cualquier otra forma, el evento será procesado.fuente
Sí, es 100% posible. Actualmente estoy usando esto en una aplicación donde IE no es un requisito, solo para el cliente. Cuando mi aplicación Backbone inicia una animación en la que se cambia el desplazamiento, el desplazamiento se produce pero no activa estas capturas de eventos. Esto se prueba en FF, Safari y Chrome más reciente.
$('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)) { } } });
fuente
Intente usar los eventos Mousewheel y DOMMouseScroll en su lugar. Ver http://www.quirksmode.org/dom/events/scroll.html
fuente
Puede comprobar la posición de desplazamiento en listo. Cuando activa el evento de desplazamiento, compruebe que la posición de desplazamiento sea diferente a la que tenía cuando se cargó la página. Por último, asegúrese de borrar el valor almacenado una vez que se desplaza por la página.
$(function () { var loadScrollTop = ($(document).scrollTop() > 0 ? $(document).scrollTop() : null); $(document).scroll(function (e) { if ( $(document).scrollTop() !== loadScrollTop) { // scroll code here! } loadScrollTop = null; }); });
fuente
Con respecto a:
Eso se activa muy pronto, después de que se renderiza la página. Puede retrasar la escucha del evento de desplazamiento en aproximadamente 1 segundo.
fuente
Hay una forma más de separar el desplazamiento creado por el usuario: puede utilizar los controladores de eventos alternativos, por ejemplo, 'mousewheel', 'touchmove', 'keydown' con los códigos 38 y 40 para desplazamiento de flechas, para desplazamiento con barra de desplazamiento, si El evento 'scroll' se dispara simultáneamente con el evento 'mousedown' hasta el evento 'mouseup'.
fuente
Encontré esto muy útil. Aquí hay una versión de coffeescript para aquellos que así lo deseen.
$ -> 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;
fuente
si está usando JQuery, entonces hay una mejor respuesta, aparentemente, solo lo estoy probando yo mismo.
ver: Detectar el desencadenador de eventos de jquery por usuario o llamar por código
fuente
Puede que no ayude con su aplicación, pero necesitaba disparar un evento en el desplazamiento del usuario, pero no en el desplazamiento programático y la publicación en caso de que ayude a alguien más.
Escuche el
wheel
evento en lugar descroll
,Se activa cada vez que un usuario usa la rueda del mouse o la almohadilla de seguimiento (que creo que es la forma en que la mayoría de la gente se desplaza de todos modos) y no se activa cuando se desplaza programáticamente. Lo usé para diferenciar entre una acción de desplazamiento de usuario y funciones de desplazamiento.
https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
element.addEventListener('wheel', (event) => { //do user scroll stuff here })
Una advertencia es que
wheel
no se activa con el desplazamiento en el móvil, así que verifiqué si el dispositivo era móvil y usé funciones similares.if(this.mobile){ element.addEventListener('scroll', (event) => { //do mobile scroll stuff here }) }
fuente