jQuery - 滚动时更改背景颜色

13

我想在滚动时实现固定标题元素背景颜色的渐变。因此,当用户滚动一个完整的页面块网站时,标题会微妙地改变以补充块的颜色。我在这里几乎实现了这个效果,但是我无法确定如何测量已经滚动的距离作为更改的标志。

一些额外的信息:更改的滚动量为400px。背景颜色存储在数组中并被提取。参考我的jQuery代码如下:

$(document).ready(function(){
  var bgArray = ["#252525","#333333","#454545","#777777"];  
  var scrollHeight = 400;
  var scrolled = $(window).scrollTop(); //What is this measuring?

  $(window).scroll(function() { //Can these conditions be neatened into one function?
    if(scrolled < scrollHeight) {
      $('header').css('background', bgArray[0]);
    }
    if(scrolled > scrollHeight) { // i.e more than 400px
      $('header').css('background', bgArray[1]);
    }
    // and so on (800, 1200...)
  })
})

请参考笔记本以获取完整的代码。非常感谢您提供任何建议!


2
一些浏览器会为每个滚动像素触发滚动事件,从而降低性能。防抖技术可以帮助解决这个问题:http://benalman.com/projects/jquery-throttle-debounce-plugin/ - Martijn
谢谢,我应该在下面的答案中的哪里添加$.debounce? - Andyjm
2
$( window ).on('scroll', $.throttle( 250, function(){ /* Code goes here */ }) ); - Martijn
3个回答

9

更新解决方案(2019)

根据当前在header下方视图中的,滚动时为header设置background:

  • 因为header固定位置,我们可以使用$header.offset().top来获取窗口滚动的,

  • (当前在视图中的块的索引)是(窗口滚动的量)与(每个块的高度)之比,

  • 现在调整header的高度,当前在视图中的块的索引为Math.floor(($header.offset().top + headerHeight) / sectionHeight)

请参见以下简化演示:

$(function() {
  var $header = $('header'),
    $window = $(window),
    bgArray = ["#252525", "red", "blue", "green"],
    headerHeight = 50,
    sectionHeight = 400;

  $window.scroll(function() {
    $header.css('background', bgArray[Math.floor(($header.offset().top + headerHeight)
        / sectionHeight)]);
  });
});
:root {
  --header: 50px; /* header height */
  --block: 400px; /* block height */
}

* {
  box-sizing: border-box; /* include padding in width / height calculations */
}

body {
  margin: 0; /* reset default margin of body */
}

header {
  height: var(--header); /* sets height of header */
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  color: #FFF;
  padding: 12px 0;
  background: #252525; /* initial background */
  transition: background 1s ease;
}

.container {
  margin: 0 auto;
}

.wrap>div {
  height: var(--block); /* sets height of each block */
  text-align: center;
}

p {
  margin: 0; /* reset margin of p */
}

.block-1 {
  background: #27AACC;
  color: #FFF;
}

.block-2 {
  background: #668E99;
  color: #FFF;
}

.block-3 {
  background: #4AFFC1;
  color: #444;
}

