elem.getBoundingClientRect() не работает на мобильном экране
Я разрабатываю веб-сайт с использованием gatsby.js, и он включает анимацию слайдов при прокрутке вниз. Я написал код, который отлично работал, пока не открыл инструменты разработчика и не попробовал его с помощью панели инструментов устройства. вот демонстрация воспроизведения, а также веб-страница, чтобы упростить задачу https://getboundingclientrect-is-broken.netlify.app
<div class="0 space"></div>
<p class="1 slideFR"></p>
<div id="boy" class="2 slideFL"></div>
<p class="3 slideFR"></p>
<div class="4 slideFL"></div>
<div class="flx space"></div>
.slideFR {
width: 100px;
height: 100px;
background-color: #957b26;
position: relative;
left: 450px;
transform: translateX(1000px);
}
.slideFL {
width: 100px;
height: 100px;
background-color: #26958f;
position: relative;
left: 300px;
transform: translateX(-1000px);
}
.inSight {
transition: all 0.5s;
transform: translateX(0);
}
.space {
width: 100px;
height: 1500px;
background-color: aquamarine;
}
let elemsFL = document.getElementsByClassName("slideFL");
var leftiesLoaded = Array.from( { length: elemsFL.length }, (_, i) => false ); // creates array length of elemsFL full of <false>
let elemsFR = document.getElementsByClassName("slideFR");
var rightersLoaded = Array.from( { length: elemsFR.length }, (_, i) => false ); // creates array length of elemsFR full of <false>
document.addEventListener("scroll", function (event) {
let windowHeight = window.outerHeight;
console.log( "%c/* ----------- scroll ---------- */", "color: purple; font-weight: bold" );
checkIfInSight(elemsFL, leftiesLoaded, windowHeight);
checkIfInSight(elemsFR, rightersLoaded, windowHeight);
});
/* -------------------------------- touchmove ------------------------------- */
document.addEventListener("touchmove", function (event) {
let windowHeight = window.outerHeight;
console.log( "%c/* ---------- touchmove --------- */", "color: red; font-weight: bold" );
checkIfInSight(elemsFL, leftiesLoaded, windowHeight);
checkIfInSight(elemsFR, rightersLoaded, windowHeight);
});
function checkIfInSight(elemArray, boolArray, windowHeight) {
for (let counter = 0; counter < elemArray.length; counter++) {
const elem = elemArray[counter];
let elemRect = elem.getBoundingClientRect();
let elemPosTop = elemRect.top;
let elemPosBottom = elemPosTop + elem.scrollHeight;
if (elemPosTop <= windowHeight && elemPosBottom >= 0) {
if (!boolArray[counter]) {
console.log( "%c In Sight", "color: green", elem.classList[0] );
boolArray[counter] = true;
elem.classList.add("inSight");
} else {
console.log( "%c In Sight And Loaded", "color: yellow", elem.classList[0] );
}
} else {
console.log( elem.classList[0], "\tOut Of Sight", elemPosTop, "<=", windowHeight, "&&", elemPosBottom, ">=0\t\t\t", elem.offsetTop );
boolArray[counter] = false;
elem.classList.remove("inSight");
}
}
}
Изменить: поскольку я устраняю неполадки, я заменилelem.offsetTop
сwindow.scrollY
что действительно заставило меня понять, что по какой-то причине он довольно долго не интерпретирует действие прокрутки как фактическую прокрутку. Я до сих пор не знаю, что я делаю неправильно или в чем проблема
1 ответ
благодаря комментарию EmielZuurbier я нашел решение IntersectionObserver API.Я даже создал более чистый и оптимизированный код.
HTML
<div class="0 space"></div>
<p class="1 slideFR toSlide"></p>
<div id="boy" class="2 slideFL toSlide"></div>
<p class="3 slideFR toSlide"></p>
<div class="4 slideFL toSlide"></div>
<div class=" space"></div>
JS
const slideDivs = document.querySelectorAll(".toSlide");
const options={
root: null,
rootMargin: "0px 2000px",
};
const observer= new IntersectionObserver(function(entries, observer){
entries.forEach(entry =>{
console.log(entry.target.classList[0],entry.isIntersecting, entry.intersectionRect);
if (entry.isIntersecting ){
entry.target.classList.add("inSight");
}else {
entry.target.classList.remove("inSight");
}
});
},options);
slideDivs.forEach(slideDiv => {
observer.observe(slideDiv);
});
CSS
.slideFR {
width: 100px;
height: 100px;
background-color: #957b26;
position: relative;
left: 200px;
transform: translateX(1000px);
}
.slideFL {
width: 100px;
height: 100px;
background-color: #26958f;
position: relative;
left: 150px;
/* visibility: hidden; */
transform: translateX(-1000px);
}
.inSight {
transition: all 0.5s;
transform: translateX(0);
}
.space {
width: 100px;
height: 1500px;
background-color: aquamarine;
}