Канбан-доска

Muuri — это мощная библиотека JavaScript для создания сеточных интерфейсов с динамическим размещением элементов. В контексте канбан-доски она позволяет реализовать перетаскиваемые карточки, автоматическое выравнивание элементов и плавную анимацию при изменении структуры доски. Основная идея заключается в том, чтобы каждая колонка канбан-доски представляла собой сетку Muuri, а карточки внутри колонок — элементы сетки.

Ключевые моменты:

  • Элементы сетки автоматически адаптируются к изменениям размера контейнера.
  • Перетаскивание элементов работает как внутри одной сетки, так и между несколькими сетками.
  • Возможность кастомизации анимаций при перемещении элементов, добавлении и удалении карточек.

Инициализация сетки и создание карточек

Для каждой колонки канбан-доски создается отдельная сетка Muuri. Элементы сетки должны быть обернуты в контейнер с уникальным классом или идентификатором.

Пример структуры HTML:

<div class="kanban-column" id="todo">
  <div class="kanban-item">Задача 1</div>
  <div class="kanban-item">Задача 2</div>
</div>

<div class="kanban-column" id="in-progress">
  <div class="kanban-item">Задача 3</div>
</div>

Инициализация сетки в Jav * aScript:

const todoGrid = new Muuri('#todo', {
  dragEnabled: true,
  layout: {
    fillGaps: true,
    horizontal: false
  }
});

const inProgressGrid = new Muuri('#in-progress', {
  dragEnabled: true,
  layout: {
    fillGaps: true,
    horizontal: false
  }
});

Объяснение ключевых опций:

  • dragEnabled: true — позволяет перетаскивать элементы.
  • layout.fillGaps: true — автоматически заполняет пустое пространство при удалении или перемещении карточек.
  • layout.horizontal: false — указывает вертикальное расположение элементов внутри колонки.

Перетаскивание карточек между колонками

Для реализации перемещения карточек между колонками используется событие dragReleaseEnd. Основная задача — определить новую сетку, куда перемещается элемент, и обновить обе сетки.

Пример:

const allGrids = [todoGrid, inProgressGrid];

allGrids.forEach(grid => {
  grid.on('dragReleaseEnd', (item) => {
    const targetColumn = document.elementFromPoint(item.drag.x, item.drag.y).closest('.kanban-column');
    if (!targetColumn) return;

    const targetGrid = allGrids.find(g => g.getElement() === targetColumn);
    if (targetGrid && targetGrid !== grid) {
      grid.remove(item, { removeElements: false });
      targetGrid.add(item.getElement());
    }
  });
});

Важные моменты:

  • Использование removeElements: false предотвращает удаление DOM-элемента при переносе между сетками.
  • Метод elementFromPoint позволяет точно определить колонку под курсором.
  • После добавления элемента в новую сетку можно вызвать targetGrid.layout(true) для обновления позиции всех карточек с анимацией.

Анимация и визуальные эффекты

Muuri обеспечивает плавную анимацию при всех изменениях сетки. Настроить скорость и тип анимации можно через опции layoutDuration и layoutEasing.

const grid = new Muuri('.kanban-column', {
  layoutDuration: 400,
  layoutEasing: 'ease',
  dragSortInterval: 50
});

Пояснение:

  • layoutDuration — длительность анимации в миллисекундах.
  • layoutEasing — функция плавности анимации ('ease', 'linear', 'ease-in-out').
  • dragSortInterval — частота обновления сетки во время перетаскивания, влияет на отзывчивость.

Можно также добавить эффекты при наведении или активации карточки с помощью CSS-трансформаций, которые Muuri корректно учитывает при перерасчете расположения.


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

Для добавления новой задачи используется метод add:

const newItem = document.createElement('div');
newItem.classList.add('kanban-item');
newItem.textContent = 'Новая задача';
todoGrid.add(newItem);
todoGrid.layout(true);

Для удаления:

const itemToRemove = todoGrid.getItems()[0];
todoGrid.remove(itemToRemove, { removeElements: true });
todoGrid.layout(true);

Особенности:

  • removeElements: true полностью удаляет элемент из DOM.
  • После добавления или удаления карточки обязательно вызывается layout(true) для корректного перерасчета позиций и анимации.

Сортировка и фильтрация карточек

Muuri поддерживает сортировку и фильтрацию элементов сетки. Это полезно для реализации функционала «фильтр по приоритету» или «сортировка по дате».

Пример фильтрации по классу:

todoGrid.filter(item => item.getElement().classList.contains('high-priority'));

Сортировка по тексту карточки:

todoGrid.sort((a, b) => {
  return a.getElement().textContent.localeCompare(b.getElement().textContent);
});

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

Для больших досок с сотнями карточек важно учитывать производительность:

  • Использовать dragSortPredicate для ограничения сеток, между которыми может происходить перетаскивание.
  • Минимизировать частоту вызова layout(true) во время массовых изменений.
  • Применять CSS-анимации вместо JavaScript для эффектов вроде масштабирования или подсветки карточек.

Muuri позволяет создавать полностью интерактивные канбан-доски с поддержкой перетаскивания, анимаций, сортировки и фильтрации, обеспечивая при этом высокую отзывчивость интерфейса и гибкость настройки.