Muuri — это мощная библиотека для организации сетки элементов с возможностью динамического перетаскивания, фильтрации и сортировки. В процессе работы с динамическими данными часто возникает необходимость показывать пользователю индикатор загрузки до момента завершения рендеринга сетки или загрузки внешнего контента.
Индикаторы загрузки помогают избежать пустого состояния страницы и создают ощущение отзывчивости интерфейса. В контексте Muuri их использование имеет несколько ключевых особенностей.
Для отображения индикатора загрузки можно использовать простой HTML-элемент, который скрывается после полной инициализации сетки.
<div id="loading">Загрузка...</div>
<div id="grid" class="grid">
<div class="item">Элемент 1</div>
<div class="item">Элемент 2</div>
<div class="item">Элемент 3</div>
</div>
#loading {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.5rem;
font-weight: bold;
}
.grid {
visibility: hidden;
}
const grid = new Muuri('.grid', {
layoutOnInit: false
});
// После полной загрузки всех элементов
window.addEventListener('load', () => {
document.getElementById('loading').style.display = 'none';
document.querySelector('.grid').style.visibility = 'visible';
grid.layout(true);
});
Ключевые моменты:
layoutOnInit: false предотвращает преждевременное
выравнивание элементов до полной загрузки контента.visibility: hidden)
предотвращает мерцание при загрузке элементов.Muuri предоставляет события, которые позволяют отслеживать изменения состояния элементов. В комбинации с индикатором загрузки это дает возможность динамически скрывать индикатор после добавления всех элементов.
const grid = new Muuri('.grid');
grid.on('layoutEnd', () => {
document.getElementById('loading').style.display = 'none';
document.querySelector('.grid').style.visibility = 'visible';
});
Если элементы загружаются асинхронно (например, через API), индикатор можно контролировать следующим образом:
async function loadItems() {
const response = await fetch('/api/items');
const items = await response.json();
const elements = items.map(item => {
const el = document.createElement('div');
el.classList.add('item');
el.textContent = item.name;
return el;
});
document.querySelector('.grid').append(...elements);
grid.add(elements);
grid.layout(true);
}
loadItems();
Здесь индикатор скрывается внутри обработчика события
layoutEnd, что гарантирует отображение сетки только после
того, как все новые элементы будут добавлены и выровнены.
Для более профессионального эффекта часто используют CSS-анимацию спиннера. Пример:
#loading::after {
content: '';
display: block;
width: 40px;
height: 40px;
border: 5px solid #ccc;
border-top-color: #333;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 10px auto 0 auto;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
Индикатор спиннера можно показывать на весь экран или внутри контейнера сетки. Важно, чтобы индикатор был визуально независим от сетки, иначе могут возникнуть проблемы с позиционированием при адаптивных изменениях.
Muuri позволяет динамически фильтровать и сортировать элементы. В таких случаях индикатор можно использовать для отображения временного состояния перерасчета сетки.
function filterGrid(filterFunc) {
document.getElementById('loading').style.display = 'block';
grid.filter(filterFunc);
grid.on('layoutEnd', () => {
document.getElementById('loading').style.display = 'none';
});
}
Рекомендации:
layoutEnd — надежный момент для скрытия
индикатора после завершения анимаций и выравнивания элементов.Если сетка содержит изображения, индикатор должен ждать полной загрузки картинок. В противном случае элементы могут “прыгать” при появлении.
const images = document.querySelectorAll('.grid img');
let loadedCount = 0;
images.forEach(img => {
img.onl oad = img.oner ror = () => {
loadedCount++;
if (loadedCount === images.length) {
document.getElementById('loading').style.display = 'none';
document.querySelector('.grid').style.visibility = 'visible';
grid.layout(true);
}
};
});
Использование события onload и onerror
гарантирует, что индикатор исчезнет только после завершения загрузки
всех медиафайлов.
Для крупных сеток (сотни элементов) можно сочетать ленивую загрузку и индикаторы прогресса. Вместо простого спиннера показывают процент загрузки:
let loadedCount = 0;
const total = items.length;
items.forEach(item => {
const el = document.createElement('div');
el.classList.add('item');
el.textContent = item.name;
document.querySelector('.grid').append(el);
loadedCount++;
document.getElementById('loading').textContent = `Загрузка ${Math.round(loadedCount / total * 100)}%`;
});
grid.add(document.querySelectorAll('.item'));
grid.layout(true);
document.getElementById('loading').style.display = 'none';
Такой подход делает ожидание более прозрачным и снижает ощущение “замороженного” интерфейса.
Эти методы позволяют строить гибкую и отзывчивую систему индикаторов загрузки в Muuri, обеспечивая корректное отображение сетки при динамическом добавлении, фильтрации, сортировке и загрузке медиафайлов. Правильное использование событий и CSS-анимаций позволяет создать плавный и профессиональный пользовательский интерфейс.