gpt4 book ai didi

javascript - 向下滚动到部分时突出显示菜单项

转载 作者:可可西里 更新时间:2023-11-01 02:13:51 25 4
gpt4 key购买 nike

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

当您向下滚动到具有与哈希链接相同的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');
}
});
});

现在的问题是,它突出显示了所有散列链接,而不是仅突出显示与该节有关系的散列链接。谁能指出错误,还是我忘记了什么?

最佳答案

编辑:

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

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

原始答案

不要将.active类添加到所有链接,而应标识href属性与该部分的ID相同的属性。

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

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

通过以上修改,您的代码将正确突出显示相应的链接。希望能帮助到你!

改善表现

即使这段代码可以完成工作,也远非最佳。无论如何,请记住:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. (Donald Knuth)



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

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

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

为了避免一次(每次触发事件)搜索DOM,您可以事先缓存jQuery对象(例如 document.ready上):
var $navigationLinks = $('#navigation > ul > li > a');
var $sections = $(".section");

然后,您可以将每个部分映射到相应的导航链接:
var sectionIdTonavigationLink = {};
$sections.each( function(){
sectionIdTonavigationLink[ $(this).attr('id') ] = $('#navigation > ul > li > a[href=\\#' + $(this).attr('id') + ']');
});

请注意 anchor 选择器中的两个反斜杠:哈希值“#”在CSS中具有特殊含义,因此 it must be escaped(感谢 @Johnnie)。

另外,您可以缓存每个节的位置(Bootstrap的 Scrollspy做到了)。但是,如果这样做,则需要记住每次更改时都要对其进行更新(用户调整窗口大小,通过ajax添加新内容,扩展子节等)。

优化事件处理程序:

假设用户正在一个区域内滚动:不需要更改 Activity 的导航链接。但是,如果您看一下上面的代码,您会发现它实际上发生了多次更改。在正确链接突出显示之前,所有先前的链接也将执行此操作(因为它们的相应部分还验证了 position >= target的条件)。

一种解决方案是迭代从下到上的节,第一个 .offset().top等于或小于 $(window).scrollTop的节是正确的节。是的, you can rely on jQuery returning the objects in the order of the DOM(从 version 1.3.2开始)。要从下到上进行迭代,只需按相反的顺序选择它们:
var $sections = $( $(".section").get().reverse() );
$sections.each( ... );

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

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

最后,如果正确突出显示了正确的导航链接,则您无需执行任何操作,因此请检查一下:
if ( !$navigationLink.hasClass( 'active' ) ) {
$navigationLinks.removeClass('active');
$navigationLink.addClass('active');
}

尽可能少地触发事件:

防止高级别事件(滚动,调整大小...)使您的网站变慢或无响应的最确定的方法是控制事件处理程序的调用频率:确保您无需检查需要突出显示哪个链接每秒100次!如果除了突出显示链接之外,还添加了一些奇特的视差效果,则可以快速解决简介问题。

在这一点上,请确保您要阅读有关 throttle ,反跳和requestAnimationFrame的信息。 This article是一个不错的讲座,它为您提供了其中三个的很好的概述。对于我们而言,节流最适合我们的需求。

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

我已经在代码段中实现了节流功能。从那里,您可以使用 underscore.jslodash之类的库来变得更加复杂,甚至更好(如果不需要整个库,则可以始终从那里提取节流功能)。

注意:环顾四周,您会发现更简单的 throttle 功能。请当心,因为它们可能会错过最后一个事件触发器(这是最重要的一个!)。

特殊情况:

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

在下面的代码段中,当该部分到达页面的顶部时,链接将突出显示。如果希望它们之前突出显示,则可以通过以下方式添加一个小的偏移量:
if (position + offset >= target) {

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

如果最后一部分太小而无法到达页面顶部,则可以在滚动条位于其最底部位置时突出显示其相应的链接:
if ( $(window).scrollTop() >= $(document).height() - $(window).height() ) {
// highlight the last link

考虑到一些浏览器支持问题。您可以阅读有关 herehere的更多信息。

片段和测试

最后,您在这里有一段摘录。请注意,我更改了一些变量的名称,以使其更具描述性。

// cache the navigation links 
var $navigationLinks = $('#navigation > ul > li > a');
// cache (in reversed order) the sections
var $sections = $($(".section").get().reverse());

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

// throttle function, enforces a minimum time interval
function throttle(fn, interval) {
var lastCall, timeoutId;
return function () {
var now = new Date().getTime();
if (lastCall && now < (lastCall + interval) ) {
// if we are inside the interval we wait
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
lastCall = now;
fn.call();
}, interval - (now - lastCall) );
} else {
// otherwise, we directly call the function
lastCall = now;
fn.call();
}
};
}

function highlightNavigation() {
// get the current vertical position of the scroll bar
var scrollPosition = $(window).scrollTop();

// iterate the sections
$sections.each(function() {
var currentSection = $(this);
// get the position of the section
var sectionTop = currentSection.offset().top;

// if the user has scrolled over the top of the section
if (scrollPosition >= sectionTop) {
// get the section id
var id = currentSection.attr('id');
// get the corresponding navigation link
var $navigationLink = sectionIdTonavigationLink[id];
// if the link is not active
if (!$navigationLink.hasClass('active')) {
// remove .active class from all the links
$navigationLinks.removeClass('active');
// add .active class to the current link
$navigationLink.addClass('active');
}
// we have found our section, so we return false to exit the each loop
return false;
}
});
}

$(window).scroll( throttle(highlightNavigation,100) );

// if you don't want to throttle the function use this instead:
// $(window).scroll( highlightNavigation );
#navigation {
position: fixed;
}
#sections {
position: absolute;
left: 150px;
}
.section {
height: 200px;
margin: 10px;
padding: 10px;
border: 1px dashed black;
}
#section5 {
height: 1000px;
}
.active {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="navigation">
<ul>
<li><a href="#section1">Section 1</a></li>
<li><a href="#section2">Section 2</a></li>
<li><a href="#section3">Section 3</a></li>
<li><a href="#section4">Section 4</a></li>
<li><a href="#section5">Section 5</a></li>
</ul>
</div>
<div id="sections">
<div id="section1" class="section">
I'm section 1
</div>
<div id="section2" class="section">
I'm section 2
</div>
<div id="section3" class="section">
I'm section 3
</div>
<div id="section4" class="section">
I'm section 4
</div>
<div id="section5" class="section">
I'm section 5
</div>
</div>


如果您有兴趣, this fiddle会测试我们所讨论的不同改进。

祝您编码愉快!

关于javascript - 向下滚动到部分时突出显示菜单项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32395988/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com