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

时间:2015-04-26 03:33:46

标签: jquery wordpress

我编写了一个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');
    }
});

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

5 个答案:

答案 0 :(得分:7)

以前的所有答案都可以正常使用,因为您有多种方法可以更好地对CSS选择器进行一些更改,但是如果您将在scroll事件中执行所有这些计算,则应该阅读此{{3关于如何处理滚动事件,特别是这部分:

  

将处理程序附加到窗口滚动事件是一个非常非常糟糕的想法。根据浏览器的不同,滚动事件可以激活很多,将代码放入滚动回调会减慢任何滚动页面的尝试(不是一个好主意)。因此,滚动处理程序中的任何性能下降只会影响整体滚动的性能。相反,最好使用某种形式的计时器来检查每X毫秒或附加滚动事件,并且只在延迟之后运行代码(或者甚至在给定次数的执行之后 - 然后延迟)。     - John Resign

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

HTML:

ICollection<T>

Jquery的:

<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>

答案 1 :(得分:1)

不应该使用他们的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 - <a>

中的所有.menu删除班级
$(".menu a").removeClass("blue");

2 - 显示您想要的

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

您应该 考虑caching the DOM selectors -

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

然后像访问它一样:

$(menuItem22).addClass('red')

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

答案 2 :(得分:1)

这个怎么样?

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');

});

});

答案 3 :(得分:0)

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

 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');
} 

});

答案 4 :(得分:0)

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

  • 使用 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');