滚动时更改徽标div背景颜色

时间:2018-12-16 18:12:22

标签: javascript jquery html css

我正在尝试使用slip-scrollparallax实现CSS JavaScript类型的效果。当屏幕向下滚动时,右上方的徽标将更改其背景,以与下面的内容形成对比。左侧还有一个导航按钮,其功能相同。

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

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

右侧的徽标按预期方式运行,随着您向下滚动页面,背景也会发生变化。

但是,左侧的导航不能正常工作,我认为它需要添加一些偏移量,因为当前随着导航的改变而改变

有人知道我要去哪里错吗?

1 个答案:

答案 0 :(得分:1)

考虑到您的代码,您将需要复制逻辑以使其对两个元素均有效。您需要调整第二个元素的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(不是well supported in older browsers)上的文字着色。

关于渐变,我使用了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>