JS 2 min
Взаимодействуем с контентом по скроллу (scroll event)
Привет! Сегодня интересная темка. Расскажу, как сделать какие-либо действия для блоков по скроллу. Для примера просто взял цвет и по скроллу будем задавать цвет (когда блок начнет появляться в зоне видимости). Поехали!
Итак, как же управлять скроллом? Да на самом деле все лежит в банальных математических вычислениях высоты (ширины). Разберемся детальнее:
HTML
<div class="item" data-color="#CD5C5C"></div>
<div class="item" data-color="#98FB98"></div>
<div class="item" data-color="#FF1493"></div>
<div class="item" data-color="#FFFF00"></div>
<div class="item" data-color="#00CED1"></div>
<div class="item" data-color="#8A2BE2"></div>
<div class="item" data-color="#191970"></div>
<div class="item" data-color="#778899"></div>
<div class="item" data-color="#FFD700"></div>
<div class="item" data-color="#000000"></div>
Имеем 10 блоков с классом item
и data-color
. Этот дата-атрибут нужен, чтобы задать нужный цвет блоку.
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: sans-serif;
}
body {
display: flex;
flex-direction: column;
align-items: center;
padding-top: 100px;
}
.item {
width: 500px;
height: 500px;
border: 1px solid #000;
border-radius: 4px;
margin-bottom: 100px;
transition: all 0.3s ease-in-out;
}
Просто расставляем блоки по центру и даем им отступы. А так же даем бордер, чтобы их вообще было видно изначально.
JS
let $item = $('.item');
let $window = $(window);
function viewedItem() {
let scrollTop = $window.scrollTop();
let scrollBottom = scrollTop + $window.height();
$item.each((index, item) => {
let $currentItem = $(item);
let itemOffsetTop = $currentItem.offset().top;
let itemOffsetBottom = itemOffsetTop + $currentItem.height();
if (scrollTop < itemOffsetBottom && scrollBottom > itemOffsetTop && !$currentItem.attr('data-viewed')) {
let color = $currentItem.attr('data-color');
$currentItem.css('background-color', color);
$currentItem.attr('data-viewed', true);
}
});
}
viewedItem();
$(window).scroll(() => {
viewedItem();
});
Магия здесь! Поехали разбираться)
- Создаем функцию
viewedItem
. Сразу получаем текущий скролл от начала документа в переменнуюscrollTop
. И после этого получаем так же определениеscrollBottom
, сложив наш скролл и высоту окна браузера. Таким образом мы сможем ловить события не когда начало экрана туда попало, а еще и когда конец. Но об этом дальше. - Пробегаемся по всем нашим блокам с помощью
each
. Получаем в переменную$currentItem
текущий блок и тут же рассчитываем для него расстояние от начала документа и расстояние + высоту. (стоит сделать ремарку — для статичных блоков мы высчитываем это значение один раз, оно сохраняется и все. А вот переменнаяscrollTop
постоянно меняется, т.к. мы использовали тамscrollTop
, а неoffset().top
). - А дальше — простые сравнения. Смотрим, чтобы расстояние скролла окна было всегда меньше чем расстояние + высота блока, а так же расстояние + высота окна были больше чем расстояние блока от начала. Таким образом, как только блок попадает в поле видимости — с ним что-то происходит.
- И да, там есть еще одно условие — проверяется
data-viewed
у блока. Напомню, что изначально его нет у блоков. По сути, это просто дата-атрибут — флаг, который позволяет скрипту понять, что над этим блоком уже действия произвелись, значит его трогать уже не надо. - Ну и в самом условии просто берем у текущего элемента его
data-color
и даемbackground-color: текущий цвет
. - Вызываем функцию один раз чтобы при загрузке страницы уже сработало один раз наше действие. А затем вызываем ее на скролл, чтобы на каждый скролл проверялось наше условие. Вот и все)
И конечно, пен: