เปลี่ยนรายการเมนูที่ใช้งานบนเลื่อนหน้าหรือไม่


97

เมื่อคุณเลื่อนหน้าลงรายการเมนูที่ใช้งานอยู่จะเปลี่ยนไป วิธีนี้ทำได้อย่างไร?

คำตอบ:


211

ทำได้โดยเชื่อมโยงกับเหตุการณ์เลื่อนของคอนเทนเนอร์ (โดยปกติจะเป็นหน้าต่าง)

ตัวอย่างด่วน:

// 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");
});​

ดูการดำเนินการด้านบนที่ jsFiddleรวมถึงภาพเคลื่อนไหวแบบเลื่อน


2
หากเมนูของคุณมีรหัสบนหน้าและหน้าปกติผสมกันให้วางลิงก์รหัสบนหน้าก่อนจากนั้นเปลี่ยนmenuItems = topMenu.find("a"),เป็นmenuItems = topMenu.find("a").slice(0,4),แทนที่4ด้วย [ลิงก์ในหน้าของคุณ - 1]
Stephen Saucier

6
จริงๆแล้วฉันใช้ menuItems = topMenu.find ('a [href ^ = "#"]') จึงส่งคืนเฉพาะลิงก์จุดยึด ใช้งานได้เหมือนมีเสน่ห์
Julian K

1
สายซอขาดแล้ว คุณช่วยแก้ไขได้ไหม Thx
m1crdy

1
@ m1crdy ขอบคุณสำหรับหัว ได้รับการแก้ไขแล้ว ดูเหมือนว่ามีบางอย่างใน jQuery edge ทำให้มันพัง ใช้งานได้ดีกับ 2.1.0 :)
mekwall

1
@JoelAzevedo ดูเหมือน Sizzle จะเปลี่ยนไป อัปเดตคำตอบและกรณีทดสอบเพื่อทำงานกับ jQuery 2.2
mekwall

16

เพียงตรวจสอบ Code และ Sniper และลิงค์สาธิตของฉัน:

    // 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");
            }
        });
    }

การสาธิตสด


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เมื่อผู้ใช้เลื่อนเนื้อหาทางด้านขวาฉันต้องการเปิดใช้งานเมนูที่เหมาะสมทางด้านซ้ายและเลื่อนเมนูหากจำเป็นเพื่อแสดงเมนูที่ใช้งานอยู่ คำแนะนำใด ๆ ที่ได้รับการชื่นชม
Dickey Singh

1
นี่คือพระเจ้ามากขอบคุณ อย่างไรก็ตามฉันจะเปลี่ยนตัวเลือกแอตทริบิวต์จาก * = เป็น ^ = หากคุณใช้ * = คุณก็จะพบสิ่งต่างๆเช่นgoogle.com/#somethingแม้ว่านี่จะเป็นลิงก์ภายนอกก็ตาม ตัวเลือกแอตทริบิวต์ได้รับการอธิบายอย่างดีที่นี่: w3schools.com/css/css_attribute_selectors.asp
Jacques

0

หากคุณต้องการให้คำตอบที่ยอมรับทำงานใน JQuery 3 ให้เปลี่ยนรหัสดังนี้:

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

ฉันยังเพิ่มการลองจับเพื่อป้องกันไม่ให้จาวาสคริปต์หยุดทำงานหากไม่มีองค์ประกอบตามรหัสนั้น อย่าลังเลที่จะปรับปรุงให้ดียิ่งขึ้น;)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.