Библиотека Muuri предоставляет мощные возможности для создания интерактивных сеток с перетаскиванием элементов. Одним из ключевых аспектов управления пользовательским взаимодействием является ограничение области, в которой элементы могут перемещаться. Это важно для поддержания структуры интерфейса, предотвращения выхода элементов за пределы контейнера и создания более предсказуемого поведения сетки.
По умолчанию элементы Muuri могут перетаскиваться свободно внутри
контейнера сетки. Чтобы ограничить область перемещения, используется
свойство dragContainer. Оно определяет DOM-элемент, внутри
которого перетаскиваемый элемент может перемещаться:
const grid = new Muuri('.grid', {
dragEnabled: true,
dragContainer: document.querySelector('.drag-area')
});
Ключевые моменты:
dragContainer может быть любым элементом
DOM, включая сам контейнер сетки или отдельный блок внутри
страницы.dragContainer не указан, по умолчанию областью
перетаскивания считается вьюпорт страницы.Muuri позволяет контролировать движение элементов по
горизонтали и вертикали с помощью опции dragAxis.
Значения могут быть следующими:
'x' — движение только по горизонтали.'y' — движение только по вертикали.null — разрешено движение по обеим осям.Пример:
const grid = new Muuri('.grid', {
dragEnabled: true,
dragAxis: 'y'
});
В этом примере элементы можно перемещать только вверх и вниз, что особенно полезно для списков с вертикальной ориентацией.
Для более тонкого контроля над перетаскиванием Muuri предоставляет
события dragStart, dragMove и
dragEnd. С их помощью можно динамически ограничивать
позицию элемента:
grid.on('dragMove', function (item, event) {
const dragElement = item.getElement();
const bounds = dragElement.parentElement.getBoundingClientRect();
const mouseX = event.clientX;
const mouseY = event.clientY;
if (mouseX < bounds.left) event.preventDefault();
if (mouseX > bounds.right) event.preventDefault();
if (mouseY < bounds.top) event.preventDefault();
if (mouseY > bounds.bottom) event.preventDefault();
});
Примечания:
dragMove вызывается при каждом движении мыши,
что позволяет проверять текущие координаты элемента.event.preventDefault() останавливает
перемещение элемента за пределами границ.Иногда требуется, чтобы элементы оставались строго в пределах ячеек сетки. Для этого используется комбинация настроек:
dragSort — включает сортировку элементов при
перетаскивании.dragSortPredicate — позволяет задавать логику
определения позиции элемента.Пример ограничения элементов только внутри текущей строки:
const grid = new Muuri('.grid', {
dragEnabled: true,
dragSort: true,
dragSortPredicate: {
threshold: 50,
action: 'move',
sortBy: 'y'
}
});
Особенности:
threshold задает минимальное смещение, необходимое для
перемещения элемента.sortBy: 'y' гарантирует, что элементы будут
перемещаться только по вертикальной оси, сохраняя горизонтальные
позиции.Иногда достаточно использовать CSS-свойства контейнера, чтобы предотвратить выход элементов за пределы области:
.drag-area {
overflow: hidden;
position: relative;
}
.grid-item {
position: absolute;
}
Преимущества:
dragContainer и событиями
dragMove.Минусы:
Muuri позволяет задавать индивидуальные ограничения
для каждого элемента, используя опцию dragEnabled на уровне
элемента и события dragMove:
grid.getItems().forEach(item => {
if (item.getElement().classList.contains('fixed')) {
item.disableDrag();
}
});
Это полезно, когда часть элементов должна оставаться неподвижной, а другие — перемещаемыми.
На практике чаще всего используется комбинация трёх подходов:
dragContainer — ограничивает физическую область
перемещения.dragAxis — ограничивает направление движения.dragMove + проверки координат — точная настройка границ
для сложных интерфейсов.Пример комплексной конфигурации:
const grid = new Muuri('.grid', {
dragEnabled: true,
dragContainer: document.querySelector('.drag-area'),
dragAxis: 'x'
});
grid.on('dragMove', function(item, event) {
const bounds = item.getElement().parentElement.getBoundingClientRect();
if (event.clientX < bounds.left || event.clientX > bounds.right) {
event.preventDefault();
}
});
Такой подход позволяет создавать сетки, в которых элементы строго соблюдают ограничения области, остаются на своих линиях и не выходят за пределы интерфейса.