Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
446 views
in Technique[技术] by (71.8m points)

javascript - 向下滚动到部分时突出显示菜单项(Highlight Menu Item when Scrolling Down to Section)

I know this question have been asked a million times on this forum, but none of the articles helped me reach a solution.

(我知道在这个论坛上已经问过这个问题一百万遍了,但是没有一篇文章能帮助我找到解决方案。)

I made a little piece of jquery code that highlights the hash-link when you scroll down to the section with the same id as in the hash-link.

(当您向下滚动到与哈希链接具有相同ID的部分时,我制作了一段小片段的jQuery代码,突出显示了哈希链接。)

$(window).scroll(function() {
    var position = $(this).scrollTop();

    $('.section').each(function() {
        var target = $(this).offset().top;
        var id = $(this).attr('id');

        if (position >= target) {
            $('#navigation > ul > li > a').attr('href', id).addClass('active');
        }
    });
});

The problem now is that it highlights all of the hash-links instead of just the one that the section has a relation to.

(现在的问题是,它突出显示了所有散列链接,而不是仅显示与该节相关的散列链接。)

Can anyone point out the mistake, or is it something that I forgot?

(谁能指出错误,还是我忘记了什么?)

  ask by Jens Kvist translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

EDIT:(编辑:)

I have modified my answer to talk a little about performance and some particular cases.

(我修改了答案,只谈了一些性能和一些特殊情况。)

If you are here just looking for code, there is a commented snippet at the bottom.

(如果您只是在这里寻找代码,则在底部有一段注释。)


Original answer(原始答案)

Instead of adding the .active class to all the links, you should identify the one which attribute href is the same as the section's id .

(不要将.active 添加到所有链接中,而应标识一个属性href与该节的id相同的类。)

Then you can add the .active class to that link and remove it from the rest.

(然后,您可以将.active 添加到该链接,然后将其从其余链接中删除。)

        if (position >= target) {
            $('#navigation > ul > li > a').removeClass('active');
            $('#navigation > ul > li > a[href=#' + id + ']').addClass('active');
        }

With the above modification your code will correctly highlight the corresponding link.

(通过以上修改,您的代码将正确突出显示相应的链接。)

Hope it helps!

(希望能帮助到你!)


Improving performance(改善表现)

Even when this code will do its job, is far from being optimal.

(即使这段代码可以完成工作,也远非最佳。)

Anyway, remember:

(无论如何,请记住:)

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

(我们应该忘记效率低下的问题,例如大约97%的时间:过早的优化是万恶之源。)

Yet we should not pass up our opportunities in that critical 3%.

(然而,我们不应放弃我们那临界的3%的机会。)

( Donald Knuth )

(( 唐纳德·努斯 ))

So if, event testing in a slow device, you experience no performance issues, the best you can do is to stop reading and to think about the next amazing feature for your project!

(因此,如果在速度较慢的设备中进行事件测试,而没有遇到性能问题,那么您最好的办法就是停止阅读并考虑项目的下一个令人惊叹的功能!)

There are, basically, three steps to improve the performance:

(基本上,可以通过三个步骤来提高性能:)

Make as much previous work as possible:

(进行尽可能多的先前工作:)

In order to avoid searching the DOM once and again (each time the event is triggered), you can cache your jQuery objects beforehand (eg on document.ready ):

(为了避免一次(每次触发事件)搜索DOM,可以预先缓存jQuery对象(例如,在document.ready ):)

var $navigationLinks = $('#navigation > ul > li > a');
var $sections = $(".section"); 

Then, you can map each section to the corresponding navigation link:

(然后,您可以将每个部分映射到相应的导航链接:)

var sectionIdTonavigationLink = {};
$sections.each( function(){
    sectionIdTonavigationLink[ $(this).attr('id') ] = $('#navigation > ul > li > a[href=\#' + $(this).attr('id') + ']');
});

Note the two backslashes in the anchor selector: the hash ' # ' has a special meaning in CSS so it must be escaped (thanks @Johnnie ).

(请注意锚定选择器中的两个反斜杠:哈希值“ ”在CSS中具有特殊含义,因此必须将其转义 (感谢@Johnnie )。)

