#javascript #intersection-observer
#javascript #пересечение-наблюдатель
Вопрос:
Я экспериментирую с IntersectionObserver(), и он ведет себя странно: я использую очень простой макет, всего 8 изображений в одном div с flexbox, используя wrap, так что в основном 8 изображений располагаются в разных строках в зависимости от размера области просмотра. Сначала я применяю класс filter (который добавляет фильтр размытия) к каждому элементу, а затем удаляю его, когда они отображаются на экране:
HTML:
<div class="flex--cont">
<div class="box box-2">
<img src="img/1.jpg" alt="" class="img img-1">
</div>
<div class="box box-1">
<img src="img/2.jpg" alt="" class="img img-2">
</div>
<div class="box box-3">
<img src="img/3.jpg" alt="" class="img img-3">
</div>
<div class="box box-4">
<img src="img/4.jpg" alt="" class="img img-4">
</div>
<div class="box box-5">
<img src="img/5.jpg" alt="" class="img img-5">
</div>
<div class="box box-6">
<img src="img/6.jpg" alt="" class="img img-6">
</div>
<div class="box box-7">
<img src="img/7.jpg" alt="" class="img img-7">
</div>
<div class="box box-8">
<img src="img/8.jpg" alt="" class="img img-8">
</div>
</div>
JAVASCRIPT
const allImage = Array.from(document.querySelectorAll(".img"));
allImage.forEach((img) => img.classList.add("filter"));
const removeFilter = function (entries, observer) {
const [entry] = entries;
const image = entry.target;
image.classList.remove("filter");
};
const ImageObserver = new IntersectionObserver(removeFilter, {
root: null,
threshold: 0.15,
});
allImage.forEach((img) => ImageObserver.observe(img));
Дело в том, что наблюдатель фактически наблюдает только самый первый элемент каждой строки, поэтому, если у меня 2 строки, он получает только 1-е и 5-е изображение, если у меня 3 строки, он получает 1-е, 4-е и 7-е изображения и так далее. Я применил его ко всем изображениям. Почему он это делает? Спасибо за ваши ответы!
Комментарии:
1. Не могли бы вы воспроизвести эту проблему в stackblitz?
2. Я попробую. Я скоро опубликую его👍
3. Я сделал это в codepen, но это показывает проблему. Я хочу, чтобы весь квадрат стал синим, но только первый из каждой строки становится синим codepen.io/andreauge/pen/ExgYqVB
Ответ №1:
Менялся только первый, потому что это было все, на что вы нацеливались в функции изменения цвета, разрушая только первый элемент массива:
const [entry] = entries;
Однако InteractionObserver
обратный вызов вызывается не для каждой записи, а для всех записей, которые запускаются одновременно; следовательно entries
, массив содержит все наблюдаемые элементы, и вам нужно проверить isIntersecting
свойство следующим образом:
const changeColor = function(entries) {
entries.forEach(entry => {
if(entry.isIntersecting) {
entry.target.style.background = 'blue';
} else {
entry.target.style.background = 'red';
}
})
}
Из документов MDN
let callback = (entries, observer) => {
entries.forEach(entry => {
// Each entry describes an intersection change for one observed
// target element:
// entry.boundingClientRect
// entry.intersectionRatio
// entry.intersectionRect
// entry.isIntersecting
// entry.rootBounds
// entry.target
// entry.time
});
};
Комментарии:
1. Ну, это очень полный и прямой ответ. Большое тебе спасибо, Эндрю!