Я пытаюсь анимировать элементы при прокрутке, основываясь на прохождении элементов по сцене. Я сталкиваюсь с проблемой браузера, возвращающего прерывистые позиции прокрутки, затрудняющие точность при запуске и остановке анимации элементов.
Минимальный пример:
Fiddle Fiddle Demo
const tweens = document.querySelectorAll('.tween');
const trigger = document.querySelector('.start');
const triggerRect = trigger.getBoundingClientRect();
let yScroll = window.scrollY;
let yCurrent = yScroll;
let AF = null;
const start = triggerRect.top - yScroll - 200;
const end = start + 400;
const updateScroll = () => {
yScroll = window.scrollY;
startAnimation();
}
const startAnimation = () => {
if(!AF) AF = requestAnimationFrame(animate)
}
const cancelAnimation = () => {
yCurrent = yScroll;
cancelAnimationFrame(AF);
AF = null;
}
const animate = () => {
if(yCurrent === yScroll) cancelAnimation();
else {
updateElements();
yCurrent = yScroll;
AF = requestAnimationFrame(animate);
}
}
const updateElements = () => {
const pos = yCurrent - start;
if(inScene()){
tweens[0].style.transform = `translateX(${pos}px)`;
tweens[1].style.transform = `translateY(${pos}px)`;
}
}
const inScene = () => {
return start <= yCurrent && end >= yCurrent ? true : false;
};
window.addEventListener('scroll', updateScroll);
.wrapper{
position:relative;
margin: 100vh 20px;
background: rgb(240,240,240);
height: 900px;
border: 1px solid red;
}
.line{
position:absolute;
left: 0;
width: 100%;
height: 1px;
background: red;
}
.start{
top: 200px;
}
.end{
bottom: 200px;
}
.tween{
position:absolute;
top:200px;
width: 100px;
height: 100px;
background: blue;
}
.left{
left: 0;
}
.right{
right: 0;
}
<h1>Scroll Down</h1>
<div class="wrapper">
<div class="line start trigger"></div>
<div class="line end"></div>
<div class="tween left"></div>
<div class="tween right"></div>
</div>
Как вы можете видеть, элементы должны останавливаться на линиях, но когда вы прокручиваете, они на самом деле никогда не делают. И чем быстрее вы прокручиваете, тем хуже становится.
Таким образом, есть метод, который либо возвращает правильную позицию прокрутки, либо каким-то образом отбрасывает элементы, чтобы затем достигать полного диапазона при прокрутке, а не постоянно подниматься не хватает их предполагаемой позиции?
Я знаю, что это возможно, потому что библиотеки прокрутки, такие как ScrollMagi c, справляются с этим довольно хорошо, но я не хочу разбирать тогда весь ScrollMagi c рамки, чтобы узнать, как они этого достигают. Я бы использовал сам фреймворк ScrollMagi c, но я стараюсь, чтобы контейнер прокрутки в стиле импульса оборачивал страницу и переводил ее по прокрутке вместе с элементами внутри этого контейнера, а с помощью ScrollMagi c он довольно глючный. Поэтому я решил опубликовать вопрос здесь и посмотреть, есть ли у кого-нибудь опыт или понимание ситуации.
Буду признателен за любые рекомендации, так как я обдумывал это некоторое время.