Drag-and-drop редакторы

Gridstack.js — это современная библиотека на JavaScript, которая позволяет создавать интерактивные drag-and-drop сетки с изменяемыми размерами элементов. Она особенно полезна для построения панелей управления, дашбордов и кастомизируемых интерфейсов. Основной концепцией является сетка, состоящая из ячеек фиксированного размера, куда можно помещать виджеты (элементы) с возможностью перемещения и изменения размеров.

Gridstack.js работает на базе HTML, CSS и JavaScript, используя jQuery для управления DOM (хотя в последних версиях поддержка jQuery необязательна). Каждый элемент сетки определяется через атрибуты data-gs-* или программно через API.


Инициализация сетки

Чтобы создать рабочую сетку, необходимо подключить библиотеку и вызвать конструктор:

const grid = GridStack.init({
    cellHeight: 80, // Высота ячейки в пикселях
    column: 12,     // Количество колонок в сетке
    verticalMargin: 10, // Отступ между виджетами
    float: true,    // Разрешает свободное перемещение элементов
    resizable: {
        handles: 'e, se, s, sw, w' // Направления изменения размера
    }
});

Ключевые параметры:

  • cellHeight — фиксирует высоту ячеек сетки. Можно задать число или функцию для динамической высоты.
  • column — задаёт количество колонок. Сетка будет автоматически адаптироваться к ширине контейнера.
  • verticalMargin — расстояние между элементами по вертикали.
  • float — включает возможность “плавающих” виджетов, которые не занимают фиксированные ряды.
  • resizable — объект, задающий возможности изменения размеров виджетов.

Создание виджетов

Виджеты — это элементы <div> с атрибутами data-gs-*:

<div class="grid-stack">
    <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
        <div class="grid-stack-item-content">Виджет 1</div>
    </div>
    <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="3">
        <div class="grid-stack-item-content">Виджет 2</div>
    </div>
</div>

Основные атрибуты виджета:

  • data-gs-x и data-gs-y — координаты виджета в сетке (номер колонки и строки).
  • data-gs-width и data-gs-height — размеры виджета в ячейках.
  • data-gs-auto-position — если true, виджет будет автоматически размещён в первой свободной позиции.

Работа с событиями

Gridstack.js поддерживает множество событий, которые позволяют реагировать на перемещение и изменение размеров элементов:

grid.on('change', function(event, items) {
    items.forEach(function(item) {
        console.log(`Элемент ${item.el.id} перемещен в (${item.x}, ${item.y})`);
    });
});

grid.on('added', function(event, items) {
    console.log('Добавлены новые виджеты:', items);
});

grid.on('removed', function(event, items) {
    console.log('Удалены виджеты:', items);
});

Часто используемые события:

  • change — вызывается при перемещении или изменении размеров виджета.
  • added — при добавлении нового элемента через API или drag-and-drop.
  • removed — при удалении виджета.
  • dragstart, drag, dragstop — события начала, процесса и окончания перетаскивания.
  • resizestart, resize, resizestop — события изменения размеров.

Динамическое добавление и удаление элементов

Виджеты можно создавать программно:

grid.addWidget({
    x: 0,
    y: 0,
    width: 3,
    height: 2,
    content: '<div class="grid-stack-item-content">Новый виджет</div>'
});

const widget = grid.getGridItems()[0]; // Получить первый виджет
grid.removeWidget(widget.el);           // Удалить виджет

Методы для работы с сеткой:

  • addWidget(options) — добавляет элемент.
  • removeWidget(el) — удаляет элемент по DOM-элементу.
  • update(el, options) — изменяет позицию и размер виджета.
  • batchUpdate() / commit() — позволяют выполнять несколько изменений одновременно без перерисовки после каждого.

Адаптивность и мобильные устройства

Gridstack.js поддерживает адаптивную сетку, автоматически меняя количество колонок при изменении ширины контейнера. Для этого используется метод grid.setColumn(n):

window.addEventListener('resize', function() {
    if (window.innerWidth < 600) {
        grid.setColumn(2);
    } else {
        grid.setColumn(12);
    }
});

Также можно отключать drag-and-drop на мобильных устройствах:

grid.enableMove(false); // Запрещает перемещение всех виджетов
grid.enableResize(false); // Запрещает изменение размеров

Стилизация виджетов

Gridstack.js оставляет полную свободу по CSS-оформлению:

.grid-stack-item-content {
    background: #f0f0f0;
    border: 1px solid #ccc;
    border-radius: 6px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 16px;
}

Возможна анимация перемещений через CSS-переходы, а также использование различных классов для визуальной дифференциации виджетов.


Оптимизация производительности

Для больших сеток рекомендуется:

  • Использовать batchUpdate() при массовых изменениях.
  • Ограничивать частоту событий drag и resize.
  • Предварительно задавать размеры и координаты виджетов, чтобы минимизировать пересчёт layout.
  • Использовать staticGrid: true для временной блокировки перетаскивания при необходимости.

Интеграция с другими библиотеками

Gridstack.js хорошо сочетается с:

  • Vue.js / React / Angular — есть официальные обёртки и компоненты.
  • Chart.js, D3.js — для создания интерактивных графиков в виджетах.
  • LocalStorage / IndexedDB — для сохранения состояния сетки и восстановления позиции виджетов после перезагрузки страницы.

Пример сохранения состояния:

function saveLayout() {
    const serialized = grid.save();
    localStorage.setItem('grid-layout', JSON.stringify(serialized));
}

function loadLayout() {
    const layout = JSON.parse(localStorage.getItem('grid-layout'));
    if (layout) {
        grid.load(layout);
    }
}

Gridstack.js обеспечивает мощный и гибкий drag-and-drop механизм для любых приложений с динамическим расположением виджетов, позволяя создавать полностью настраиваемые дашборды и интерактивные интерфейсы без сложной ручной логики позиционирования.