それで、イベントがトリガーされたときにスクロール方向を知るにはどうすればよいですか?
返されたオブジェクトで最も近い可能性は、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);
#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;
}
<div id="element">Observed</div>
これを知りたいので、これを固定ヘッダーメニューに適用して表示/非表示にすることができます
BoundingClientRectの処理でパフォーマンスの問題が発生するかどうかはわかりません。
MDNは、IntersectionObserver
がメインスレッドで実行されないことを示しています。
このように、サイトはこの種の要素の交差を監視するためにメインスレッドで何もする必要がなくなり、ブラウザは適切と思われる交差の管理を自由に最適化できます。
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)
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;
}
<div class="observer__target"></div>
<span class="observer__state"></span>
thresholdArray
ヘルパー関数が混乱する可能性がある場合は、0.0
から1.0
までの範囲の配列を、指定されたステップ数だけ作成します。 5
を渡すと、[0.0, 0.2, 0.4, 0.6, 0.8, 1.0]
が返されます。
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;
});
}
お役に立てれば。
:)
これは単一のしきい値では不可能だと思います。コンテナがビューポートを離れるとき、ほとんどの場合1
の下にあるintersectionRatio
に注意してみてください(交差点オブザーバーが非同期を起動するため)。ブラウザがすぐに追いつく場合でも、1
になる可能性があると確信しています。 (私はこれをテストしませんでした:D)
しかし、おそらくできることは、いくつかの値を使用して2つのしきい値を観察することです。 :)
threshold: [0.9, 1.0]
0.9
のイベントを最初に取得した場合、コンテナがビューポートに入ることは明らかです...
お役に立てれば。 :)
私の要件は:
IntersectionObserverEntry
から提供されるいくつかの情報を確認する必要がありました。
そのため、コールバックは次のようになりました。
intersectionObserver = new IntersectionObserver(function(entries) {
const entry = entries[0]; // observe one element
const currentRatio = intersectionRatio;
const newRatio = entry.intersectionRatio;
const boundingClientRect = entry.boundingClientRect;
const scrollingDown = currentRatio !== undefined &&
newRatio < currentRatio &&
boundingClientRect.bottom < boundingClientRect.height;
intersectionRatio = newRatio;
if (scrollingDown) {
// it's scrolling down and observed image started to hide.
// so do something...
}
console.log(entry);
}, { threshold: [0, 0.25, 0.5, 0.75, 1] });
完全なコードについては my post をご覧ください。