1. Чтобы не слушать каждый раз какое-то событие(в Вашем случае scroll), нужно написать debounce функцию (
вот отличное описание работы и сама функция). Которая является оберткой к Вашей функции onscroll , и не дает выполнять ее пока не пройдет N секунд.
2. Вам нужно почитать про анимацию в css
В краце: стили top, left, margin и тп затрачивают больше CPU потому, что браузеру нужно пересчитывать позицию всех элементов относительно анимированного. Если их большое кол., то и анимация будет дерганой.
Поэтому стоит использовать ряд других стили: opacity, transform. Их свойства никак не влияют на остальные блоки.(в гугле много ссылок по этой теме.
например)
и не задавайте
transition: all
Теперь все вместе(накидал пример на
Jsfiddle):
1. Задам вашему блоку стили:
.image{
/* ваши стили */
/* сдвигаем на 100px вниз и задаем прозрачность 0*/
transform: translate3d(0, 100px, 0);
opacity: 0;
/* ******* */
transition: opacity .3s, transform .3s;
}
.image.is-shown{
/* возвращаем в обычное состояние */
transform: translate3d(0, 0px, 0);
opacity: 1;
}
const image = document.getElementById('image');
const imageFromTop = image.getBoundingClientRect().top;
const showOnScroll = debounce(function() {
// How much scroll from top
let scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
// Check scroll position
if (imageFromTop < scrollTop + 500) {
image.classList.add('is-shown')
// Remove this listener for better pref
window.removeEventListener('scroll', showOnScroll, false);
}
}, 30);
window.addEventListener('scroll', showOnScroll, false);
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
Писал по памяти, но должно работать...
Это если применить Вашу логику к решению проблемы.
В либах, вродь, делают через
requestAnimationFrame . Можно посмотреть в исходниках(там и комменты есть). Вот хорошая
scrollReveal
Если будете сами писать через requestAnimationFrame, то не забывайте, что нужно использовать не больше 2-3 реквеста на страницу . Иначе будет грузить компьютер сильно