JQuery ScrollTop() works on window event but not d

2019-09-13 00:27发布

问题:

Working on this page at the moment

https://www.cliquenext.com/sandbox.php

We have two div columns. #mainpage (to the right) and #sidebar to the left.

The aim is that if I scroll in the right column, the left scrolls too. If I scroll in the left column, the right scrolls too. Both at the same time.

When I use $(window).ScrollTop - it works fine. When I use $("#sidebar").Scrolltop - it doesnt fire.

The following code works scrolling #mainpage when scrolling #sidebar.

$("#sidebar").scroll(function(event){
   event.preventDefault();  

   var st = $(this).scrollTop();
   if (st > lastScrollTop){
       // downscroll code

       var y = $(window).scrollTop();  //your current y position on the page
       $(window).scrollTop(y+10);

   } else {
      // upscroll code

        var y = $(window).scrollTop();  //your current y position on the page
       $(window).scrollTop(y-10);


   }
   lastScrollTop = st;
});

The following code doesn't work. When scrolling on #mainpage the #sidebar should scroll too. But its not.

$("#mainpage").scroll(function(event){
   event.preventDefault();  

   var st2 = $(this).scrollTop();
   if (st2 > lastinfoscroll){
       // downscroll code

       var y = $("#sidebar").scrollTop();  //your current y position on the page
       $("#sidebar").scrollTop(y+10);

   } else {
      // upscroll code

        var y = $("#sidebar").scrollTop();  //your current y position on the page
      $("#sidebar").scrollTop(y-10);


   }
   lastinfoscroll = st2;
});

I would like to detect when one of the divs are being scrolled, and then scroll both divs.

I can't seem to figure out how to get it fire on divs so that I can scroll both divs at once. Been stuck on this problem for ages. Also don't want to use Animate.

Any help would be greatly appreciated. Cheers

回答1:

.scroll() does fire on divs, and .scrollTop() does work on them, too. You can simplify your code: remove scroll position caching, and the calculation of current vs desired position, and the problem goes away :)

The snippet below synchronizes the scroll position in all $containers:

$( function () {
  var $containers = $( ".container" );

  $containers.scroll( _.throttle( syncScroll, 20, { leading: false } ) );

  function syncScroll () {
    var $this = $( this ),
        $other = $containers.not( this ),
        target = $this.scrollTop();

    if ( $other.scrollTop() !== target ) {
      $other.scrollTop( target );
    }

  }

} );

You can see it in action in this demo (code view).

Throttling is important, otherwise the inertia of scrolling with a mouse wheel would vanish (and you'd flood the CPU with garbage scroll events). I'm using Underscore here (_.throttle()), but any other implementation will do. You can control the extent of the lag with the second argument, currently set to 20ms.

The example here synchronizes the absolute scroll position, so it implies that the scrolled content is of the same height everywhere. For content of differing height, you need to go through a quick conversion and express the target position as a percentage, before converting it back to an absolute value to scroll the $other box to.