滚动时当前部分未在导航中正确突出显示

时间:2015-03-25 14:43:14

标签: jquery

我正在创建一个带有锚链接导航的长页面。向下滚动页面时,导航中的相应链接将突出显示以匹配您所在的部分。

它工作正常,但我在页面上也有一个部分,导航中没有锚链接。问题是,通过添加此部分,它会破坏我的部分顺序,这会破坏正确的选定状态。

这是一个代码示例,向您展示一个示例。 http://codepen.io/anon/pen/jEdKBp - 请注意,当您向下滚动到“新部分”时,导航中的“声明”链接会突出显示,这是错误的!

我需要做什么才能突出显示当前链接?

这是我的代码......

HTML

    <nav id="prod-menu">
  <div class="wrapper">
      <ul>
        <li><a href="#features">Features</a></li>
        <li><a href="#claims">Claims</a></li>
        <li><a href="#guides">Guides</a></li>
        <li><a href="#reviews">Reviews</a></li>
        <li><a href="#faq">FAQs</a></li>
      </ul>
  </div>
</nav> 


<section class="prod-hero"></section>

<div class="wrapper">

    <section class="tile js-panel pad0">        

        <section id="features" class="prod-panels"> 
            <h2>Features</h2>
        </section>

  <section class="prod-panels"> 
            <h2>New section</h2>
    <p>I do not want this section to appear in the nav</p>
        </section>

        <section id="claims" class="prod-panels">   
            <h2>Claims</h2>
        </section>

        <section id="guides" class="prod-panels">   
            <h2>Guides</h2>
        </section>

        <section id="reviews" class="prod-panels">  
            <h2>Reviews</h2>
        </section>

        <section id="faq" class="prod-panels">  
            <h2>FAQs</h2>
        </section>

    </section>
</div>

的jQuery

var homeH = $( window ).height(),
    pH = [];
pH.push("0"); 

// create array with panel heights
for (var s=1; s<5; s++) { 
  var po = $(".js-panel section:nth-child("+s+")").position();
  pH.push( Math.round(po.top) );
};

$( window ).scroll(function() {      

  // toggle top menu selection
  for (var i=0;i<6;i++) {
    if ( $( window ).scrollTop() > pH[i]+900 ) { 
      $("#prod-menu ul li").removeClass("sel");
      $("#prod-menu ul li:nth-child("+(i+1)+")").addClass("sel");
     }
  };

});

3 个答案:

答案 0 :(得分:4)

我已经更改了代码中的一些内容,我希望这样:http://codepen.io/anon/pen/pvmXgK就是您想拥有的内容。

首先,我改变了这一行:

var po = $(".js-panel section:nth-child("+s+")").position();

var po = $(".js-panel section.nav-section:eq("+s+")").offset();

并将类nav-section添加到应该属于导航的所有html部分。

切换功能现在被拆分为两个for循环,但这可能不是必需的。 ;)

所有代码(没有css部分) 的 HTML

<nav id="prod-menu">
  <div class="wrapper">
    <ul>
      <li><a href="#features">Features</a></li>
      <li><a href="#claims">Claims</a></li>
      <li><a href="#guides">Guides</a></li>
      <li><a href="#reviews">Reviews</a></li>
      <li><a href="#faq">FAQs</a></li>
    </ul>
</div>
</nav> 


<section class="prod-hero"></section>
 <div class="wrapper">
    <section class="tile js-panel pad0">        
        <section id="features" class="nav-section prod-panels"> 
        <h2>Features</h2>
        </section>
        <section class="prod-panels">   
            <h2>New section</h2>
            <p>I do not want this section to appear in the nav</p>
        </section>

        <section id="claims" class="nav-section prod-panels">   
            <h2>Claims</h2>
        </section>
        ....    

   </section>
 </div>

<强> JS

var homeH = $( window ).height(),
pH = [];
var clicked = false;
// create array with panel heights
for (var s=0; s<5; s++) { 
   var po = $(".js-panel section.nav-section:eq("+s+")").offset();
   pH.push( Math.round(po.top) );
};
$( window ).scroll(function() {
 if (clicked === true) {
    return;
 } else if (clicked == "fuzzy") {
    clicked = false;
    return;
 }
 // toggle top menu
 if ( $( window ).scrollTop() < homeH/2) {
   $("#prod-menu ul li").removeClass("sel");
   $("#prod-menu").css("top", "-55px");
 } else {
   $("#prod-menu").css("top", "0");
 };
 $("#prod-menu ul li").removeClass("sel");

 // toggle top menu selection
 var st = $( window ).scrollTop();
 for (var i=4;i>=0;i--) {
   if ( st > pH[i] ) { 
     $("#prod-menu ul li:eq("+i+")").addClass("sel");
     break;
   }
 };

});

// animating anchor link scrolling
// snippet from css-tricks 
// css-tricks.com/snippets/jquery/smooth-scrolling

$("a[href*=#]:not([href=#])").click(function() { 
  if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
   var liEle = $(this).parent("li");
   var target = $(this.hash);

   target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
   if (target.length) {
      clicked = true;
      $('body').animate({
       scrollTop: target.offset().top-50
      }, 700, function() {
        clicked = "fuzzy";
        $("#prod-menu ul li").removeClass("sel");
        liEle.addClass("sel");
      });

    return false;
   }
 }
});

答案 1 :(得分:2)

我已经分叉你的代码笔,试图使用另一种方法

