Добрый день. У меня возникла проблема с анимацией при прокрутке страницы, которую я реализую с помощью AOS.js. Иногда несколько блоков (например, три) одновременно попадают в область видимости браузера. Мне необходимо, чтобы их анимация появления происходила последовательно, с задержкой между каждым блоком. Однако, если эти три блока не одновременно отображаются в области видимости (например, на мобильных устройствах они располагаются друг под другом), задержка для последующих блоков (второго и третьего) должна отсутствовать. В случае, если два блока видны, а третий - нет, задержка у второго блока относительно первого сохраняется, а у третьего - нет. Количество блоков может варьироваться. Как правильно реализовать эту функциональность? Дополнительно, посмотрите пример работы на сайте bannermaker.by в разделе портфолио, где контент генерируется динамически, а у меня статические заранее подготовленные блоки. Также прикладываю картинку для большей наглядности (цифры обозначают задержку появления блоков при входе в область видимости):
Для реализации анимации блоков, как вы описали, вам потребуется создать кастомное поведение, используя JavaScript, чтобы обрабатывать видимость блоков и применять задержки при анимации. Вот один из возможных подходов, используя Intersection Observer API и CSS-анимации.
### 1. Структура HTML
У вас должны быть блоки, которые вы хотите анимировать:
```html
<div class="animated-block">Block 1</div>
<div class="animated-block">Block 2</div>
<div class="animated-block">Block 3</div>
<!-- и так далее -->
```
### 2. Стили CSS
Определите стиль для анимации. Например:
```css
.animated-block {
opacity: 0;
transform: translateY(20px); /* Начальная позиция */
transition: opacity 0.5s ease, transform 0.5s ease;
}
.animated-block.animate {
opacity: 1;
transform: translateY(0); /* Конечная позиция */
}
```
### 3. JavaScript для управления анимацией
Теперь используйте Intersection Observer для отслеживания видимости блоков:
```javascript
const blocks = document.querySelectorAll('.animated-block');
let delay = 0;
const options = {
root: null,
rootMargin: '0px',
threshold: 0.1 // 10% видимости
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Удаляем старую задержку и применяем новую
entry.target.style.transitionDelay = `${delay}s`;
entry.target.classList.add('animate');
// Увеличиваем задержку для следующего блока, если он виден
delay += 0.3; // Пример: задержка в 300 мс
} else {
// Если блок выходит из видимости, сбрасываем задержку
delay = 0;
}
});
}, options);
// Наблюдаем за каждым блоком
blocks.forEach(block => {
observer.observe(block);
});
```
### 4. Альтернативная обработка для мобильных устройств
Если вы хотите, чтобы анимация была мгновенной на мобильных устройствах, можно добавить проверку ширины экрана:
```javascript
if (window.innerWidth <= 768) { // Или другое значение в пикселях для мобильных устройств
delay = 0; // Отключаем задержку
}
```
### 5. Итоговая логика
Теперь, если блоки будут одновременно видимы, они будут появляться с заданной задержкой. Если один из блоков станет невидимым, задержка для других блоков сбрасывается, что позволяет;
- Последовательно анимировать их появление.
- Избегать задержки анимации для блоков, которые не видны.
Вы также можете настроить параметры `threshold` и `rootMargin` в зависимости от ваших потребностей для более точного отслеживания видимости блоков.
Этот подход даст вам гибкость и контроль над анимацией блоков в зависимости от их видимости в области просмотра.
Всем привет. Решил свою проблему через дополнительное использование IntersectionObserver, который отслеживает блоки, помеченные AOS атрибутами. Инициализировал сам AOS через таймаут в 50 (не знаю зачем это нужно, но без этого не работает). Observer отслеживает теги, у которых еще не задан delay, как только delay через скрипт задается, блок перестает отслеживаться. Накидывание delay выполнено через FIFO. Вот рабочий код, может кому пригодиться: <br/> <pre><code class="javascript">const stack = []
const delayFactor = 300
const options = {
rootMargin: '0px',
threshold: 0.2,
}
const callback = entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
stack.push(entry.target)
const delay = (stack.length - 1) * delayFactor
entry.target.setAttribute('data-aos-delay', `${delay}`)
setTimeout(() => {
stack.shift()
}, delay)
}
})
}
const observer = new IntersectionObserver(callback, options)
const elementsToTrack = document.querySelectorAll(
'[data-aos]:not([data-aos-delay])'
)
elementsToTrack.forEach(element => {
observer.observe(element)
})</code></pre> <br/> <br/> Пример работы можно посмотреть на сайте: <a href="https://yourbanner.ru" rel="nofollow">https://yourbanner.ru</a>