首页 > 解决方案 > 滚动文本以更改滚动时的固定背景图像

问题描述

我正在寻求帮助,我正在尝试在此站点上重新创建主页。

https://madebyarticle.com/

我不想使用 Jquery,无论是 Plain JS 还是 Vue。

我已经让它做我想做的大部分事情,但有一些问题。

代码笔示例

HTML

    <main id="parent" class="Loop js-loop">
  <section>
    <h1 class="step1">One</h1>
  </section>
  <section>
    <h1 class="step2">For</h1>
  </section>
  <section>
    <h1 class="step3">All</h1>
  </section>
  <section>
    <h1>And</h1>
  </section>
  <section>
    <h1>All</h1>
  </section>
  <section>
    <h1>For</h1>
  </section>

  <!--
  These blocks are the same as the first blocks to get that looping illusion going.
  You need to add clones to fill out a full viewport height.
  -->
  <section class="green is-clone">
    <h1>One</h1>
  </section>
  <section class="red is-clone">
    <h1>For</h1>
  </section>
</main>

CSS

    html,
body {
  height: 100%;
  overflow: hidden;
}

.Loop {
  position: relative;
  height: 100%;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}

section {
  position: relative;
  text-align: center;
/*   min-height: 300px;
  max-height: 700px; */
  height: 100vh;
}

::scrollbar {
  display: none;
}

body {
  font-family: "Avenir Next", Helvetica, sans-serif;
  font-weight: normal;
  font-size: 100%;
}

h1 {
  margin: 0;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 100%;
  font-size: 80px;
  letter-spacing: 5px;
/*   color: #fff; */
  text-transform: uppercase;
}

.mystyle {
  background: red;
}


.mystyle1 {
    background-image: url(https://images.unsplash.com/photo-1528834379234-2de7f8328fd8?ixlib=rb-1.2.1&auto=format&fit=crop&w=1920&q=10);
}

.mystyle2 {
  background-image: url(https://images.unsplash.com/photo-1501854140801-50d01698950b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2600&q=80);
}

JS

    var doc = window.document,
  context = doc.querySelector(".js-loop"),
  clones = context.querySelectorAll(".is-clone"),
  disableScroll = false,
  scrollHeight = 0,
  scrollPos = 0,
  clonesHeight = 0,
  i = 0;

function getScrollPos() {
  return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
}

function setScrollPos(pos) {
  context.scrollTop = pos;
}

function getClonesHeight() {
  clonesHeight = 0;

  for (i = 0; i < clones.length; i += 1) {
    clonesHeight = clonesHeight + clones[i].offsetHeight;
  }

  return clonesHeight;
}

function reCalc() {
  scrollPos = getScrollPos();
  scrollHeight = context.scrollHeight;
  clonesHeight = getClonesHeight();

  if (scrollPos <= 0) {
    setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
  }
}

function scrollUpdate() {
  if (!disableScroll) {
    scrollPos = getScrollPos();

    if (clonesHeight + scrollPos >= scrollHeight) {
      // Scroll to the top when you’ve reached the bottom
      setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
      disableScroll = true;
    } else if (scrollPos <= 0) {
      // Scroll to the bottom when you reach the top
      setScrollPos(scrollHeight - clonesHeight);
      disableScroll = true;
    }
  }

  if (disableScroll) {
    // Disable scroll-jumping for a short time to avoid flickering
    window.setTimeout(function() {
      disableScroll = false;
    }, 40);
  }
}

function init() {
  reCalc();

  context.addEventListener(
    "scroll",
    function() {
      window.requestAnimationFrame(scrollUpdate);
    },
    false
  );

  window.addEventListener(
    "resize",
    function() {
      window.requestAnimationFrame(reCalc);
    },
    false
  );
}

if (document.readyState !== "loading") {
  init();
} else {
  doc.addEventListener("DOMContentLoaded", init, false);
}

// Just for this demo: Center the middle block on page load
window.onload = function() {
  setScrollPos(
    Math.round(
      clones[0].getBoundingClientRect().top +
        getScrollPos() -
        (context.offsetHeight - clones[0].offsetHeight) / 2
    )
  );
};





const images = document.querySelectorAll('h1');

observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.intersectionRatio > 0) {
      entry.target.classList.add('active');
    } else {
      entry.target.classList.remove('active');
    }
  });
});

images.forEach(image => {
  observer.observe(image);
});

const header = document.getElementById("parent");
const sectionOne = document.querySelector("h1.step1");
const sectionTwo = document.querySelector("h1.step2");
const sectionThree = document.querySelector("h1.step3");

const sectionOneObserver = new IntersectionObserver(function(
  entries,
  sectionOneObserver
) {
  entries.forEach(entry => {
    if (!entry.isIntersecting) {
      header.classList.add("mystyle");
    } else {
      header.classList.remove("mystyle");
    }
  });
});

sectionOneObserver.observe(sectionOne);

const sectionTwoObserver = new IntersectionObserver(function(
  entries,
  sectionTwoObserver
) {
  entries.forEach(entry => {
    if (!entry.isIntersecting) {
      header.classList.add("mystyle1");
    } else {
      header.classList.remove("mystyle1");
    }
  });
});

sectionTwoObserver.observe(sectionTwo);

const sectionThreeObserver = new IntersectionObserver(function(
  entries,
  sectionThreeObserver
) {
  entries.forEach(entry => {
    if (!entry.isIntersecting) {
      header.classList.add("mystyle2");
    } else {
      header.classList.remove("mystyle2");
    }
  });
});

sectionThreeObserver.observe(sectionThree);






// if (document.querySelectorAll('h1.step1.active')){
//   document.getElementById("parent").classList.toggle("mystyle");
//   } else {
//     document.getElementById("parent").classList.remove("mystyle");
// }


// if (document.classList.contains("h1.step1.active")) {
//     document.getElementById("parent").classList.add("mystyle");
// } else {
//     document.getElementById("parent").classList.remove("mystyle");
// }
  1. 我必须为我需要的每张图片复制 IntersectionObserver,有没有更干净的方法来做到这一点?

  2. 在某些时候,有 2 个活动状态,因此它不会仅显示背景颜色的任何图像。

  3. 像示例网站这样在更改时淡化图像的最佳方法是什么?

有没有可以做我想做的事情的例子或脚本?

谢谢

标签: javascriptvue.jsintersection-observer

解决方案


推荐阅读