简体   繁体   English

为什么路口观察器一直在运行?

[英]why does intersection observer keeps on running?

I want to change the class of the header using intersection observer.我想使用路口观察器更改 header 的 class。 The idea here is that I have a header with full height and width and when we scroll down to another div the header shrinks to a small bar.这里的想法是,我有一个具有完整高度和宽度的 header,当我们向下滚动到另一个 div 时,header 会缩小为一个小条。

This is my javascript code.这是我的 javascript 代码。

if('IntersectionObserver' in window){
  const options = {
    root: null,
    rootMargin: '0px',
    threshold: 0.0
  }

  callback = (entries) => {
    const header = document.querySelector("header");
    const IS_INTERSECTING = entries[0].isIntersecting;
    if(!IS_INTERSECTING){
      header.classList.replace("header_full","header");
      return false;
    }else if(IS_INTERSECTING){
      header.classList.replace("header","header_full");
      return false;
    }else{
      return false;
    }
  }

  let observer = new IntersectionObserver(callback, options);

  let target = document.querySelector('header');
  observer.observe(target);
}

This is my markup这是我的标记

<div class="application">
        <header class="header_full">
            <div>
                <img src="logo_2.png" alt="logo">
                <h2>Intersection Observer</h2>
            </div>
            <div class="bars"></div>
        </header>
        <div class="full">full_1</div>
        <div class="full">full_2</div>
        <div class="full">full_3</div>
        <div class="full">full_4</div>
        <div class="full">full_5</div>
    </div>

This is my scss file这是我的 scss 文件

%full{
    height: 100vh;

}
body{
    margin: unset;
    background:whitesmoke;
    font-family: Comfortaa;
}

.full{
    @extend %full;
}

.header_full{
    @extend %full;
    background: goldenrod;
    display: grid;
    place-items:center;
    position: relative;

    & img{
        height: 250px;
        width:250px;
        object-fit: contain;
    }

    & h2{
        text-align: center;
        color: rgb(60, 60, 60);
        letter-spacing: 1.4px;
    }

    & .bars{
        &::after{
            content: "☰";
            font-size:1.3rem;
        }
        height: 40px;
        width: 40px;
        display: grid;
        place-items:center;
        position:absolute;
        top:10px;
        right: 10px;
        color: rgb(60,60,60);
    }
}

header{
    transition: all 500ms linear;
}

.header{
    height: 100px;
    max-height: 100px;;
    background: goldenrod;
    position: fixed;
    top:0;
    width: 100%;
    padding: 10px;
    box-sizing: border-box;
    animation: bring_down 500ms linear;

    & img{
        height: 80px;
        width:80px;
        object-fit: contain;
    }

    & h2{
        display: none;
    }

    & .bars{
        position:static;
    }
}

The problem I am facing is when I scroll down, the intersection observer keeps toggling the classes ie.我面临的问题是当我向下滚动时,路口观察者不断切换类,即。 header_full and header. making it flicker all the time. header_full 和 header。让它一直闪烁。 I have tried "observer.unobserve(header)" but the problem that I get is stops observing and thus makes the header change one time only.我试过“observer.unobserve(header)”,但我遇到的问题是停止观察,因此 header 仅更改一次。

I have also refered the following stack overflow questions but no luck.我还提到了以下堆栈溢出问题,但没有运气。

Change style header/nav with Intersection Observer (IO) 使用 Intersection Observer (IO) 更改样式标题/导航

Intersection Observer change class based on clientHeight 路口观察者根据clientHeight改成class

IntersectionObserver is based on visibility within the viewport (or another specified element root), so if your target is constantly entering and exiting the viewport you will end up with an infinite loop. IntersectionObserver基于视口(或另一个指定元素根)内的可见性,因此如果您的目标不断进入和退出视口,您将以无限循环结束。

This is what your code is doing.这就是您的代码正在做的事情。 The header exits the viewport, triggering the !IS_INTERSECTING control flow, which immediately puts it back inside the viewport. header退出视口,触发!IS_INTERSECTING控制流,立即将其放回视口内。 Re-entering the viewport triggers the IS_INTERSECTING control flow, which immediately pushes it back out - that's an infinite loop.重新进入视口会触发IS_INTERSECTING控制流,它会立即将其推出 - 这是一个无限循环。

You need your IntersectionObserver to target a static element which will not change its DOM position as a result of the callback.您需要将IntersectionObserver定位到 static 元素,该元素不会因回调而更改其 DOM position。 I would suggest taking your header out of the document flow entirely and putting a 100vh placeholder behind it.我建议将您的header完全从文档流中取出,并在其后面放置一个100vh占位符。 This has the added benefit of removing the heavy layout shift when your header goes from 100vh to essentially 0px as far as the remaining content is concerned.就剩余内容而言,当您的 header 从100vh变为基本0px时,这样做的额外好处是可以消除繁重的布局偏移。

<div class="application">
  <div class="header_placeholder"></div>
  <header class="header_full">
      <div>
          <img src="logo_2.png" alt="logo">
          <h2>Intersection Observer</h2>
      </div>
      <div class="bars"></div>
  </header>
  <div class="full">full_1</div>
  <div class="full">full_2</div>
  <div class="full">full_3</div>
  <div class="full">full_4</div>
  <div class="full">full_5</div>
</div>
%full{
    height: 100vh;

}
body{
    margin: unset;
    background:whitesmoke;
    font-family: Comfortaa;
}

.full{
    @extend %full;
}

.header_placeholder {
  height: 100vh;
}

.header_full{
    @extend %full;
    background: goldenrod;
    display: grid;
    place-items:center;

    /* move this out of the document flow */
    position: absolute;
    top: 0;
    width: 100%;

    & img{
        height: 250px;
        width:250px;
        object-fit: contain;
    }

    & h2{
        text-align: center;
        color: rgb(60, 60, 60);
        letter-spacing: 1.4px;
    }

    & .bars{
        &::after{
            content: "☰";
            font-size:1.3rem;
        }
        height: 40px;
        width: 40px;
        display: grid;
        place-items:center;
        position:absolute;
        top:10px;
        right: 10px;
        color: rgb(60,60,60);
    }
}

header{
    transition: all 500ms linear;
}

.header{
    height: 100px;
    max-height: 100px;;
    background: goldenrod;
    position: fixed;
    top:0;
    width: 100%;
    padding: 10px;
    box-sizing: border-box;
    animation: bring_down 500ms linear;

    & img{
        height: 80px;
        width:80px;
        object-fit: contain;
    }

    & h2{
        display: none;
    }

    & .bars{
        position:static;
    }
}
if('IntersectionObserver' in window){
  const options = {
    root: null,
    rootMargin: '0px',
    threshold: 0.0
  }

  callback = (entries) => {
    const header = document.querySelector("header");
    const IS_INTERSECTING = entries[0].isIntersecting;
    if(!IS_INTERSECTING){
      header.classList.replace("header_full","header");
      return false;
    }else if(IS_INTERSECTING){
      header.classList.replace("header","header_full");
      return false;
    }else{
      return false;
    }
  }

  let observer = new IntersectionObserver(callback, options);

  // target the placeholder element here
  let target = document.querySelector('.header_placeholder');
  observer.observe(target);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM