Crear una navegación por anclas con animación que resalte ítem activo

En el HTML:

<div id="main">
<div id="sidemenu">
<ul>
 <li class="selected"><a href="#home">Home</a></li>
 <li><a href="#work">Work</a></li>
 <li><a href="#blog">Blog</a></li>
 <li><a href="#projects">Projects</a></li>
 <li><a href="#about">About</a></li>
 <li><a href="#contact">Contact</a></li>
</ul>
</div>

En el CSS:

#main { width: 300px; margin: 0 auto; position: relative; }
#sidemenu { position: fixed; top: 50px; left: 20px; background: #ddd; }
#sidemenu ul { list-style-type: none; }
#sidemenu li { margin: 5px; padding: 5px; width: 100px; text-align: center; }
#sidemenu li.selected { background: #aaa; }
#sidemenu a { text-decoration: none; }

.content { height: 400px; border: #ddd 1px solid; margin: 10px 0 100px 10px; }

En el Javascript:

var topRange      = 200,  // measure from the top of the viewport to X pixels down
     edgeMargin    = 20,   // margin above the top or margin from the end of the page
     animationTime = 1200, // time in milliseconds
     contentTop = [];

$(document).ready(function(){ 

 // Stop animated scroll if the user does something
 $('html,body').bind('scroll mousedown DOMMouseScroll mousewheel keyup', function(e){
 if ( e.which > 0 || e.type == 'mousedown' || e.type == 'mousewheel' ){
  $('html,body').stop();
 }
})

 // Set up content an array of locations
 $('#sidemenu').find('a').each(function(){
  contentTop.push( $( $(this).attr('href') ).offset().top );
 })

 // Animate menu scroll to content
  $('#sidemenu').find('a').click(function(){
   var sel = this,
       newTop = Math.min( contentTop[ $('#sidemenu a').index( $(this) ) ], $(document).height() - $(window).height() ); // get content top or top position if at the document bottom
   $('html,body').stop().animate({ 'scrollTop' : newTop }, animationTime, function(){
    window.location.hash = $(sel).attr('href');
   });
   return false;
 })

 // adjust side menu
 $(window).scroll(function(){
  var winTop = $(window).scrollTop(),
      bodyHt = $(document).height(),
      vpHt = $(window).height() + edgeMargin;  // viewport height + margin
  $.each( contentTop, function(i,loc){
   if ( ( loc > winTop - edgeMargin && ( loc < winTop + topRange || ( winTop + vpHt ) >= bodyHt ) ) ){
    $('#sidemenu li')
     .removeClass('selected')
     .eq(i).addClass('selected');
   }
  })
 })

})

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

9 − 2 =