是否可以在每个滚动/像素触发交叉点观察者回调



我使用的是Intersection Observer API,而不是滚动动画事件,但在尝试根据滚动位置和滚动值沿offset-path设置SVG动画时遇到了问题。

path.style.offsetDistance = element.intersectionRatio * 100 + "%";

由于Intersection Observer回调每次通过options对象中定义的threshold值时都会触发,因此使用element.intersectionRatiooffset-distance设置动画会给我带来一个小问题,即仅每滚动25%就会触发一次。我可以把每1%放在选项对象中作为阈值,就像这样:

let options = {
root: null,
rootMargin: "20px",
threshold: [0.01, 0.02, 0.03, 0.04, .....]
};

但是有更好的解决方案吗?还是我应该切换到好的旧滚动事件,并在公式中使用scrollY值来平滑地计算每个滚动/像素的偏移距离?

代码的其余部分:

let options = {
root: null,
rootMargin: "20px",
threshold: [0, 0.25, 0.5, 0.75, 1]
};
let callback = (entries, observer) => {
entries.forEach(element => {
if (element.isIntersecting) {
element.target.querySelectorAll("path").forEach(path => {
path.setAttribute("style", "offset-path: path('M" + generateRandomAnimationPathM() +" " + generateRandomAnimationPathM() + " L " + generateRandomAnimationPathLine() + " " + generateRandomAnimationPathLine() + "')", "offset-rotate: 0deg");
path.style.offsetDistance = element.intersectionRatio * 100 + "%";
});
}
});   
}
let generateRandomAnimationPathM = () => {
return Math.floor(Math.random() * Math.floor(100));
}
let generateRandomAnimationPathLine = () => {
return Math.floor(Math.random() * Math.floor(200));
}
let observer = new IntersectionObserver(callback, options);
document.querySelectorAll('section').forEach(section => {
console.log(section)
observer.observe(section);
});

值得注意的是,您提出的阈值技巧是一种破解,不能保证100%有效
这是因为IntersectionObserver API内部使用window.requestIdleCallback,它将请求浏览器只有在有时间并且用户没有与之交互时才执行回调。这意味着即使每0.01步设置一次阈值,动画仍可能导致故障,因为某些步骤可能会被跳过
正如您已经说过的,通过使用window.scrollY在scrollEvents上计算元素的交集比率,您可以很容易地实现您想要实现的目标。

最新更新