Also, you could cache the position of each section (Bootstrap's Scrollspy does it).

(另外,您可以缓存每个节的位置(Bootstrap的Scrollspy做到了)。)

But, if you do it, you need to remember to update them every time they change (the user resizes the window, new content is added via ajax, a subsection is expanded, etc).

(但是,如果这样做,则需要记住每次更改时都要对其进行更新(用户调整窗口大小,通过ajax添加新内容,扩展子节等)。)

Optimize the event handler:

(优化事件处理程序:)

Imagine that the user is scrolling inside one section: the active navigation link doesn't need to change.

(想象一下,用户正在一个区域滚动:不需要更改活动的导航链接。)

But if you look at the code above you will see that actually it changes several times.

(但是,如果您看一下上面的代码,您会发现它实际上发生了多次更改。)

Before the correct link get highlighted, all the previous links will do it as well (because their corresponding sections also validate the condition position >= target ).

(在正确链接突出显示之前,所有先前的链接也将执行此操作(因为它们的相应部分还验证了条件position >= target )。)

One solution is to iterate the sections for the bottom to the top, the first one whose .offset().top is equal or smaller than $(window).scrollTop is the correct one.

(一种解决方案是将底部的部分循环到顶部,第一个部分的.offset().top等于或小于$(window).scrollTop是正确的部分。)

And yes, you can rely on jQuery returning the objects in the order of the DOM (since version 1.3.2 ).

(是的, 您可以依靠jQuery以DOM的顺序返回对象 (从1.3.2版开始 )。)

To iterate from bottom to top just select them in inverse order:

(要从下到上进行迭代,只需按相反的顺序选择它们:)

var $sections = $( $(".section").get().reverse() );
$sections.each( ... );

The double $() is necessary because get() returns DOM elements, not jQuery objects.

(双重$()是必需的,因为get()返回DOM元素,而不是jQuery对象。)

Once you have found the correct section, you should return false to exit the loop and avoid to check further sections.

(找到正确的部分后,应return false退出循环并避免检查其他部分。)

Finally, you shouldn't do anything if the correct navigation link is already highlighted, so check it out:

(最后,如果正确突出显示了正确的导航链接,则您无需执行任何操作,因此请检查一下:)

if ( !$navigationLink.hasClass( 'active' ) ) {
    $navigationLinks.removeClass('active');
    $navigationLink.addClass('active');
}

Trigger the event as less as possible:

(尽可能少地触发事件:)

The most definitive way to prevent high-rated events (scroll, resize...) from making your site slow or unresponsive is to control how often the event handler is called: sure you don't need to check which link needs to be highlighted 100 times per second!

(防止高级别事件(滚动,调整大小...)使您的网站变慢或无响应的最确定的方法是控制事件处理程序的调用频率:确保您无需检查需要突出显示哪个链接每秒100次!)

If, besides the link highlighting, you add some fancy parallax effect you can ran fast intro troubles.

(如果除了突出显示链接之外,还添加了一些奇特的视差效果,则可以快速解决简介问题。)

At this point, sure you want to read about throttle, debounce and requestAnimationFrame.

(在这一点上,请确保您要阅读有关节流,防抖动和requestAnimationFrame的信息。)

This article is a nice lecture and give you a very good overview about three of them.

(本文是一次不错的演讲,并为您提供了其中三个的很好的概述。)

For our case, throttling fits best our needs.

(对于我们而言,节流最适合我们的需求。)

Basically, throttling enforces a minimum time interval between two function executions.

(基本上,节流会强制两个函数执行之间的最短时间间隔。)

I have implemented a throttle function in the snippet.

(我已经在代码段中实现了节流功能。)

From there you can get more sophisticated, or even better, use a library like underscore.js or lodash (if you don't need the whole library you can always extract from there the throttle function).

(从那里您可以变得更复杂,甚至更好,可以使用underscore.jslodash之类的库(如果不需要整个库,可以随时从其中提取节流功能)。)

Note: if you look around, you will find more simple throttle functions.

(注意:环顾四周,您会发现更简单的油门功能。)

Beware of them because they can miss the last event trigger (and that is the most important one!).

(当心它们,因为它们会错过最后一个事件触发器(这是最重要的一个!)。)

Particular cases:(特殊情况:)

I will not include these cases in the snippet, to not complicate it any further.

(我不会在代码段中包含这些案例,以免使其进一步复杂化。)

In the snippet below, the links will get highlighted when the section reaches the very top of the page.

(在下面的代码段中,当该部分到达页面的顶部时,链接将突出显示。)

If you want them highlighted before, you can add a small offset in this way:

(如果希望它们之前突出显示,则可以通过以下方式添加一个小的偏移量:)

if (position + offset >= target) {

This is particullary useful when you have a top navigation bar.

(当您具有顶部导航栏时,这特别有用。)

And if your last section is too small to reach the top of the page, you can hightlight its corresponding link when the scrollbar is in its bottom-most position:

(如果最后一部分太小而无法到达页面顶部,则可以在滚动条位于其最底部位置时突出显示其相应的链接:)

if ( $(window).scrollTop() >= $(document).height() - $(window).height() ) {
    // highlight the last link

There are some browser support issues thought.

(考虑到一些浏览器支持问题。)

You can read more about it here and here .

(您可以在这里这里阅读更多有关它的<a href="https://stackoom.com/link/aHR0cHM6Ly9zdGFja292ZXJmbG9


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...