首页 > 解决方案 > 在滚动时更改徽标 div 背景颜色

问题描述

我正在尝试使用and实现slip-scroll parallax类型效果。当屏幕向下滚动时,右上角的徽标将更改其背景以与下面的内容形成对比。左侧还有一个导航按钮可以执行相同的操作。CSSJavaScript

到目前为止我有这个...

// Detect request animation frame
var scroll = window.requestAnimationFrame ||
  window.webkitRequestAnimationFrame ||
  window.mozRequestAnimationFrame ||
  window.msRequestAnimationFrame ||
  window.oRequestAnimationFrame
  // IE Fallback, you can even fallback to onscroll
  ||
  function(callback) {
    window.setTimeout(callback, 1000 / 60)
  };
var lastPosition = -1;

// my Variables
var lastSection = false;
var replaceItemTop = -1;
var replaceItemBottom = -1;
var replaceItemHeight = -1;

// The Scroll Function
function loop() {
  var top = window.pageYOffset;
  // my variables

  // my sections to calculate stuff
  var sections = document.querySelectorAll('.section');
  var replaceContainer = document.querySelectorAll('.js-replace');
  var replaceItem = document.querySelectorAll('.js-replace__item');

  if (replaceItem.length > 0) {
    // get top position of item from container, because image might not have loaded
    replaceItemTop = parseInt(replaceContainer[0].getBoundingClientRect().top);
    replaceItemHeight = replaceItem[0].offsetHeight;
    replaceItemBottom = replaceItemTop + replaceItemHeight;
  }

  var sectionTop = -1;
  var sectionBottom = -1;
  var currentSection = -1;

  // Fire when needed
  if (lastPosition == window.pageYOffset) {
    scroll(loop);
    return false;
  } else {
    lastPosition = window.pageYOffset;

    // Your Function
    Array.prototype.forEach.call(sections, function(el, i) {
      sectionTop = parseInt(el.getBoundingClientRect().top);
      sectionBottom = parseInt(el.getBoundingClientRect().bottom);

      // active section
      if ((sectionTop <= replaceItemBottom) && (sectionBottom > replaceItemTop)) {
        // check if current section has bg
        currentSection = el.classList.contains('section--bg');

        // switch class depending on background image
        if (currentSection) {
          replaceContainer[0].classList.remove('js-replace--reverse');
        } else {
          replaceContainer[0].classList.add('js-replace--reverse')
        }
      }
      // end active section

      // if active Section hits replace area
      if ((replaceItemTop < sectionTop) && (sectionTop <= replaceItemBottom)) {
        // animate only, if section background changed
        if (currentSection != lastSection) {
          document.documentElement.style.setProperty('--replace-offset', 100 / replaceItemHeight * parseInt(sectionTop - replaceItemTop) + '%');
        }
      }
      // end active section in replace area

      // if section above replace area
      if (replaceItemTop >= sectionTop) {
        // set offset to 0 if you scroll too fast
        document.documentElement.style.setProperty('--replace-offset', 0 + '%');
        // set last section to current section
        lastSection = currentSection;
      }

    });

  }

  // Recall the loop
  scroll(loop)
}

// Call the loop for the first time
loop();

window.onresize = function(event) {
  loop();
};
/* variables */

:root {
  /* this value is going to be changed by javascript */
  --replace-offset: 50%;
  --replace-offset-2: calc((100% - var(--replace-offset)) * -1)
}

a {
  text-decoration: none;
}


/* set image position */

img {
  vertical-align: bottom;
}

.footer {
  background-color: black;
  color: white;
  padding-top: 50px;
  padding-bottom: 50px;
  text-align: center;
}


/* without fixed header this makes no sense */

.header {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 9;
}

.header_nav {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  left: 0;
  z-index: 9;
}

.logo {
  background-color: white;
  display: inline-block;
  border: solid;
  padding: 10px;
  border-radius: 10px;
  font-size: 2em;
}

.logo a {
  color: black;
}

.logo--invert {
  background-color: black;
  color: white;
  border-color: white;
}

.logo--invert a {
  color: white;
}

.sidelogo {
  background-color: white;
  display: inline-block;
  border: solid;
  padding: 10px;
  border-radius: 10px;
  font-size: 2em;
}

.sidelogo a {
  color: black;
}

.sidelogo--invert {
  background-color: black;
  color: white;
  border-color: white;
}

.sidelogo--invert a {
  color: white;
}

.section {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
}

section--1 {
  height: 100vh;
  width: 100%;
}

