Задать вопрос
@antpv

Как сделать анимацию блоков при скроллинге на чистом js?

А именно всплытие вверх и opacity с 0 до 1 при попадании элемента в видимую область.

Кто может описать алгоритм? интересует только чистый js.

Я пытался делать так:
1. Задал для блока margin-top 50px;
2. Поставил прослушку на scroll, при window.pageYOffset > block.getBoundingClientRect().top делаю margin 0;

Но понимаю что очень рукожопый способ, анимация дерганная.

Мне хватит подробного алгоритма на словах, реализовать смогу сам
  • Вопрос задан
  • 2376 просмотров
Подписаться 1 Простой 5 комментариев
Решения вопроса 1
alsolovyev
@alsolovyev
¯\_(ツ)_/¯ Enjoy life, Eat well & Laugh often
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 реквеста на страницу . Иначе будет грузить компьютер сильно
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы