最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Add class when intersection observer passes the element scrolling down, and remove when up? - Stack Overflow

programmeradmin0浏览0评论

I'm trying to toggle the class when Intersection Observer passes a certain element. When it passes from the top, I'd like to add class and then to remove it when scroll direction is up.

It works, but unfortunately not each time and not in correct place. How to add / remove the class when the element is just barely visible at the bottom of the screen?

const options = {
        root: null,
     //   rootMargin: '50px',
       threshold: 0.1
    }


    const observer = new IntersectionObserver(
        ([entry]) => {

            if (entry.isIntersecting) {
                
                     // up
                if (entry.boundingClientRect.top < 0) {
                    document.querySelector('button').classList.remove('hidden');
                } else {
                      //down 
                    document.querySelector('button').classList.add('hidden')
                }
            }
        },
        options
    );


const arr = document.querySelectorAll('h2')
arr.forEach(i => {
  observer.observe(i)
})
h2 {
  margin-top: 700px;
  margin-bottom: 700px;
}

button {
  position: fixed;
  top: 0;
  left:0;
}

button.hidden {
  background: red !important;
}
<h2>
ELEMENT
</h2>

<button>
  FIXED BUTTON
</button>

I'm trying to toggle the class when Intersection Observer passes a certain element. When it passes from the top, I'd like to add class and then to remove it when scroll direction is up.

It works, but unfortunately not each time and not in correct place. How to add / remove the class when the element is just barely visible at the bottom of the screen?

const options = {
        root: null,
     //   rootMargin: '50px',
       threshold: 0.1
    }


    const observer = new IntersectionObserver(
        ([entry]) => {

            if (entry.isIntersecting) {
                
                     // up
                if (entry.boundingClientRect.top < 0) {
                    document.querySelector('button').classList.remove('hidden');
                } else {
                      //down 
                    document.querySelector('button').classList.add('hidden')
                }
            }
        },
        options
    );


const arr = document.querySelectorAll('h2')
arr.forEach(i => {
  observer.observe(i)
})
h2 {
  margin-top: 700px;
  margin-bottom: 700px;
}

button {
  position: fixed;
  top: 0;
  left:0;
}

button.hidden {
  background: red !important;
}
<h2>
ELEMENT
</h2>

<button>
  FIXED BUTTON
</button>

Share Improve this question asked Feb 1 at 21:00 RunnickRunnick 7154 gold badges16 silver badges36 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

The following example was adapted from this article. There is a bug (see comment) concerning .rootBounds so it replaced by a simple constant of 100. The class changes are applied to the entry.target, h2 (the scrolled element being observed) and the fixed element h1.

Details are commented in example.

const h1 = document.querySelector("h1");
const h2 = document.querySelector("h2");

/**
 * Having a rootMargin would mean the target element would have
 * to clear that length before it was considered intersecting 
 * so it was changed from 50px to 0px
 */
const options = {
  root: null,
  rootMargin: "0px",
  threshold: 0
};

/**
 * Callback function compares the target element top position
 * to its bottom position in order  to determine the direction
 * the target element is scrolling (up or down).
 * @param {object} entries  - IntersectionObserverEntry
 * @param {object} observer - IntersectionObserver instance
 */
const callback = (entries, observer) => {
  entries.forEach(entry => {
/**
 * IntersectionObserverEntry Properties
 * - .intersectionRect is the clientBoundingRect of the part 
 *   of the target that is intersecting.
 * - .top is the y position of .intersectionRect relative to 
 *   its top border and viewport.
 * - .bottom is like .top concerning the bottom border.
 * - .intersectionRatio is the portion of the target that's
 *   intersecting.
 * - .target is the element being observed.
 * - .isIntersecting a boolean when true is when .target is
 *   at or past its threshold and within the intersection
 *   observer root.
 */     
const fromTop = entry.intersectionRect.top;
const fromBottom = 100 - entry.intersectionRect.bottom;
if (entry.intersectionRatio < 0.1 ||
    fromTop > fromBottom &&
    entry.isIntersecting === true) {
  h1.classList.remove("red");
  entry.target.classList.remove("red");
}
if (fromBottom > fromTop && entry.isIntersecting === true) {
  h1.classList.add("red");
  entry.target.classList.add("red");
}
  });
};
/**
 * Instintate IntersectionObserver pass callback function and
 * options object.
 */
let observer = new IntersectionObserver(callback, options);
// Call .observe() method and pass the target element
observer.observe(h2);
body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 350vh;
}

header {
  position: fixed;
  top: 0;
  left: 0
}

.red {
  color: red;
}
<header>
  <h1>Header 1</h1>
</header>
<h2>Header 2</h2>

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论