3

I am trying to make this scrolleffect work on a website. When a users scroll down it automagically has to go to the next slide. When the users scrolls up it has to go one slide back. I have tried a lot of things using the onScroll function in Jquery, but none of them seem to work.

I use the following script to check whether the users scrolls up or down.

var lastScrollTop = 0;
var check = 1;
var scrollDirection = 'down';

var scrollBottom = $(window).scrollTop() + $(window).height();
    $(window).scroll(function(event) {
        slideHeight = $('.slide').height();
         var st = $(this).scrollTop();
         if (st > lastScrollTop){
             scrollDirection = 'down';
             if (check == 1){
                $('body').scrollTo( {top:'0px', left:'100%'}, 800 );
     check = 0;    
 }

         } else {
             scrollDirection = 'up';
         }
         lastScrollTop = st;


         console.log('ScrollDirection: '+ scrollDirection);

    });

I am not coming any further than this. The (test)website where developing takes place is: http://bit.ly/RBcffY If anyone has experience with this kind of function it would be really helpful.

Sebass van Boxel
  • 2,514
  • 1
  • 22
  • 37
  • I am not an expert at all on UI design but I have a suggestion. Make all divs but the first one invisible at the time page loaded. When the user scrolls hide the first one and activate/make visible the second one. You may require to keep a track of the current one or next one or last scrolled direction etc. All this is of course based on the assumption that you can capture SCROLL event in a browser. To have scroll bar you may need to append dummy content to actual content of the div – Ertunç Oct 20 '12 at 13:15
  • Possible duplicate: [Treating each div as a “page” when scrolling](http://stackoverflow.com/q/12849439/520779) – mgibsonbr Oct 21 '12 at 20:25

2 Answers2

12

The jquery.mousewheel plugin can be used to capture the mouse wheel even when no scrolling happened (contrary to $.scroll). This way you can both detect that the mouse wheel was moved and prevent the scrolling from happening. Then it's just a matter to performing the animated scrolling yourself.

var scrollingScreen = false;
$("body").mousewheel(function(event, delta) {
    if ( !scrollingScreen ) {
        scrollingScreen = true; // Throttles the call
        var top = $("body").scrollTop() || // Chrome places overflow at body
                  $("html").scrollTop();   // Firefox places it at html
        // Finds slide headers above/below the current scroll top
        var candidates = $(".slide").filter(function() {
            if ( delta < 0 )
                return $(this).offset().top > top + 1;
            else
                return $(this).offset().top < top - 1;
        });
        // If one of more are found, updates top
        if ( candidates.length > 0 ) {
            if ( delta < 0 )
                top = candidates.first().offset().top;
            else if ( delta > 0 )
                top = candidates.last().offset().top;
        }
        // Performs an animated scroll to the right place
        $("html,body").animate({ scrollTop:top }, 800, "easeInOutQuint", function() {
            scrollingScreen = false; // Releases the throttle
        });
    }
    return false; // Prevents default scrolling
});​

Working example at jsFiddle. This is pretty consistent with the behavior of the reference you showed, and you could add extra effects as needed - by inserting code either before the animate or in its callback function, to perform them before or after the scrolling respectively. (Obs.: the fiddle, running in an iframe, cannot access scrollTop in some browsers, for security reasons, so it stores the top variable globally; however, the code as shown in the answer should work fine in a standalone page)

Note: both in the reference site and in my example, middle clicking and moving the mouse scrolls at will. You might want to prevent that or not, your choice. Nonetheless, the updated example scrolls to a specific point instead of just addind some delta, like you suggested in your question - $('.slide').height(). The reason is to account for the possibility that different slides have different heights. Also, knowing exactly which slide you're showing allows you to properly set the location's hash.

See also this related question for more info.

Community
  • 1
  • 1
mgibsonbr
  • 21,755
  • 7
  • 70
  • 112
  • The scroll looks quite randomly in the jsFiddle. One time is scroll 50 pixels, the other time 100 pixels. – Sebass van Boxel Oct 23 '12 at 10:16
  • 1
    @SebassvanBoxel I fixed some browser quirks, tested it both in the fiddle and as a standalone html, and went the last mile to eliminate the delta - now it will scroll to the next/previous slide relative to the current scrollTop, regardless of slide size. Check the updated answer. – mgibsonbr Oct 23 '12 at 12:57
  • Any idea how this could work in combination with the menu? This doesn't trigger the current scroll top. So when scrolling after using the menu is doesn't work anymore. – Sebass van Boxel Oct 23 '12 at 14:46
  • Which menu are you talking about? The browser's? The pop-up? A `select` element in the page? Please clarify, because I couldn't reproduce the problem. But it should be noted that, when scrolling using the bars or the arrow keys/page up/down or middle clicking, the fiddle will not work properly (because of the `iframe` issue), but in a standalone page it will. The code in the answer above was tested this way, and it always moves relative to the current position, no matter how the user came to it. – mgibsonbr Oct 23 '12 at 15:05
  • If you check out this page: http://bit.ly/RBcffY. Try to click on the menu-item 'contact' (Navigates to the 4th slide) and try to scroll back up after that with your mouse. The scroll will go to the first slide instead of going to the slide before 'contact'. Also see this screencapture: http://www.youtube.com/watch?v=zOgvDcH80Pg&feature=youtu.be – Sebass van Boxel Oct 24 '12 at 07:24
  • 1
    I checked the source of your page (jquery.scrollControl.js) and found two problems: 1) You got the `return false` in the wrong place, it should be **outside** the `if ( _MOUSEOVER_IN_PROGRESS == false)` block (the way it is, if you hover `TEST OM TE KIJKEN HOEVEEL IK NOU MAG ZEGGEN` and scroll, it will behave oddly); 2) You used the fiddle code, not the answer code - `var top` should not be a global and keep state between scrolls, it should be local to the `mousewheel` callback and get the **current** value of `scrollTop`. As explained before, the global var was a workaround for jsFiddle only. – mgibsonbr Oct 24 '12 at 15:39
  • Hello @mgibsonbr i am using scrollorama i am satisfied with your fiddle that is exactly the same what i want but that is not working in my page could you please suggest me something else – Abhay Singh Nov 26 '14 at 06:36
  • @abhay9455 I suggest opening a new question, it's hard to help without knowing your code etc, besides other people can help too (and the new question can help other people too). Since you're using a specific library, that's a bit out of scope of this question IMHO. – mgibsonbr Nov 26 '14 at 10:23
  • actually that plugins required jquery-1.7.1.min.js & in your code you have used 1.7.2.js so my problem is this when i used 1.7.2 my site stop working so could you please suggest me can i use jquery-1.7.1.min.js & 1.7.2.js together ? – Abhay Singh Nov 26 '14 at 11:16
