Change active menu item depending on 'scroll' [closed]

4

Does anyone know how to do the effect that activates / deactivates menu items depending on the scroll? Like for example in the PHP of the Right Way site, the menu items activate / deactivate as the page scrolls.

I tried to analyze the source code of the page and I did not find out and as I do not know the name of the technique (?) I could not find anything on the internet.

    
asked by anonymous 25.05.2016 / 22:01

3 answers

5

I do not think this feature has any special names. I made an example where you can get an idea, it was with jquery and not with native javascript. If I do not help you in this way, say I'll withdraw the answer:

EXAMPLE

// animação scroll quando se clica no menu
$('span').on('click', function() {
  $("html, body").animate({
    scrollTop: $('#' +$(this).data('section')).offset().top // ir para a secção cujo o id é o valor do atributo 'data-section' do item do menu onde clicamos
  }, 500);
});

// guardamos todas as distancias de cada secção até ao todo da página e respetivo id
var alturas = {};
$('.section').each(function () {
  alturas[$(this).prop('id')] = $(this).offset().top; // ex: alturas['section_2'] = 600
});

// quando fazemos scoll vamos percorrer o nosso obj alturas e comparar a altura de cada secção com o que já andamos em scroll
$(window).on('scroll', function() {
  for(var seccao in alturas) {
    if($(window).scrollTop() >= alturas[seccao]) {
      $('span').removeClass('active'); // removemos a classe ative
      $('span[data-section="' +seccao+ '"]').addClass('active'); // adicionamos a class active ao item do menu cuja data-section é igual ao id da secção que está a uma maior ou igual distancia do topo do que aquela que percorremos com o scroll
    }
  }
});
body {
 margin:0;
}
nav {
  position:fixed;
  top:0;
  background-color: #ffffff;
  left:0;
  height:100%;
}
span {
  display:block;
  border:1px solid;
  cursor: pointer;
}
.active {
  background-color: red;
}
.section {
  height:600px;
  width:400px;
  border:1px solid;
  text-align:center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><nav><spanclass="active" data-section="section_1">
      Secção 1
   </span>
   <span data-section="section_2">
      Secção 2
   </span>
   <span data-section="section_3">
      Secção 3
   </span>
   <span data-section="section_4">
      Secção 4
   </span>
</nav>

<div id="section_1" class="section">
   Secção 1
</div>
<div id="section_2" class="section">
   Secção 2
</div>
<div id="section_3" class="section">
   Secção 3
</div>
<div id="section_4" class="section">
   Secção 4
</div>
    
25.05.2016 / 22:39
2

@Miguel's answer already has an example of how to do, so I'll just show the site code which was mentioned in the question.

How about "stealing" their source?

They use jQuery and anchors to do such functionality, as can be seen in the code below:

(function ($) {
    //Add current view's highlighting to the navigation

    /** helper for highlighting */
    function highlightNav(navLinks,id)
    {
        navLinks.filter('[href="/#'+id+'"]').addClass("active");
    }

    $(window).scroll(function() {
        //console.log("They see me scrollin, they hatin");

        //clear highlighting
        var navLinks = $('.site-navigation a');
        navLinks.removeClass("active");

        //calc current viewport
        var viewTop = $(window).scrollTop();
        var viewBottom = viewTop + $(window).height();

        //for all h1 and h2 elements, check if they are visible
        //performance tweak: stop each() after the first element is found to be behind view
        var previous = "";
        var foundOne = false;
        var fallback = "";
        $('h1, h2').each(function(i,e) {
            //get element position;
            var eTop = $(e).offset().top;
            var eBottom = eTop + $(e).height();
            var id=e.id;
            id = id.replace("_title", "");

            if (eTop >= viewTop) {
                //if we are passed the view and no heading was highlighted yet, store previous one as fallback
                if (! foundOne) {
                    fallback=previous;
                }
                if (eBottom <= viewBottom) {
                    highlightNav(navLinks, id);
                    foundOne = true;
                } else {
                    return false; //break the each(), the rest is below
                }
            }
            previous=id;
        });
        //no h1/h2 is in the viewport, so highlight the last one above
        if (! foundOne) {
            highlightNav(navLinks, fallback);
        }
    });
})(jQuery);

This code fetches the anchor that is in scroll and adds the active class to the menu item.

If you'd like to study more, this code can be found at passed by .

  

It's worth noting that I did not find the code source to post the copyright, so I posted what was found on the site quoted in the question and in Google searches.

    
25.05.2016 / 22:44
0

It seems that this effect is called Scrollspy. I found it on the Materialize CSS page

  

Scrollspy is a jQuery plugin that monitors certain elements and which   element is centered on the user's screen. Our main   This is demonstrated by our table of contents on all pages of   documentation on the right. Clicking on these links will also scroll   page for the element.

    
08.06.2016 / 13:14