En mi código Javascript, estoy escuchando el evento de desplazamiento y haciendo algo de trabajo cada vez que se dispara:
document.addEventListener( 'scroll', (event) => { // do something }, { passive: true } );Tengo una barra de navegación que contiene anclas a diferentes secciones en mi página, que cuando se hace clic hace que la página se desplace hacia abajo a la sección (y activa el evento de desplazamiento):
<nav class="navbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link nav-link-jump" href="#anchor-1">Popular Items</a> </li> </ul> </nav> ... <section id="anchor-1">...</section>Sin embargo, no quiero que se active el evento de desplazamiento cuando la página se desplaza como resultado de hacer clic en el enlace de anclaje. Solo quiero que se active cuando el usuario realmente se desplaza (es decir, con la rueda del mouse o deslizando).
No pude encontrar ningún campo en el objeto 'evento' que diferenciara las dos fuentes de desplazamiento, pero tal vez me perdí algo.
El evento de desplazamiento toma la interfaz Event más genérica, por lo que no hay propiedades para diferenciar el origen del desplazamiento. Creo que es básicamente inviable sin anular por completo el comportamiento predeterminado del ancla de desplazamiento con su propio JS. Habiendo intentado hacer cosas similares en el pasado y terminando con resultados horribles, no lo recomendaría.
Es posible que desee pensar en hacer esto a la inversa: deshabilite cualquier cosa que no desee que suceda cuando un usuario haga clic en el enlace, luego vuelva a habilitarlo la próxima vez que se touchmove un evento de wheel o movimiento táctil. Estos eventos son específicos del comportamiento de desplazamiento del usuario y no se activarán mediante un enlace ancla.
const link = document.querySelector("a"); const counter = document.querySelector("p"); const target = document.querySelector("#target"); let userScrolling = true; link.addEventListener("click", () => userScrolling = false); window.addEventListener("wheel", () => userScrolling = true); window.addEventListener("touchmove", () => userScrolling = true); window.addEventListener("mousedown", () => userScrolling = true); window.addEventListener("scroll", () => { if (!userScrolling) return; counter.textContent = parseInt(counter.textContent) + 1; }); html { scroll-behavior: smooth; } p { position: fixed; bottom: 0; right: 0; padding: 16px; } .separator, #target { height: 100vh; } <a href="#target">Link</a> <p>0</p> <div class="separator"></div> <div id="target">Target<div> Notarás que también hay un controlador de mousedown allí. Eso es para que podamos permitir que el usuario se desplace nuevamente haciendo clic y arrastrando manualmente la barra de desplazamiento, y también haciendo clic en la brújula de la rueda central. Desafortunadamente, uno o varios eventos de scroll se deslizarán dependiendo del navegador si presiona el mousedown mientras el desplazamiento de anclaje está en progreso.
También puede ir un paso más allá para aliviar este problema y asegurarse de que el evento del mouse provenga de un botón de rueda central event.button = 1 o se active sobre una barra de desplazamiento. Este segundo factor es potencialmente complicado y está más allá del alcance de la pregunta, así que los dejo con esta respuesta , que es la más prometedora que pude encontrar.
Sin embargo, sinceramente, creo que la moraleja aquí debería ser no intentes hacer esto. La razón por la que no puede distinguir usuario/ancla en el evento es porque son funcionalmente idénticos: un usuario que hace clic en un botón para desplazarse por ellos es un comportamiento de desplazamiento del usuario y, de manera realista, no debería causar un problema. Si tiene alguna animación basada en desplazamiento que necesita omitir, podría ser mejor simplemente eliminar el comportamiento de desplazamiento suave y restablecer los valores de animación en segundo plano.
let navElements = document.getElementsByClassName("nav-link")[0] let scroll = true navElements.addEventListener("click", function () { scroll = false }); document.addEventListener( 'scroll', (event) => { if ( scroll === true ) { // do something } scroll = true }, { passive: true } ); <nav class="navbar"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link nav-link-jump" href="#anchor-1">Popular Items</a> </li> </ul> </nav> ... <section id="anchor-1">...</section>scroll de elemento, establecido en verdadero.true .