Description
As the spec stands today, having the threshold
value as a property of the instance make the API quite a bit more complex than it needs to be in any situation that involves observing multiple elements at multiple thresholds via a single IntersectionObserver instance.
Consider an example that wants to observe these three element/threshold combination:
#foo
at threshold0
.#bar
at threshold0.5
#quz
at threshold1
To observe all of these elements using a single IntersectionObserver instance today, you have to instantiate the IntersectionObserver with a threshold of [0, 0.5, 1]
, and then in the callback you have to loop through each of the targets to make sure it has passed the appropriate threshold (e.g. #qux
will trigger the callback when passing a threshold of 0
and 0.5
even though you only care about 1
).
A second problem with the current API is, in the above example if I decide I no longer want to monitor #foo
for intersections, I can unobserve()
the #foo
element, but I can't stop observing the 0
threshold, so now #bar
and #qux
will trigger at a threshold of 0
even though neither element cares about that threshold.
At minimum, we should add a method to update the threshold value, but I think associating the threshold(s) with the targets is a much more intuitive approach.
Here's how I'd want to write the above example:
const io = new IntersectionObserver((records) => {
// ...
});
io.observe(document.querySelector('#foo'), {threshold: [0]});
io.observe(document.querySelector('#bar'), {threshold: [0.5]});
io.observe(document.querySelector('#qux'), {threshold: [1]});
With these change, the callback is not called for #foo
on any threshold other than 0
, which means I can avoid writing the logic to check the threshold level in the callback.
It also means I can later call io.unobserve(document.querySelector('#foo'))
and not have to worry about the 0
threshold lingering around unnecessarily.
If an element needs to be observed at multiple thresholds but later only one of those threshold values needs to be unobserved, you could do so by specifying the threshold in the second argument to unobserve()
exactly as you do in observe()
.
For example, to observe #foo
at threshold 0
and 1
and then later only observe it at 0
you could do the following:
// Observe #foo at 0 and 1.
io.observe(document.querySelector('#foo'), {threshold: [0, 1]});
// Stop observing at 1 but continue to observe at 0.
io.unobserve(document.querySelector('#foo', {threshold: [1]});