如何在滚动时添加类到部分,循环问题

时间:2015-11-11 18:17:44

标签: javascript jquery loops

我正在构建一个包含多个部分的网站,我希望每次该部分都在视口中时为该部分提供一个活动状态。我的HTML结构看起来像这样:

<header></header>
<section id="intro"></section>
<section id="schools"></section>
<section id="quotes"></section>
<section id="projects"></section>

依旧......

在CSS中,我的部分由VH单位定义。为了使用定义的垂直断点,我计算了它们并得出了一个我在Js中用作数组的序列。

// Cache the Window object
var windowScroll, $h, pos;
$window = $(window);

// Cache the height of the window for future reference
// as section height = 100vh, 2nd section = h * 2, 3rd = h * 3, and so on
$h = window.innerHeight;

// pos[0] is the end of the header,
// pos[1] is the end of the 1st section
pos = [$h * 1, $h * 2.1, $h * 3.2, $h * 4.7];

// Cache the sections in an array
sections = document.getElementsByTagName("section");

如果我写这篇文章,它会工作:

if ((!$(sections[0]).hasClass('active')) && (windowScroll <= pos[0]) && (windowScroll <= pos[1])) {
    console.log("Scroll is contained between " + pos[0] + " and " + pos[1]);                        
    $(sections[0]).addClass('active'); //
}

但是我想避免为每个部分编写它。如果我尝试使用 for 每个循环,它会立即将类添加到每个部分,而不会在视口中定位该部分。

// This is not working
$(sections).each(function(i) {
    if(!$(this).hasClass('active')){
        if ((windowScroll <= pos[i]) && (windowScroll <= pos[i+1])) {
                console.log("Scroll is contained between " + pos[i] + " and " + pos[i+1]);
                $('section').eq(i).addClass('active');
        }
    }
});

我错过了什么?

这是一个小提琴:https://jsfiddle.net/0fct57p1/12/

1 个答案:

答案 0 :(得分:0)

以下是解决方案:https://jsfiddle.net/xtpqwjur/

代码:

// Cache the Window object
var windowScroll, $h, pos;
$window = $(window);

// Cache the height of the window for future reference
// as section height = 100vh, 2nd section = h * 2, 3rd = h * 3, and so on
$h = window.innerHeight;

// pos[0] is the end of the header,
// pos[1] is the end of the 1st section
pos = [$h * 1, $h * 2.1, $h * 3.2, $h * 4.7, $h * 6.2];

// Cache the sections in an array
sections = document.getElementsByTagName("section");

// Avoid loop on scroll function
var scroll_timeout, scroll_trigger_time, userScrolled; // Cache variables
var userScrolled = false; // The scroll is false by default
var scroll_trigger_time = 100; // Trigger after x ms of scroll

function on_window_scroll() {
    if (userScrolled) {
        userScrolled = false;
        $('section.active').removeClass('active');        
        $(sections).each(function (i, value) {
          if ( !$(this).hasClass('active') && (windowScroll >= pos[i] && windowScroll <= pos[i+1]) ) {
            console.log('scroll between ' + pos[i] + ' and ' + pos[i+1]);
            $('section.active').removeClass('active');
            $(sections[i]).addClass('active');
          }
        });
    }
}

window.addEventListener("scroll", function () {
    userScrolled = true;
    if(scroll_timeout !== null) clearTimeout(scroll_timeout); // Clear the scroll cache at if time is out
    scroll_timeout = setTimeout(on_window_scroll, scroll_trigger_time); // Trigger a function within the scroll
    windowScroll = Math.floor(window.pageYOffset); // Listen to the scroll position

});

主要问题是您的比较运算符 - 您正在执行

(windowScroll <= pos[i]) && (windowScroll <= pos[i+1])

表示,“如果滚动位置比(部分)少,而且比(部分+ 1)少。

我改为:

(windowScroll >= pos[i] && windowScroll <= pos[i+1]

表示,“如果滚动位置等于或大于(部分),则小于或等于(部分+ 1)。

您可以将上限(<=pos[i+1])更改为小于(而不是小于或等于)以防止重叠条件。