0

I'm trying to make slide-show website using intersectionObserver. Basically, i grep elements and listen for intersection event, then i want to set window.srollTo to element's offsetTop. I have tried window.scrollTo(0, 10), elem.scrollIntoView(), window.scrollBy(), but nothing is working at all.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title></title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      body,
      html {
        position: ablolute;
        -ms-overflow-style: none;
        display: block;
        height: 100vh;
        width: 100%;
      }
      body::-webkit-scrollbar {
        width: 0 !important;
      }

      .page {
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div class="page">one</div>
    <div class="page">two</div>
    <div class="page">three</div>
    <div class="page">four</div>
    <script>

      const pages = document.querySelectorAll('.page');
      const observer = new IntersectionObserver(
        entries => {
          entries.forEach(entry => {
            if (entry.isIntersecting == true) {

              console.log(entry.target.offsetTop);
              entry.target.scrollIntoView(top);
            }
          });
        },
        {threshold: 0.01},
      );
      pages.forEach(page => {
        observer.observe(page);
      });
    </script>
  </body>
</html>
Celso Wellington
  • 875
  • 8
  • 19

1 Answers1

0

Firstly scrollIntoView takes a Boolean or an options Object. I don't know what top is supposed to be since it's not in your code, but it's not correct.

Your scroll event is firing constantly and overriding your scrollIntoView. In order to stop this you can set the container's overflow property so that it no longer allows scrolling, disabling the event, and then re-enable it with a timer just before calling scrollIntoView.

          entries.forEach(entry => {
        if (entry.isIntersecting == true) {

          console.log(entry.target.offsetTop);
          document.body.setAttribute('style','overflow:hidden;');

          setTimeout(function(){
           document.body.setAttribute('style','overflow:visible;');       
           entry.target.scrollIntoView(true);
           }, 250);

        }

Example:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title></title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }

      body,
      html {
        position: absolute;
        -ms-overflow-style: none;
        display: block;
        height: 100vh;
        width: 100%;
      }
      body::-webkit-scrollbar {
        width: 0 !important;
      }

      .page {
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div class="page">one</div>
    <div class="page">two</div>
    <div class="page">three</div>
    <div class="page">four</div>
    <script>
      const pages = document.querySelectorAll('.page');
      const observer = new IntersectionObserver(
        entries => {
          entries.forEach(entry => {
            if (entry.isIntersecting == true) {

              console.log(entry.target.offsetTop);
              document.body.setAttribute('style','overflow:hidden;');

              setTimeout(function(){
               document.body.setAttribute('style','overflow:visible;');       
               entry.target.scrollIntoView(true);
               }, 250);
        
            }
          });
        },
        {threshold: 0.10},
      );
      pages.forEach(page => {
        observer.observe(page);
      });
    </script>
  </body>
</html>

Note There are likely better ways to do this without a timer - for instance a flag within a closure, etc, but this should give you an idea of what's causing the issue and how to get around it.

zfrisch
  • 8,474
  • 1
  • 22
  • 34