【发布时间】:2020-02-14 18:24:20
【问题描述】:
我正在尝试根据元素在场景中的滚动来为元素设置动画。我遇到了浏览器返回间歇性滚动位置的问题,这使得在启动和停止元素动画时很难准确。
小例子:
小提琴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>
如您所见,元素应该停止在行上,但是当您滚动时,它们实际上并没有。而且你滚动得越快,它就会变得越糟糕。
那么是否有一种技术可以返回正确的滚动位置或以某种方式使元素去抖动,以便在滚动时可以达到整个范围,而不是不断地低于预期位置?
我知道这是可能的,因为像 ScrollMagic 这样的滚动库可以很好地处理这个问题,但我真的不想解构整个 ScrollMagic 框架来了解它们是如何实现的。我会使用 ScrollMagic 框架本身,但我试图让一个动量风格的滚动容器包裹页面并将其与该容器内的元素一起在滚动上进行翻译,并且使用 ScrollMagic 它非常有问题。所以我想我会在这里发布这个问题,看看是否有人对这种情况有任何经验或见解。
任何指导都将不胜感激,因为我已经考虑了一段时间。
【问题讨论】:
-
我曾经遇到过 Intersection Observer 但没有时间实现它,我认为它可以提供帮助但你必须自己做,或者找到一些帮助库,这里是开始的参考如果你没有听说过他们developer.mozilla.org/en-US/docs/Web/API/…
-
@LouayAlosh 我对交叉点观察者的问题是我想创建一个基于进度的动画。我不知道交叉点观察者是否有可能获得元素在场景中取得的进展。因此,如果我想将元素设置为从开始到结束移动 200px。使用交点观察者,它只检查元素是否与顶部或底部相交。据我所知,没有办法检查交叉点之间的进度。回调仅在元素相交时触发。
-
你是对的,对不起,我认为它可以提供帮助。
-
您可能希望hook into the
scrollevent 改为passive event listener(这样浏览器就可以向您发送高保真事件更新,并且不会断断续续地滚动内容)跨度>
标签: javascript html css css-animations onscroll