Я написал этот фрагмент ниже, в котором рассматриваются элементы, использующие атрибут data-direction
. Значения этих атрибутов могут быть любыми, но я решил дать им либо horizontal
, либо vertical
значение, которое может быть направлением прокрутки, которое вы можете использовать.
Это будет контролировать только элементы что вы запрашиваете с аргументом selector
и не изменит направление прокрутки. Эта часть, которую я оставляю на ваше усмотрение.
callback
сработает всякий раз, когда в окне просмотра есть только 1 элементов Наблюдатель (что Вы просили, я полагаю). Этот обратный вызов имеет параметр, который является текущим значением направления. На основании этого значения вы можете переключать направления прокрутки.
Надеюсь, это поможет вам, мужик.
/**
* Observes elements that indicate the current
* scroll-direction based on a data-direction attribute.
* The callbacks fires with the current direction whenever
* a single observed element is in view.
*
* @param {string} selector
* @param {function} callback
* @returns {IntersectionObserver}
*/
function directionObserver(selector, callback) {
/**
* Store elements that are in view in a Set and
* set the default direction.
*/
const elementsInView = new Set();
let currentDirection = 'vertical';
/**
* Callback that runs whenever observed
* elements intersect.
*
* @param {IntersectionObserverEntry[]} entries
*/
const intersectionCallback = entries => {
/**
* Check if current entries are in view.
* If they are add them to the elementsInView array
* and remove them if they are not.
*/
entries.forEach(entry => {
const { target } = entry;
if (entry.isIntersecting) {
elementsInView.add(target);
} else {
elementsInView.delete(target);
}
});
/**
* Whenever there is only one element in the view
* switch the currentDirection to the value of the
* direction data attribute.
*/
if (elementsInView.size === 1) {
for (const element of elementsInView.values()) {
currentDirection = element.dataset.direction;
if ('function' === typeof callback) {
callback(currentDirection);
}
}
}
}
/**
* Options for the observer
*/
const options = {
root: null,
rootMargin: '50px 0px',
threshold: [0, 1]
};
/**
* Create observer
*/
const observer = new IntersectionObserver(intersectionCallback, options);
/**
* Observer elements based on the selector argument
*/
const sections = document.querySelectorAll(selector);
sections.forEach(section => observer.observe(section));
return currentDirection;
}
// Use the observer and observe all the .section elements.
directionObserver('.section', direction => {
console.log(`Current direction is: ${direction}`);
// Change scroll direction based on direction value.
});
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.section {
display: block;
height: 100vh;
margin: 50px 0;
}
.vertical {
width: 100%;
background: repeating-linear-gradient(
0deg,
white,
white 50px,
red 50px,
red 100px
);
}
.horizontal {
width: 300vw;
background: repeating-linear-gradient(
90deg,
white,
white 50px,
blue 50px,
blue 100px
);
}
<div class="section vertical" data-direction="vertical"></div>
<div class="section horizontal" data-direction="horizontal"></div>