.hero {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("https://www.w3schools.com/howto/photographer.jpg");
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

.section--2 {
  background: white;
}

.section--3 {
  background: black;
  color: white;
}


/**
  This is the interesting part
**/


/* align content above each other without absolute */

.js-replace {
  display: grid;
}

.js-replace__item {
  grid-row: -1 / 1;
  grid-column: -1 / 1;
  overflow: hidden;
  will-change: transform;
}


/* item to replace with */

.js-replace__item {
  transform: translateY(calc(var(--replace-offset) * 1));
}

.js-replace__content {
  /* fixes problem with calculating correct height in js */
  border: 1px solid transparent;
  will-change: transform;
  transform: translateY(calc(var(--replace-offset) * -1));
}


/* previous replace item*/

.js-replace__item--active {
  transform: translateY(calc(var(--replace-offset-2) * 1));
}

.js-replace__item--active .js-replace__content {
  transform: translateY(calc(var(--replace-offset-2) * -1));
}


/* REVERSE ANIMATION */

.js-replace--reverse .js-replace__item {
  transform: translateY(calc(var(--replace-offset-2) * 1));
}

.js-replace--reverse .js-replace__content {
  transform: translateY(calc(var(--replace-offset-2) * -1));
}


/* previous replace item*/

.js-replace--reverse .js-replace__item--active {
  transform: translateY(calc(var(--replace-offset) * 1));
}

.js-replace--reverse .js-replace__item--active .js-replace__content {
  transform: translateY(calc(var(--replace-offset) * -1));
}
<body class="body">

  <div class="header">

    <!-- replace content -->
    <div class="header__logo js-replace">

      <!-- item to replace -->
      <div class="js-replace__item  js-replace__item--active">
        <div class="js-replace__content">
          <div class="logo"><a href="#">Logo</a></div>
        </div>
      </div>
      <!-- end item to replace -->

      <!-- item to replace with -->
      <div class="js-replace__item">
        <div class="js-replace__content">
          <div class="logo logo--invert"><a href="#">Logo</a></div>
        </div>
      </div>
      <!-- end item to replace with -->

    </div>
    <!-- end replace content -->

  </div>

  <div class="header_nav">

    <!-- replace content -->
    <div class="header__side js-replace">

      <!-- item to replace -->
      <div class="js-replace__item  js-replace__item--active">
        <div class="js-replace__content">
          <div class="sidelogo"><a href="#">Nav</a></div>
        </div>
      </div>
      <!-- end item to replace -->

      <!-- item to replace with -->
      <div class="js-replace__item">
        <div class="js-replace__content">
          <div class="sidelogo sidelogo--invert"><a href="#">Nav</a></div>
        </div>
      </div>
      <!-- end item to replace with -->

    </div>
    <!-- end replace content -->

  </div>

  <main class="main">

    <section class="section--1 section">
      <div class="hero">
      </div>
    </section>

    <section class="section--2 section section--bg">
      <h1>Section 2</h1>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
        Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis
        tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan
        porttitor, facilisis luctus, metus</p>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
        Mauris placerat eleifend leo.</p>
    </section>

    <section class="section--3  section">
      <h1>Section 3</h1>
      <p>
        <strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em>        Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
        sagittis tempus lacus enim ac dui. <a href="#">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.
      </p>
      <h2>Header Level 2</h2>
      <ol>
        <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
        <li>Aliquam tincidunt mauris eu risus.</li>
      </ol>
      <blockquote>
        <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus
          turpis elit sit amet quam. Vivamus pretium ornare est.</p>
      </blockquote>
      <h3>Header Level 3</h3>
      <ul>
        <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
        <li>Aliquam tincidunt mauris eu risus.</li>
      </ul>
    </section>

    <section class="section--4 section  section--bg">
      <h1>Section 4</h1>
      <p>
        Some great section 4 content
      </p>
      <ul>
        <li>This is a list item</li>
        <li>This is a list item</li>
        <li>This is a list item</li>
        <li>This is a list item</li>
        <li>This is a list item</li>
      </ul>
    </section>

    <section class="section--5 section section--bg">
      <h1 class="section__title">
        Section 5
      </h1>
      <p>
        This is some random content for section 5
      </p>
    </section>

  </main>

  <footer class="footer section">

    <form action="#" method="post">
      <div>
        <label for="name">Text Input:</label>
        <input type="text" name="name" id="name" value="" tabindex="1" />
      </div>
      <div>
        <h4>Radio Button Choice</h4>
        <label for="radio-choice-1">Choice 1</label>
        <input type="radio" name="radio-choice-1" id="radio-choice-1" tabindex="2" value="choice-1" />
        <label for="radio-choice-2">Choice 2</label>
        <input type="radio" name="radio-choice-2" id="radio-choice-2" tabindex="3" value="choice-2" />
      </div>
      <div>
        <label for="select-choice">Select Dropdown Choice:</label>
        <select name="select-choice" id="select-choice">
          <option value="Choice 1">Choice 1</option>
          <option value="Choice 2">Choice 2</option>
          <option value="Choice 3">Choice 3</option>
        </select>
      </div>
      <div>
        <label for="textarea">Textarea:</label>
        <textarea cols="40" rows="8" name="textarea" id="textarea"></textarea>
      </div>
      <div>
        <label for="checkbox">Checkbox:</label>
        <input type="checkbox" name="checkbox" id="checkbox" />
      </div>
      <div>
        <input type="submit" value="Submit" />
      </div>
    </form>

  </footer>

</body>

右侧的徽标按预期运行,当您向下滚动页面时,背景会发生变化。

但是,左侧的导航无法正常工作,我认为它需要添加一些偏移量,因为当前导航更改时它会更改

有人知道我哪里出错了吗?

标签: javascriptjqueryhtmlcss

解决方案


考虑到您的代码,您将需要复制您的逻辑以使其适用于这两个元素。您将需要调整top第二个元素的变量,使其不再是屏幕顶部,而是屏幕顶部 + 元素的偏移量。

这是另一个想法,它更多地依赖 CSS 更少的 JS 代码来获得几乎相同的结果:

window.onscroll = function() {
  var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
  document.documentElement.style.setProperty('--scroll-var', scroll+"px");
}
:root {
  --scroll-var: 0px;
}


a {
  text-decoration: none;
}


/* set image position */

img {
  vertical-align: bottom;
}

.footer {
  background-color: #fff;
  color: #000;
  padding-top: 50px;
  padding-bottom: 50px;
  text-align: center;
}


/* without fixed header this makes no sense */

.header {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 9;
}

.header_nav {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  left: 0;
  z-index: 9;
}

.logo,
.sidelogo{
  background:
    repeating-linear-gradient(to bottom,
        #fff 0,#fff 100vh,
        #000 100vh,#000 200vh) top/100% 600vh no-repeat padding-box,
     repeating-linear-gradient(to bottom,
        #000 0,#000 100vh,
        #fff 100vh,#fff 200vh) top/100% 600vh no-repeat border-box;
  display: inline-block;
  border: solid transparent;
  border-radius: 10px;
  font-size: 2em;
}
.logo a,
.sidelogo a{
  display:block;
  padding: 10px;
  background:
    repeating-linear-gradient(to bottom,
        #000 0,#000 100vh,
        #fff 100vh,#fff 200vh) top/100% 600vh no-repeat;
  background-clip: text;
  color: transparent;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.logo,
.logo a{
  background-position:0 calc(-1 * var(--scroll-var));
}
.sidelogo,
.sidelogo a{
  background-position:0 calc(-1 * var(--scroll-var) - 50vh + 30px);
}



.section {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
}

section--1 {
  height: 100vh;
  width: 100%;
}

.hero {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("https://www.w3schools.com/howto/photographer.jpg");
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

.section--2,
.footer{
  background: white;
}

.section--3,
.section--5{
  background: black;
  color: white;
}
<body class="body">

  <div class="header">
    <div class="logo"><a href="#">Logo</a></div>

  </div>

  <div class="header_nav">

          <div class="sidelogo"><a href="#">Nav</a></div>

  </div>

  <main class="main">

    <section class="section--1 section">
      <div class="hero">
      </div>
    </section>

    <section class="section--2 section section--bg">
      <h1>Section 2</h1>
      <p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
        Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis
        </p>
    </section>

    <section class="section--3  section">
      <h1>Section 3</h1>
      <p>
        <strong>Pellentesque habitant morbi tristique</strong> senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. <em>Aenean ultricies mi vitae est.</em>        Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, <code>commodo vitae</code>, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci,
        sagittis tempus lacus enim ac dui. <a href="#">Donec non enim</a> in turpis pulvinar facilisis. Ut felis.
      </p>
      <h2>Header Level 2</h2>
      <ol>
        <li>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</li>
        <li>Aliquam tincidunt mauris eu risus.</li>
      </ol>
    </section>

    <section class="section--4 section  section--bg">
      <h1>Section 4</h1>
      <p>
        Some great section 4 content
      </p>
      <ul>
        <li>This is a list item</li>
        <li>This is a list item</li>
        <li>This is a list item</li>
        <li>This is a list item</li>
        <li>This is a list item</li>
      </ul>
    </section>

    <section class="section--5 section section--bg">
      <h1 class="section__title">
        Section 5
      </h1>
      <p>
        This is some random content for section 5
      </p>
    </section>

  </main>

  <footer class="footer section">

    <form action="#" method="post">
      <div>
        <label for="name">Text Input:</label>
        <input type="text" name="name" id="name" value="" tabindex="1" />
      </div>
      <div>
        <h4>Radio Button Choice</h4>
        <label for="radio-choice-1">Choice 1</label>
        <input type="radio" name="radio-choice-1" id="radio-choice-1" tabindex="2" value="choice-1" />
        <label for="radio-choice-2">Choice 2</label>
        <input type="radio" name="radio-choice-2" id="radio-choice-2" tabindex="3" value="choice-2" />
      </div>
      <div>
        <label for="select-choice">Select Dropdown Choice:</label>
        <select name="select-choice" id="select-choice">
          <option value="Choice 1">Choice 1</option>
          <option value="Choice 2">Choice 2</option>
          <option value="Choice 3">Choice 3</option>
        </select>
      </div>
      <div>
        <label for="textarea">Textarea:</label>
        <textarea cols="40" rows="8" name="textarea" id="textarea"></textarea>
      </div>
      <div>
        <label for="checkbox">Checkbox:</label>
        <input type="checkbox" name="checkbox" id="checkbox" />
      </div>
      <div>
        <input type="submit" value="Submit" />
      </div>
    </form>

  </footer>

</body>

它依赖于元素的渐变着色的技巧。着色应与场地着色相反。我们的部分是100vh高度交替的白色/黑色,因此我们使用带有黑色/白色颜色的渐变,我们会更改每个颜色100vh并覆盖整个屏幕(600vh在这种情况下,因为我们有 6 个部分)。

然后我们使用一个在滚动时更新的简单 CSS 变量来定义背景位置。这就像我们让背景在元素内部滑动,使其相对于整个文档保持固定,我们将获得所需的结果。

这种方法的缺点:

  • 这些部分需要具有固定的高度,这就是为什么我稍微调整内容以使其不超过100vh能够正确定义渐变的原因。如果该部分是动态的,我们可以考虑使用更多的代码来使用更多的 CSS 变量来调整渐变。
  • 我使用背景为文本着色,旧浏览器background-clip:text支持该背景。

关于渐变,我之所以使用渐变,repeating-linear-gradient是因为我调整了部分以在白色和黑色之间完美交替,但如果我们没有这个,我们可以考虑在linear-gradient其中定义我们想要的每个部分的颜色。

这是一个更通用的示例(我删除了边框颜色的渐变以使其变得容易)

window.onscroll = function() {
  var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
  document.documentElement.style.setProperty('--scroll-var', scroll + "px");
}
:root {
  --scroll-var: 0px;
}

body {
 margin:0;
}

.header {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 9;
}

.header_nav {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  left: 0;
  z-index: 9;
}

.logo,
.sidelogo {
  background: 
   linear-gradient(to bottom, 
    #fff 0, #fff 100vh, 
    blue 100vh, blue 300vh,
    red 300vh, red 400vh,
    #fff 400vh, #fff 500vh,
    #000 500vh, #000 600vh) 
    top/100% 600vh;
  display: inline-block;
  border: solid transparent;
  border-radius: 10px;
  font-size: 2em;
}

.logo a,
.sidelogo a {
  display: block;
  padding: 10px;
  background:
    linear-gradient(to bottom, 
      #000 0, #000 100vh, 
      red 100vh, red 300vh,
      blue 300vh, blue 400vh,
      #000 400vh, #000 500vh,
      #fff 500vh, #fff 600vh)
      top/100% 600vh no-repeat;
  background-clip: text;
  color: transparent;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.logo,
.logo a {
  background-position: 0 calc(-1 * var(--scroll-var));
}

.sidelogo,
.sidelogo a {
  background-position: 0 calc(-1 * var(--scroll-var) - 50vh + 30px);
}

.section {
  min-height: 100vh;
}


.hero {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("https://www.w3schools.com/howto/photographer.jpg");
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}
<div class="header">
    <div class="logo"><a href="#">Logo</a></div>

  </div>

  <div class="header_nav">

    <div class="sidelogo"><a href="#">Nav</a></div>

  </div>


    <section class="section">
      <div class="hero">
      </div>
    </section>

    <section class="section" style="background:red;">

    </section>

    <section class="section" style="background:red;">

    </section>

    <section class="section" style="background:blue;">

    </section>

    <section class="section" style="background:#000;">

    </section>
    <section class="section" style="background:#fff;">

    </section>


推荐阅读