2012-10-06 13 views
5

Estoy intentando crear este comportamiento: cuando el usuario desplaza una rueda del mouse (o presiona ), la página web se desplaza hacia abajo por la altura de la ventana.Impide que scrollTop invoque el evento de desplazamiento

he terminado con el siguiente código:

var newScrollTop, 
    oldScrollTop = $(window).scrollTop(), 
    preventScroll = false; 
$(window).scroll(function() { 
    if (!preventScroll) { 
     preventScroll = true; 
     newScrollTop = $(this).scrollTop(); 
     if (newScrollTop > oldScrollTop) { 
      $(this).scrollTop(oldScrollTop + $(window).height()); 
     } 
     else { 
      $(this).scrollTop(oldScrollTop - $(window).height()); 
     } 
     oldScrollTop = newScrollTop; 
     preventScroll = false; 
    } 
}); 

Pero esto no funciona como yo esperaba: en la página de eventos de desplazamiento se desplaza hasta el mismo borde (inferior o superior). ¿Qué me estoy perdiendo?

Respuesta

2

No hay una manera fácil de anular la funcionalidad predeterminada de desplazamiento del navegador. He aquí una manera de hacer lo que quiere, pero requiere de jquery-mousewheel plugin Brandon Aaron para gestionar la rueda de desplazamiento del ratón:

$(function() { 
    // Ugly hack to disable browser scrolling (downside: hides scrollbar!!!) 
    $('html').css('overflow', 'hidden'); 

    // Get viewport height by which to scroll (up or down) 
    var viewportHeight = $(window).height(); 

    // Recache viewport height on browser resize 
    $(window).on('resize', function() { 
     viewportHeight = $(window).height(); 
    }); 

    // Scroll on mousewheel 
    $('html').on('mousewheel', function(event, delta, deltaX, deltaY) { 
     // scroll down 
     if (deltaY < 0) 
      window.scrollBy(0, viewportHeight); 
     // scroll up 
     else 
      window.scrollBy(0, -viewportHeight); 
    }); 

    // Disable document keypress event 
    // which would scroll the content even with "overlow: hidden" 
    $(document).on('keypress', function(){ 
     return false; 
    }); 

    // Scroll on arrow up/down keys 
    $(document).on('keydown', function(event){ 
     // arrow down key 
     if (event.which == 40) 
      window.scrollBy(0, viewportHeight); 
     // arrow up key 
     if (event.which == 38) 
      window.scrollBy(0, -viewportHeight); 
    }); 
}); 

Aquí hay una fiddle de demostración del código. Todo funciona muy bien, excepto que hay un inconveniente desagradable para mi solución. El $('html').css('overflow', 'hidden'); está eliminando la barra de desplazamiento del navegador.

+0

ya que tienen barras de desplazamiento ocultos y deshabilitar 'keypress' parece ser innecesaria. La otra parte funciona como un encanto. Muchas gracias. – Pavlo

+1

Me alegro de poder ser de ayuda. He notado un pequeño error en mi solución, más exactamente si cambia el tamaño del navegador en la ventana gráfica. La altura ya no es válida, ya que se almacenó en caché en DOMReady. He actualizado el código para administrar eso. – Bogdan

+0

Gracias. Tu voto ha superado ese punto :-). – Bogdan

4

El problema es que está utilizando scrollTop() que activan un evento de desplazamiento dentro del evento de desplazamiento de la ventana.

Básicamente, con el código que ha escrito, se ejecuta en un bucle infinito porque tan pronto como se desencadena el primer evento de desplazamiento, scrollTop() se activa, mientras que su variable preventScroll sigue sin configurarse en falso, y así sucesivamente.

Para hacer su trabajo de código que tendría que establecer la variable de preventScroll a false dentro de la función setTimeout así:

var newScrollTop, 
    oldScrollTop = $(window).scrollTop(), 
    preventScroll = false; 

$(window).scroll(function() { 
    if (!preventScroll) { 
     preventScroll = true; 
     newScrollTop = $(this).scrollTop(); 
     if (newScrollTop > oldScrollTop) { 
      $(this).scrollTop(oldScrollTop + $(window).height()); 
     } 
     else { 
      $(this).scrollTop(oldScrollTop - $(window).height()); 
     } 
     oldScrollTop = newScrollTop; 

     setTimeout(function(){ preventScroll = false; }, 0); 
    } 
}); 

Añadimos un poco de "retraso" antes de que nos propusimos preventScroll a false. De esta manera, cuando llame a scrollTop()preventScroll ¡la variable seguirá siendo verdadera!

Aquí es un violín de trabajo: http://jsfiddle.net/J6Fcm/ (he modificado un poco su código para permitir que los pasos de desplazamiento funcionan como se esperaba)

Cuestiones relacionadas