.block-4 {
  background: #FF8F8A;
  color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
  <div class="container">
    Website Title.
  </div>
</header>

<div class="wrap">
  <div class="block-1">
    <div class="container">
      <p>This pen was made to solve a problem on a project...</p>
    </div>
  </div>
  <div class="block-2">
    <div class="container">
      <p>...I needed a sticky header with thr right bg colour.</p>
    </div>
  </div>
  <div class="block-3">
    <div class="container">
      <p>But this conflicted with the footer, which was the same colour...</p>
    </div>
  </div>
  <div class="block-4">
    <div class="container">
      <p>So the solution was to subtley change the header's bg on scroll</p>
    </div>
  </div>
</div>


原始解决方案

通过使用 $(window).scrollTop() > $('.block-1').offset().top来检查每个块相对于窗口滚动了多少(scrollTop)。因此,现在我们可以使用这个方法在进入块时改变颜色 - 请参见下面的演示:

$(document).ready(function() {
  var $header = $('header'),
    $window = $(window),
    bgArray = ["#252525", "#333333", "#454545", "#777777"],
    headerHeight = $header.outerHeight();

  $window.scroll(function() {
    for (var i = 1; i < 5; i++) {
      if ($window.scrollTop() + headerHeight > $('.block-' + i).offset().top) {
        $header.css('background', bgArray[i - 1]);
      }
    }
  });
});
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,700');
body {
  font-family: 'Roboto', sans-serif;
  font-size: 30px;
  font-weight: 300;
  margin-top: 0;
}

header {
  width: 100%;
  height: 50px;
  line-height: 50px;
  position: fixed;
  font-size: 24px;
  font-weight: 700;
  color: #FFF;
  padding: 12px 0;
  margin: 0;
  background: #252525;
  transition: background 1s ease;
}

.wrap {
  padding-top: 74px;
  margin: 0;
}

.container {
  width: 960px;
  margin: 0 auto;
  overflow: hidden;
}

.block-1,
.block-2,
.block-3,
.block-4 {
  height: 400px;
  text-align: center;
}

p {
  margin-top: 185px;
}

.block-1 {
  background: #27AACC;
  color: #FFF;
}

.block-2 {
  background: #668E99;
  color: #FFF;
}

.block-3 {
  background: #4AFFC1;
  color: #444;
}

.block-4 {
  background: #FF8F8A;
  color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>
  <div class="container">
    Website Title.
  </div>
</header>
<div class="wrap">
  <div class="block-1">
    <div class="container">
      <p>This pen was made to solve a problem on a project...</p>
    </div>
  </div>
  <div class="block-2">
    <div class="container">
      <p>...I needed a sticky header with thr right bg colour.</p>
    </div>
  </div>
  <div class="block-3">
    <div class="container">
      <p>But this conflicted with the footer, which was the same colour...</p>
    </div>
  </div>
  <div class="block-4">
    <div class="container">
      <p>So the solution was to subtley change the header's bg on scroll</p>
    </div>
  </div>
</div>

请注意,这种解决方案在每次浏览器调用滚动更新时不必要地循环遍历各个部分 - 我不喜欢这种方式。

1
为什么要用for循环? - n4m31ess_c0d3r
2
循环结构使代码更加整洁,这个解决方案对我来说最有意义!非常感谢。 - Andyjm
1
你想要毁掉浏览器吗?因为这就是如何毁掉浏览器。我会稍微修复一下。 - Martijn
2
保存了一些参考资料。在Firefox中,这仍然会影响性能,因为它会在每个像素上触发滚动事件。我强烈推荐使用http://benalman.com/projects/jquery-throttle-debounce-plugin/。 - Martijn
而且你是对的 - 去抖动 对于性能来说非常推荐... - kukkuz
显示剩余5条评论

7
你正在将scrolled用作固定变量,你应该直接在条件语句中使用它。这将使得所有包含在wrap div中的元素都变得动态。
$(document).ready(function(){
var bgArray = ["#252525","#333333","#454545","#777777"];
$(window).scroll(function() { 
    for(var i = 1; i < bgArray.length; i++) {
      if ($(window).scrollTop() > $('.wrap div:nth-child(' + i + ')').offset().top) {
        $('header').css('background', bgArray[i-1]);        
      }
    }
  });
})

1
这很好,解释得很清楚!但是似乎只处理了数组中的前两个项目? - Andyjm
1
当页面滚动到 800px1200px...时怎么办? - n4m31ess_c0d3r
一个注意点 - 为了防止不必要的浏览器重绘,你可以添加一个条件来检查标题是否已经是你即将设置的颜色。 - Pat

4
尝试这样做:

试试像这样:

$(document).ready(function(){
  var bgArray = ["#252525","#333333","#454545","#777777"];  
  var scrollHeight = 400;

  $(window).scroll(function() {

    var scrolled = $(window).scrollTop(); 

    var index=Number((scrolled/scrollHeight).toFixed());

    if(bgArray[index]!=undefined)
        $('header').css('background', bgArray[index]);

  });
})

这是当前滚动位置,因此它应该在 $(window).scrollTop() 中。


1
在这里使用模数(%)可能存在缺陷,因为425%400将返回25,但最大索引是3 - n4m31ess_c0d3r

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接