根据滚动位置更改CSS——重构错误代码



我编写了一个jQuery函数,它根据导航菜单项的引用部分是否在窗口中可见来更改其css值。

$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll <= 590) {
$("#menu-item-25 a").addClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 591 && scroll <= 1380) {
$("#menu-item-26 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 1381 && scroll <= 2545) {
$("#menu-item-22 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 2546 && scroll <= 2969) {
$("#menu-item-23 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-24 a").removeClass('blue');
}
else if (scroll >= 2970) {
$("#menu-item-24 a").addClass('blue');
$("#menu-item-25 a").removeClass('blue');
$("#menu-item-26 a").removeClass('blue');
$("#menu-item-22 a").removeClass('blue');
$("#menu-item-23 a").removeClass('blue');
}
});

它看起来非常难看。有没有更好的方法来实现这个目标?

之前的所有答案都会很好,因为你有多种方法可以让它变得更好,只需对CSS选择器进行一些更改,但如果你要在滚动事件中进行所有这些计算,你应该阅读这篇关于如何处理滚动事件的John Resign文章,特别是这部分:

将处理程序附加到窗口滚动事件是一个非常非常糟糕的主意。根据浏览器的不同,滚动事件可能会触发很多,在滚动回调中放入代码会减慢滚动页面的速度(这不是一个好主意)。因此,滚动处理程序的任何性能下降都只会使滚动的整体性能更加复杂。相反,最好使用某种形式的计时器每隔X毫秒检查一次,或者附加一个滚动事件,只在延迟后(甚至在给定的执行次数后,然后延迟)运行代码
-John辞去职务

所以,在你的情况下,我会这样做:

HTML:

<div class="menu">
<a id="menu-item-22">Link 1</a>
<a id="menu-item-23">Link 2</a>
<a id="menu-item-24">Link 3</a>
<a id="menu-item-25">Link 4</a>
<a id="menu-item-26">Link 5</a>
</div>

Jquery:

var didScroll = false;
$(window).scroll(function() {
didScroll = true;
});
setInterval(function() {
if ( didScroll ) {
didScroll = false;
var $el;
//Same that all the if else statements
switch (true) {
case (scroll >= 591 && scroll <= 1380):
$el = $("#menu-item-26 a");
break;
case (scroll >= 1381 && scroll <= 2545):
$el = $("#menu-item-22 a");
break;
case (scroll >= 2546 && scroll <= 2969):
$el = $("#menu-item-23 a");
break;
case (scroll >= 2970):
$el = $("#menu-item-24 a");
break;
default: //scroll<=590
$el = $("#menu-item-25 a");
}
//Removing blue class from all links
$('.menu a').removeClass('blue');
//Adding blue class to the matched element
$el.addClass('blue');
}
}, 50);

不应该使用它们的ID-访问一组公共元素

示例

<div class="menu">
<a id="menu-item-22 a">Link 1</a>
<a id="menu-item-23 a">Link 2</a>
<a id="menu-item-24 a">Link 3</a>
<a id="menu-item-25 a">Link 4</a>
</div>

1-.menu中的所有<a>中删除类

$(".menu a").removeClass("blue");

2-显示您想要的

$("#menu-item-25 a").addClass("red");

您也应该考虑缓存DOM选择器-

var menuItem22 = $("#menu-item-22 a")

然后像一样访问它

$(menuItem22).addClass('red')

这将阻止您在每次想要对元素执行操作时访问DOM。这在你的情况下不是绝对必要的,但这是一个很好的技巧,要记住

这个怎么样?

http://pastebin.com/SrtE3yxS

$(function() {
var highlighted = null,         // Keep track of previously selected
$menuItems  = $('#menu a'); // Grab all menu items once
// Which items at which points
var breakpoints = {
'#menu-item-25': 590,
'#menu-item-26': 1380,
'#menu-item-22': 2545,
'#menu-item-23': 2969,
'#menu-item-24': 99999
};
$(window).scroll(function() {
var scroll = $(window).scrollTop(),
selected = '#menu-item-24';  // default
// Loop through breakpoints to find the current one that should be selected
for (id in breakpoints) {
if (scroll <= breakpoints[id]) {
selected = id;
break;
}
}
// If the right one is already highlighted, do nothing
if (highlighted == id) {
return;
}
// Remove all
$menuItems.removeClass('blue');
// Add it to the one you need
$(id).addClass('blue');
});

});

您可以使用一个函数来做同样的事情。。

function menueHandle(ident, color, type){
for(var i = 0; i < ident.length; i++){
var handle = $("#menu-item-"+ident[i]+" a");
if(type == 'remove'){
handle.removeClass(color);
}else{
handle.addClass(color);
}
}
}
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll <= 590) {
menueHandle([25], 'blue', 'add');
menueHandle([26,26,22,23, 24], 'blue', 'remove');
}else if (scroll >= 591 && scroll <= 1380) {
menueHandle([26], 'blue', 'add');
menueHandle([25,26,22,23, 24], 'blue', 'remove');
}else if (scroll >= 1381 && scroll <= 2545) {
menueHandle([22], 'blue', 'add');
menueHandle([25,26,22,23, 24], 'blue', 'remove');
}else if (scroll >= 2546 && scroll <= 2969) {
menueHandle([23], 'blue', 'add');
menueHandle([25,26,22,23, 24], 'blue', 'remove');
}else if (scroll >= 2970) {
menueHandle([24], 'blue', 'add');
menueHandle([25,26,22,23], 'blue', 'remove');
} 

});

我想添加另一种方法(我个人最喜欢的)

  • 使用setTimeout()滚动事件处理

  • 使用getBoundingClientRect()检测视图中的元素

https://codepen.io/oriadam/pen/NLMqjN

var vertical_threshold = 3; // pixels inside the element for it to be considered in view
function element_in_view(e) {
if (e.style.display == "none") {
// when element is hidden, getBoundingClientRect() returns all 0
return false;
}
var r = e.getBoundingClientRect();
return (
r.top >= 0 && // vertical check 1
r.top <=
(innerHeight || document.documentElement.clientHeight) -
Math.min(r.height, vertical_threshold) // vertical check 2
/* CHECK HORIZONTAL SCROLL
&& r.left >= 0 // horizontal check 1
&& r.right <= (innerWidth || document.documentElement.clientWidth) // horizontal check 2
*/
);
}
function onScroll() {
console.log("onScroll");
$("li").each(function() {
this.classList.toggle("inview", element_in_view(this));
});
}
$(window).scroll(function() {
clearTimeout(window.scrollTO);
window.scrollTO = setTimeout(onScroll, 50);
}).trigger('scroll');

最新更新