【问题标题】:Change Active Menu Item on Page Scroll?更改页面滚动上的活动菜单项?
【发布时间】:2012-04-02 16:08:54
【问题描述】:

当您向下滚动页面时,活动菜单项会发生变化。这是怎么做到的?

【问题讨论】:

    标签: jquery html


    【解决方案1】:

    由容器(通常是窗口)的binding to the scroll event 完成。

    快速示例:

    // Cache selectors
    var topMenu = $("#top-menu"),
        topMenuHeight = topMenu.outerHeight()+15,
        // All list items
        menuItems = topMenu.find("a"),
        // Anchors corresponding to menu items
        scrollItems = menuItems.map(function(){
          var item = $($(this).attr("href"));
          if (item.length) { return item; }
        });
    
    // Bind to scroll
    $(window).scroll(function(){
       // Get container scroll position
       var fromTop = $(this).scrollTop()+topMenuHeight;
    
       // Get id of current scroll item
       var cur = scrollItems.map(function(){
         if ($(this).offset().top < fromTop)
           return this;
       });
       // Get the id of the current element
       cur = cur[cur.length-1];
       var id = cur && cur.length ? cur[0].id : "";
       // Set/remove active class
       menuItems
         .parent().removeClass("active")
         .end().filter("[href='#"+id+"']").parent().addClass("active");
    });​
    

    参见上面的in action at jsFiddle,包括滚动动画。

    【讨论】:

    • 如果您的菜单混合了页面 ID 和常规页面,请先放置页面 ID 链接,然后将 menuItems = topMenu.find("a"), 更改为 menuItems = topMenu.find("a").slice(0,4),,将 4 替换为 [your on -页面链接 - 1].
    • 我实际上使用了 menuItems = topMenu.find('a[href^="#"]'),因此只返回锚链接。像魅力一样工作。
    • 小提琴坏了。你能修好吗?谢谢
    • @m1crdy 感谢您的提醒。它已被修复。似乎 jQuery edge 中的某些东西破坏了它。适用于 2.1.0 :)
    • @JoelAzevedo 似乎嘶嘶声已经改变。更新了答案和测试用例以使用 jQuery 2.2。
    【解决方案2】:

    只需检查我的代码和狙击手和演示链接:

        // Basice Code keep it 
        $(document).ready(function () {
            $(document).on("scroll", onScroll);
    
            //smoothscroll
            $('a[href^="#"]').on('click', function (e) {
                e.preventDefault();
                $(document).off("scroll");
    
                $('a').each(function () {
                    $(this).removeClass('active');
                })
                $(this).addClass('active');
    
                var target = this.hash,
                    menu = target;
                $target = $(target);
                $('html, body').stop().animate({
                    'scrollTop': $target.offset().top+2
                }, 500, 'swing', function () {
                    window.location.hash = target;
                    $(document).on("scroll", onScroll);
                });
            });
        });
    
    // Use Your Class or ID For Selection 
    
        function onScroll(event){
            var scrollPos = $(document).scrollTop();
            $('#menu-center a').each(function () {
                var currLink = $(this);
                var refElement = $(currLink.attr("href"));
                if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
                    $('#menu-center ul li a').removeClass("active");
                    currLink.addClass("active");
                }
                else{
                    currLink.removeClass("active");
                }
            });
        }
    

    demo live

    $(document).ready(function () {
        $(document).on("scroll", onScroll);
        
        //smoothscroll
        $('a[href^="#"]').on('click', function (e) {
            e.preventDefault();
            $(document).off("scroll");
            
            $('a').each(function () {
                $(this).removeClass('active');
            })
            $(this).addClass('active');
          
            var target = this.hash,
                menu = target;
            $target = $(target);
            $('html, body').stop().animate({
                'scrollTop': $target.offset().top+2
            }, 500, 'swing', function () {
                window.location.hash = target;
                $(document).on("scroll", onScroll);
            });
        });
    });
    
    function onScroll(event){
        var scrollPos = $(document).scrollTop();
        $('#menu-center a').each(function () {
            var currLink = $(this);
            var refElement = $(currLink.attr("href"));
            if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
                $('#menu-center ul li a').removeClass("active");
                currLink.addClass("active");
            }
            else{
                currLink.removeClass("active");
            }
        });
    }
    body, html {
        margin: 0;
        padding: 0;
        height: 100%;
        width: 100%;
    }
    .menu {
        width: 100%;
        height: 75px;
        background-color: rgba(0, 0, 0, 1);
        position: fixed;
        background-color:rgba(4, 180, 49, 0.6);
        -webkit-transition: all 0.4s ease;
        -moz-transition: all 0.4s ease;
        -o-transition: all 0.4s ease;
        transition: all 0.4s ease;
    }
    .light-menu {
        width: 100%;
        height: 75px;
        background-color: rgba(255, 255, 255, 1);
        position: fixed;
        background-color:rgba(4, 180, 49, 0.6);
        -webkit-transition: all 0.4s ease;
        -moz-transition: all 0.4s ease;
        -o-transition: all 0.4s ease;
        transition: all 0.4s ease;
    }
    #menu-center {
        width: 980px;
        height: 75px;
        margin: 0 auto;
    }
    #menu-center ul {
        margin: 0 0 0 0;
    }
    #menu-center ul li a{
    		padding: 32px 40px;
    }
    #menu-center ul li {
        list-style: none;
        margin: 0 0 0 -4px;
        display: inline;
    
    }
    .active, #menu-center ul li a:hover  {
        font-family:'Droid Sans', serif;
        font-size: 14px;
        color: #fff;
        text-decoration: none;
        line-height: 50px;
    	background-color: rgba(0, 0, 0, 0.12);
    	padding: 32px 40px;
    
    }
    a {
        font-family:'Droid Sans', serif;
        font-size: 14px;
        color: black;
        text-decoration: none;
        line-height: 72px;
    }
    #home {
        background-color: #286090;
        height: 100vh;
        width: 100%;
        overflow: hidden;
    }
    #portfolio {
        background: gray; 
        height: 100vh;
        width: 100%;
    }
    #about {
        background-color: blue;
        height: 100vh;
        width: 100%;
    }
    #contact {
        background-color: rgb(154, 45, 45);
        height: 100vh;
        width: 100%;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <!--	<div class="container">	--->
    			<div class="m1 menu">
    			<div id="menu-center">
    				<ul>
    					<li><a class="active" href="#home">Home</a>
    
    					</li>
    					<li><a href="#portfolio">Portfolio</a>
    
    					</li>
    					<li><a href="#about">About</a>
    
    					</li>
    					<li><a href="#contact">Contact</a>
    
    					</li>
    				</ul>
    			</div>
    			</div>
    			<div id="home"></div>
    			<div id="portfolio"></div>
    			<div id="about"></div>
    			<div id="contact"></div>

    【讨论】:

      【解决方案3】:

      只是为了补充@Marcus Ekwall 的回答。 这样做只会得到锚链接。如果您将锚链接和常规链接混合使用,您将不会遇到问题。

      jQuery(document).ready(function(jQuery) {            
                  var topMenu = jQuery("#top-menu"),
                      offset = 40,
                      topMenuHeight = topMenu.outerHeight()+offset,
                      // All list items
                      menuItems =  topMenu.find('a[href*="#"]'),
                      // Anchors corresponding to menu items
                      scrollItems = menuItems.map(function(){
                        var href = jQuery(this).attr("href"),
                        id = href.substring(href.indexOf('#')),
                        item = jQuery(id);
                        //console.log(item)
                        if (item.length) { return item; }
                      });
      
                  // so we can get a fancy scroll animation
                  menuItems.click(function(e){
                    var href = jQuery(this).attr("href"),
                      id = href.substring(href.indexOf('#'));
                        offsetTop = href === "#" ? 0 : jQuery(id).offset().top-topMenuHeight+1;
                    jQuery('html, body').stop().animate({ 
                        scrollTop: offsetTop
                    }, 300);
                    e.preventDefault();
                  });
      
                  // Bind to scroll
                  jQuery(window).scroll(function(){
                     // Get container scroll position
                     var fromTop = jQuery(this).scrollTop()+topMenuHeight;
      
                     // Get id of current scroll item
                     var cur = scrollItems.map(function(){
                       if (jQuery(this).offset().top < fromTop)
                         return this;
                     });
      
                     // Get the id of the current element
                     cur = cur[cur.length-1];
                     var id = cur && cur.length ? cur[0].id : "";               
      
                     menuItems.parent().removeClass("active");
                     if(id){
                          menuItems.parent().end().filter("[href*='#"+id+"']").parent().addClass("active");
                     }
      
                  })
              })
      

      基本上我换了

      menuItems = topMenu.find("a"),
      

      通过

      menuItems =  topMenu.find('a[href*="#"]'),
      

      将所有链接与某处的锚点匹配,并更改所有必要的内容以使其与此一起工作

      jsfiddle上查看它的实际应用

      【讨论】:

      • 当菜单比页面大时,如何为垂直菜单扩展此功能? pyze.com/product/docs/index.html 当用户滚动右侧的内容时,我想激活左侧的相应菜单并在需要时滚动菜单以显示活动菜单。任何指针表示赞赏。
      • 这真是太神了,谢谢。但是,我会将属性选择器从 *= 更改为 ^=。如果您使用 *= 那么即使这是一个外部链接,您也会捕捉到 google.com/#something 之类的东西。属性选择器在这里得到了很好的解释:w3schools.com/css/css_attribute_selectors.asp
      【解决方案4】:

      如果您希望接受的答案在 JQuery 3 中起作用,请更改如下代码:

      var scrollItems = menuItems.map(function () {
          var id = $(this).attr("href");
          try {
              var item = $(id);
            if (item.length) {
              return item;
            }
          } catch {}
        });
      

      我还添加了一个 try-catch 以防止 javascript 在该 id 没有元素时崩溃。随意改进它;)

      【讨论】:

      • 这对我仍然不起作用。它返回一个错误“Uncaught SyntaxError: Unexpected token 'var'”
      猜你喜欢
      • 2013-02-16
      • 2018-01-09
      • 2020-05-23
      • 2020-06-02
      • 1970-01-01
      • 1970-01-01
      • 2021-03-17
      • 2023-03-25
      相关资源
      最近更新 更多