我目前正在尝试开发一个小型轻量级 vanilla-js 视差库,它可以在两个方向上水平和垂直地设置视差元素(图像、视频、滑块等),而无需任何背景位置的东西。
到目前为止,它运行良好,并且在期待一个重要细节方面做得很好:有时它仍然滞后。我已经在 Mac OS 和 iPhone、Safari 和 Chrome 浏览器上对其进行了测试。都一样。
我尝试使用节流、requestAnimationFrame 和 CSS 的 will-change 等常见做法,但没有成功。
我不确定,是否可以在此视频中看到滞后。
但我做了一个例子,你可以测试它: https ://codepen.io/flexplosion/pen/RwgQXxo?editors=1111
有人有一个想法,我如何提高视差的滚动性能?
var parallaxes = document.getElementsByClassName('parallax');
const windowInnerHeight = window.innerHeight;
function throttle (callback, limit) {
var wait = false; // Initially, we're not waiting
return function () { // We return a throttled function
if (!wait) { // If we're not waiting
callback.call(); // Execute users function
wait = true; // Prevent future invocations
setTimeout(function () { // After a period of time
wait = false; // And allow future invocations
}, limit);
}
}
}
Array.from(parallaxes).forEach((parallax) => {
const movement = parseFloat(parallax.dataset.movement),
direction = parallax.dataset.direction,
element = parallax.children[0];
if( direction == 'horizontal' ) {
// Prepare for orzintal
element.style.height = '100%';
element.style.width = (100 + movement) + "%";
} else {
// Otherwise prepare for vertical
element.style.height = (100 + movement) + "%";
element.style.width = '100%';
}
});
const handleScroll = () => {
var parallaxes = document.getElementsByClassName('parallax');
Array.from(parallaxes).forEach((parallax) => {
const movement = parseFloat(parallax.dataset.movement),
direction = parallax.dataset.direction,
reverse = parallax.dataset.reverse === 'true',
element = parallax.children[0];
var containerReact = parallax.getBoundingClientRect();
var scrolledInContainer = 0 - (containerReact.top - windowInnerHeight);
var scrollArea = windowInnerHeight + containerReact.height;
var progress = scrolledInContainer / scrollArea;
var scrolledInContainer = window.pageYOffset - (containerReact.top - windowInnerHeight);
if(progress > 0 && progress < 1) {
requestAnimationFrame(() => {
var position = reverse
? movement * progress
: movement - movement * progress;
element.style[ direction == 'horizontal' ? 'left' : 'top'] = "-" + position + "%";
});
}
});
}
// Initialize
handleScroll();
// Hook into event
window.addEventListener('scroll', throttle(handleScroll, 10) );
更新 1:
我尝试将脚本切换为使用 translate3d 而不是顶部/左侧属性。桌面 (Chrome) 上的动画现在非常流畅。它应该是怎样的。在 Safari 和所有移动浏览器中,它并没有真正帮助......
https://codepen.io/flexplosion/pen/BaZrKYv
在 Safari 中(在移动 Chrome 和 Safari 上相同):https ://jmp.sh/n4JG8J5 在 Chrome 中:https ://jmp.sh/EMM7y1Z