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>
粒子改编的。有一个关于
.rootBounds
entry.target
,h2
(观察到的滚动元素)和固定元素 h1
.例如,在示例中评论了详细信息。
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.1
};
/**
* 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>