1

Here's my version used for scrolling DIV.

Btw. it's better to use object.stop(), to have it smoother on scroll change.

var vi = $('.box'), vis = $('.box .inbox');

// both events needed for Firefox
vi.on('mousewheel DOMMouseScroll', function(e) {
    
    var eo = e.originalEvent;
    var xy = eo.wheelDelta || -eo.detail; //shortest possible code
    
    var isScrollUp = xy /120 > 0;
        
    if (vi.hasClass('scrolling'+(isScrollUp ? '1' : '0'))) return; // no change
    var top = vi.scrollTop();
    var candidates = vis.filter(function() {
     if ( !isScrollUp )
      return this.offsetTop > top;
     else
      return jQuery(this).offset().top < - 1;
    });
    
    if (candidates.length > 0) {
     if (!isScrollUp)
      top = candidates.first()[0].offsetTop;
     else
      top = candidates.last()[0].offsetTop;
    }
    vi.addClass('scrolling'+(isScrollUp ? '1' : '0')).stop().animate({ scrollTop:top }, 300, "swing", function() {
     vi.removeClass('scrolling1 scrolling0');
    });
    return false; // no default
   });

<!-- begin snippet: js hide: false console: true babel: false -->
BODY{
padding:10px;
}
.box{
 height:300px;
 overflow:scroll;
 position:relative;
}

.inbox{
background:purple;height:300px;font-size:35px;color:#fff;font-weight:bold;
}
.inbox:nth-child(2n){background:lightblue;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

<div class="box">
<div class="inbox">1 -- SCROLLIT</div>
<div class="inbox">2</div>
<div class="inbox">3</div>
<div class="inbox">4</div>
<div class="inbox">5</div>
<div class="inbox">6</div>
</div>
Martin Zvarík
  • 2,120
  • 22
  • 27