Auto-Scroll to next anchor at Mouse-wheel
Asked Answered
S

2

11

I have 5 anchors on my html page. Is there any way that the page scrolls automatically to the next anchor (#) by a single Mouse-wheel scroll? Is there a way that it happens regardless of the anchor's name? just to the next anchor.

Saucy answered 15/9, 2014 at 1:0 Comment(2)
Mousewheel click or mousewheel scroll?Flatiron
You could use the window.scroll() function along with the .next() function and the .scrollTop() functionRajah
G
27

This works in Chrome, IE, Firefox, Opera, and Safari:

(function() {
  var delay = false;

  $(document).on('mousewheel DOMMouseScroll', function(event) {
    event.preventDefault();
    if(delay) return;

    delay = true;
    setTimeout(function(){delay = false},200)

    var wd = event.originalEvent.wheelDelta || -event.originalEvent.detail;

    var a= document.getElementsByTagName('a');
    if(wd < 0) {
      for(var i = 0 ; i < a.length ; i++) {
        var t = a[i].getClientRects()[0].top;
        if(t >= 40) break;
      }
    }
    else {
      for(var i = a.length-1 ; i >= 0 ; i--) {
        var t = a[i].getClientRects()[0].top;
        if(t < -20) break;
      }
    }
    if(i >= 0 && i < a.length) {
      $('html,body').animate({
        scrollTop: a[i].offsetTop
      });
    }
  });
})();

Fiddle at http://jsfiddle.net/t6LLybx8/728/

How it works

To monitor the mouse wheel in most browsers, use $(document).on('mousewheel'). Firefox is the oddball, and it requires $(document).on('DOMMouseScroll').

To get the direction of the mouse wheel (up or down), use event.originalEvent.wheelDelta. Again, Firefox is the oddball, and you have to use -event.originalEvent.detail.

If the direction is a negative number, you're scrolling down the page. In that case, loop through each tag beginning with the first, until its first getClientRects() top is >= 40. (I used 40, in case the browser adds a default margin at the top of the viewport.)

If the direction is a positive number, you're scrolling up the page. In that case, loop through each tag beginning with the last, until its first getClientRects() top is < -20. (I used -20 to ensure we move up the page.)

The delay variable prevents the mouse wheel from scrolling too quickly. The entire function is wrapped in a closure, so delay remains a private variable.

Goldagoldarina answered 15/9, 2014 at 1:59 Comment(25)
@dcc, you're absolutely right. I've updated my code, and it should now work in all browsers.Goldagoldarina
Thank you Rick. Is there any chance to get smooth scrolling in this? The scroll jumps to the next anchor instead of scroll.Saucy
Sure. You can't animate scrollIntoView, but you can simulate it by animating scollTop to the a's offsetTop. I've updated my answer.Goldagoldarina
Hi @RickHitchcock, how can I put a pixel distance from the top? I have a header fixer, that is why is necessary add distance from top to windowMiriam
@ThallysonDias, not sure I understand, but you could possibly add the pixel offset here: scrollTop: a[i].offsetTop + pixel offsetGoldagoldarina
Can this be adopted to include spacebar scrolling? @RickHitchcockSlickenside
@RGilkes, see jsfiddle.net/t6LLybx8/202. Does that work for you? Tested in IE11 and Chrome only at the moment.Goldagoldarina
@RickHitchcock I'm curious to know what would be the AngularJS way?Lifeboat
@Kshitij, I haven't learned AngularJS, but that may be a question worth posting.Goldagoldarina
@RickHitchcock, In case you want to follow it, here is the link to the question.Lifeboat
is it just me that scroll up dosent work the same way as down?Ginny
@Dementic, what browser are you using?Goldagoldarina
Chrome Version 46.0.2490.71 m (Kudos for the fast answer)Ginny
Thanks, that's the same version I'm using. Seems to work fine, so maybe it's your mouse?Goldagoldarina
i find that hard to believe (support.logitech.com/product/…)Ginny
No one else has mentioned an issue with scroll up, and I can't replicate it, so I don't know what could be causing the problem.Goldagoldarina
A few years later may-b someone can help me... I get Uncaught TypeError: Cannot read property 'top' of undefined - On this line: var t = a[i].getClientRects()[0].top;Trujillo
@Blue, I'm surprised no one else has brought this up! That can happen if you're trying to scroll above the first anchor or beyond the last anchor. I've updated my answer to handle these cases.Goldagoldarina
@RickHitchcock Thank you for this but the proprety 'top' is still undefined.. I've been banging my head around this for the whole day and tried 100's of different things and the property still cant be read :)) I have other links on site also so is it possible to limit <a>'s to specific class like say .custom-achor ?Trujillo
Hmm, that I can't explain. Can you create a Fiddle? You can limit the anchors to a class by changing the a variable to: var a = $('a.custom-anchor');.Goldagoldarina
Oh, no guarantees that the code will work in Wordpress. Sorry!Goldagoldarina
Cool, but what if a paragraph is very long ?Bidden
@L.Trabacchin, if the paragraph is longer than the screen height, it might not make sense to auto-scroll. Alternatively, you could exclude that particular paragraph within the logic.Goldagoldarina
Instead I was thinking about inspecting if the scroll will cause the next element to enter the scroller and if it does do the autoscroll, instead let the default scroll behaviour. But i haven't implemented that yet, so i can't know if there are flaws in my thinking...Bidden
That's certainly doable, and it shouldn't take too much adjustment of my code to accomplish that.Goldagoldarina
A
1

let's say you have array of IDs.then you can do something like...

  var ancherList = ["id1","id2","id3"];
  var currentPosition = null;

  var mousewheelevent = 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll';
  $(document).on(mousewheelevent,function(e){
      var scrollToAncher function (id,speed){
          spd = speed ? "slow" //deafult value for the animation speed
          var ancherTag = $("a[name='"+ id +"']");
          $('html,body').animate({scrollTop: ancherTag.offset().top},spd);
      }
      e.preventDefault();
      var delta = e.originalEvent.deltaY ? -(e.originalEvent.deltaY) : e.originalEvent.wheelDelta ? e.originalEvent.wheelDelta : -(e.originalEvent.detail);
      if (delta > 0){
          console.log("up")
          //check your current position and target id
          switch(currentPosition){
            case null :
            case ancherList[0] :
              scrollToAncher(ancherList[1]);
              currentPosition = ancherList[1];
              break;
            case ancherList[1] :
              currentPosition = ancherList[2];
              scrollToAncher(ancherList[2]);
              break;
            case ancherList[2] :
              currentPosition = ancherList[0];
              scrollToAncher(ancherList[0]);
              break;              
          }
      } else {
          console.log("down")
          //do the same for mouse wheel down
      }
  });

code ain't tested.sorry if there was syntax error

Antoneantonella answered 15/9, 2014 at 1:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.