http://codepen.io/anon/pen/myNRzR

    var homeH = $( window ).height(),
    pH = new Array();

// create array with panel heights

   $(".js-panel section").each(function(){
      var elm = $(this);
       var po = elm.position();
      pH.push({
        top : Math.round(po.top),
        element : elm
      });
    });


pH.sort(function(a, b) {
    if (a.top > b.top)
      return -1;
    if (a.top < b.top)
      return 1;
    // a doit être égale à b
    return 0;
});
var ord = {
  hasScrolled : true,
  locked : false
};
var ticker = function(){

  if(ord.hasScrolled){
    var menu = $("#prod-menu"),        
     actTop = $( window ).scrollTop(), 
     level = actTop + menu.height();
    ord.locked = true;
    ord.hasScrolled = false; 
    for(var i in pH){
      var o = pH[i];

      if(level > o.top && level < (o.top + o.element.height())){
        menu.css("top", "0");
        $("#prod-menu ul li").removeClass("sel");
        $("#prod-menu").find("a[href='#"+ o.element.attr("id") +"']").parent().addClass("sel");
        break;
      }
    }





    ord.locked = false;
  }
}

setInterval(ticker, 250);

$( window ).scroll(function() {
 ord.hasScrolled = true && !ord.locked;
  // toggle top menu


});

// animating anchor link scrolling
// snippet from css-tricks 
// css-tricks.com/snippets/jquery/smooth-scrolling

$("a[href*=#]:not([href=#])").click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top-50
        }, 700);
        return false;
      }
    }
  });

使用代码而不是onScrollEvent:它的工作正常。

如果将所有内容包装在插件中会更好。

答案 2 :(得分:2)

我决定对此进行一次尝试。我喜欢在考虑灵活性的情况下处理这样的事情,尽可能地删除硬编码值,并考虑动态页面流。在我的分支中,我不使用你想链接到top-nav的面板上的类,而是使用href和面板ID来利用那些匹配所隐含的链接。

var navPanels = $();
$('#prod-menu a').each(function() {
    navPanels = navPanels.add($(this.hash));    // easy array of nav panels according to nav items
});

采用这种方法,您可以简单地添加或减去导航项和面板而无需其他类。此外,如果它们改变高度或移动,因为堆栈中它们上面的另一个元素导致偏移量发生变化,从一开始就有一个offset()。top值的数组在滚动时将不匹配,因此在滚动时检查。然后偏移检查变为:

navPanels.each(function() {
    var $p = $(this)    // current panel in loop

    if ( $( window ).scrollTop() + $('#prod-menu').outerHeight() >= $p.offset().top) { 
        $("#prod-menu ul li").removeClass("sel");
        $('#prod-menu a').filter('[href="#'+$p.attr('id')+'"]').parent().addClass("sel");
    }
});

我还考虑了整个脚本中的最高导航高度,以便当该部分滚过可视区域时会突出显示导航项目,该区域从顶部导航下方开始。

这种方法没有做的是删除您不希望在导航中显示的部分的突出显示。相反,它只是在突出显示之前离开导航。

这是完整的JS:

$(function() {
    var homeH = $( window ).height(),
        navPanels = $();

    $('#prod-menu a').each(function() {
        navPanels = navPanels.add($(this.hash));    // easy array of nav panels according to nav items
    });

    $( window ).scroll(function() {
        // toggle top menu
        if ( $( window ).scrollTop() < homeH/2) {
            $("#prod-menu ul li").removeClass("sel");
            $("#prod-menu").css("top", ($('#prod-menu').outerHeight()*-1));
        } 
        else {
            $("#prod-menu").css("top", "0");
        };

        // toggle top menu selection
        navPanels.each(function() {
            var $p = $(this)    // current panel in loop

            if ( $( window ).scrollTop() + $('#prod-menu').outerHeight() >= $p.offset().top) { 
                $("#prod-menu ul li").removeClass("sel");
                $('#prod-menu a').filter('[href="#'+$p.attr('id')+'"]').parent().addClass("sel");
            }
        });
    });

    // animating anchor link scrolling
    // snippet from css-tricks 
    // css-tricks.com/snippets/jquery/smooth-scrolling
    $("a[href*=#]:not([href=#])").click(function() {
        if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
            var target = $(this.hash);
            target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
            if (target.length) {
                $('html,body').animate({
                    scrollTop: target.offset().top-$('#prod-menu').outerHeight()
                }, 700);
                return false;
            }
        }
    });
});

完整的笔在这里:http://codepen.io/anon/pen/MYNmbb

编辑我很无聊所以我决定对此进行扩展。如果您希望导航在您滚动到不在导航栏上的部分时不亮,您可以更改&#34;切换顶部菜单选项&#34;功能如下,检查面板底部相对于可视区域:

// toggle top menu selection
navPanels.each(function() {
    var $p = $(this)    // current panel in loop
    var viewTop = $( window ).scrollTop() + $('#prod-menu').outerHeight();
    if (viewTop  >= $p.offset().top) {
        $("#prod-menu ul li").removeClass("sel");
        if ($p.offset().top + $p.outerHeight() > viewTop) { 
            $('#prod-menu a').filter('[href="#'+$p.attr('id')+'"]').parent().addClass("sel");
        }
    }
});

然后,当您滚动到不在导航中的部分时,在您点击导航中的另一部分之前,不会突出显示任何内容。

同样,完整的笔在此处可见:http://codepen.io/anon/pen/emqWEW