InterSectionOberserver 예제

by ChangJoo Park

HTML

<main>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?1">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?2">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?3">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?4">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?5">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?6">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?7">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?8">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?9">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?10">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?11">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?12">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?13">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?14">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?15">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?16">Hello</div>
  <div class="lazy-element" data-url="https://picsum.photos/600/600/?random?17">Hello</div>
</main>

CSS

main {
  height: 2000px;
}

.lazy-element {
  width: 400px;
  min-height: 400px;
  border: 1px solid black;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  margin-bottom: .5rem;
  transition: all .5s ease-in-out;
  background-color: grey;
  opacity: 0.8;
}

.lazy-element.visible {
  color: white;
  opacity: 1;
}

JavaScript

const elements = document.querySelectorAll('.lazy-element')
const config = {
  rootMargin: '50px 0px',
  threshold: 0.01
};

function preloadImage(url) {
  return new Promise((resolve, reject) => {
    let image = new Image();
    image.load = resolve(url);
    image.error = reject;
    image.src = url;
  })
}

const io = new IntersectionObserver(entries => {
  entries.forEach((entry, index) => {
    if (entry.intersectionRatio > 0) {

      io.unobserve(entry.target);
      preloadImage(entry.target.dataset.url)
        .then(url => {
          entry.target.tagName === 'IMG' ?
            entry.target.src = url :
            entry.target.style.backgroundImage = 'url(' + url + ')';
          entry.target.removeAttribute('data-url');
          entry.target.classList.add('visible');
        })
        .catch(error => console.error(error))
    }
  })
}, config)

elements.forEach(element => {
  io.observe(element)
})