Jos*_*des 26 html javascript css intersection-observer
那么,当触发事件时,如何知道滚动方向?
在返回的对象中,我看到的最接近的可能性是与boundingClientRect保存最后滚动位置的类型进行交互,但我不知道处理boundingClientRect是否会最终导致性能问题.
是否可以使用交集事件来确定滚动方向(向上/向下)?
我添加了这个基本代码段,所以如果有人可以帮助我.
我会非常感激的.
这是片段:
var options = {
rootMargin: '0px',
threshold: 1.0
}
function callback(entries, observer) {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log('entry', entry);
}
});
};
var elementToObserve = document.querySelector('#element');
var observer = new IntersectionObserver(callback, options);
observer.observe(elementToObserve);Run Code Online (Sandbox Code Playgroud)
#element {
margin: 1500px auto;
width: 150px;
height: 150px;
background: #ccc;
color: white;
font-family: sans-serif;
font-weight: 100;
font-size: 25px;
text-align: center;
line-height: 150px;
}Run Code Online (Sandbox Code Playgroud)
<div id="element">Observed</div>Run Code Online (Sandbox Code Playgroud)
我想知道这一点,所以我可以在固定标题菜单上应用它来显示/隐藏它
Mat*_*vic 24
该解决方案不使用任何外部状态,因此比跟踪其他变量的解决方案更简单:
const observer = new IntersectionObserver(
([entry]) => {
if (entry.boundingClientRect.top < 0) {
if (entry.isIntersecting) {
// entered viewport at the top edge, hence scroll direction is up
} else {
// left viewport at the top edge, hence scroll direction is down
}
}
},
{
root: rootElement,
},
);
Run Code Online (Sandbox Code Playgroud)
Jas*_*son 13
我不知道处理boundingClientRect是否会最终导致性能问题.
MDN声明IntersectionObserver不在主线程上运行:
这样,站点不再需要在主线程上执行任何操作来观察这种元素交集,并且浏览器可以自由地优化交叉点的管理.
MDN,"Intersection Observer API"
我们可以通过保存值来计算滚动方向IntersectionObserverEntry.boundingClientRect.y,并将其与之前的值进行比较.
运行以下代码段作为示例:
const state = document.querySelector('.observer__state')
const target = document.querySelector('.observer__target')
const thresholdArray = steps => Array(steps + 1)
.fill(0)
.map((_, index) => index / steps || 0)
let previousY = 0
let previousRatio = 0
const handleIntersect = entries => {
entries.forEach(entry => {
const currentY = entry.boundingClientRect.y
const currentRatio = entry.intersectionRatio
const isIntersecting = entry.isIntersecting
// Scrolling down/up
if (currentY < previousY) {
if (currentRatio > previousRatio && isIntersecting) {
state.textContent ="Scrolling down enter"
} else {
state.textContent ="Scrolling down leave"
}
} else if (currentY > previousY && isIntersecting) {
if (currentRatio < previousRatio) {
state.textContent ="Scrolling up leave"
} else {
state.textContent ="Scrolling up enter"
}
}
previousY = currentY
previousRatio = currentRatio
})
}
const observer = new IntersectionObserver(handleIntersect, {
threshold: thresholdArray(20),
})
observer.observe(target)Run Code Online (Sandbox Code Playgroud)
html,
body {
margin: 0;
}
.observer__target {
position: relative;
width: 100%;
height: 350px;
margin: 1500px 0;
background: rebeccapurple;
}
.observer__state {
position: fixed;
top: 1em;
left: 1em;
color: #111;
font: 400 1.125em/1.5 sans-serif;
background: #fff;
}Run Code Online (Sandbox Code Playgroud)
<div class="observer__target"></div>
<span class="observer__state"></span>Run Code Online (Sandbox Code Playgroud)
如果thresholdArray辅助函数可能会让您感到困惑,它会构建一个数组,范围从0.0给1.0定的步数到.传递5将返回[0.0, 0.2, 0.4, 0.6, 0.8, 1.0].
小智 8
比较boundingClientRect并rootBounds从entry,你可以很容易地知道,如果目标是高于或低于视.
在期间callback(),你检查isAbove/isBelow然后,最后,你将它存储到wasAbove/wasBelow.下一次,如果目标进入视口(例如),您可以检查它是在上面还是下面.所以你知道它是来自顶部还是底部.
你可以尝试这样的事情:
var wasAbove = false;
function callback(entries, observer) {
entries.forEach(entry => {
const isAbove = entry.boundingClientRect.y < entry.rootBounds.y;
if (entry.isIntersecting) {
if (wasAbove) {
// Comes from top
}
}
wasAbove = isAbove;
});
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.