Drag-and-drop - удобный интерфейсный элемент для веб-приложений. Позволяет интуитивно перемещать объекты мышью. Раньше тяжело было реализовать кроссбраузерно, но теперь с jQuery стало легко. Давайте разберемся как устроен drag-and-drop и как его можно использовать.
Основы Drag and Drop в jQuery
Для реализации drag-and-drop в jQuery используются два плагина - Draggable
и Droppable
. Первый делает элементы перетаскиваемыми, а второй добавляет контейнеры, куда эти элементы можно перетаскивать.
Плагины jQuery UI Draggable и Droppable являются базовыми блоками для создания интерфейсов с drag-and-drop
Чтобы подключить эти плагины, нужно подключить библиотеку jQuery и плагин jQuery UI:
<script src="jquery.min.js"></script> <script src="jquery-ui.min.js"></script>
После этого можно использовать методы draggable()
и droppable()
для настройки элементов.
Основные события Drag and Drop:
- drag - при перетаскивании
- dragstart - в начале перетаскивания
- dragstop - в конце перетаскивания
На эти события можно повесить обработчики и выполнять нужные действия.
Опции плагинов
Плагины имеют множество опций для настройки:
- revert - возврат в исходное положение
- axis - ограничение перемещения по осям
- cursor - изменение курсора
- handle - перетаскивать только за указанный элемент
Сравнение с нативным HTML5 API
В отличие от нативного HTML5 Drag and Drop API библиотека jQuery UI:
- Кроссбраузерна и работает в старых браузерах
- Имеет удобный и функциональный API
- Позволяет легко расширять и настраивать drag-and-drop
Рассмотрим как можно реализовать простой функционал перетаскивания элементов с помощью jQuery.
Делаем элемент перетаскиваемым
Чтобы сделать элемент перетаскиваемым, нужно вызвать метод draggable()
:
$('.item').draggable();
После этого элемент с классом item
можно будет перетаскивать мышью.
Настраиваем область перетаскивания
По умолчанию перетаскивать элементы можно в любом месте страницы. Чтобы ограничить область, используется опция containment
:
$('.item').draggable({ containment: '#container' });
Теперь перемещать элемент можно будет только внутри блока с идентификатором container
.
Добавляем Drop зону
Чтобы определить области, куда можно перетаскивать элементы, используется метод droppable()
:
$('#drop').droppable({ drop: function() { alert('Элемент перетащен!'); } });
В обработчике события drop
можно реализовать нужную логику.
Обработка событий перетаскивания
Помимо события drop
, можно отслеживать:
- dragenter - при входе элемента в drop зону
- dragleave - при выходе из нее
- dragover - при перемещении над ней
Пример: перетаскивание картинок
Рассмотрим пример drag and drop галереи, где можно перетаскивать миниатюры картинок в область preview:
$('.thumbnail').draggable({ helper: 'clone' }); $('#preview').droppable({ drop: function(event, ui) { $(this).html('').append(ui.draggable); } });
Здесь в опции helper
указано значение clone
, чтобы вместо элемента перемещалась его копия. В обработчике события drop
эта копия вставляется в блок preview.
Так можно реализовать drag-and-drop интерфейс для перемещения объектов.
Дополнительная функциональность
Помимо базового функционала перетаскивания элементов, библиотека jQuery UI предоставляет расширенные возможности.
Ограничения и сетка
Можно задавать различные ограничения на перемещение объектов:
- Перетаскивание только горизонтально или вертикально с помощью опции
axis
- Привязка к невидимой сетке через
grid
- Невозможность выйти за пределы родителя через
containment
Вспомогательные элементы
При перетаскивании можно использовать вспомогательные объекты:
- Полупрозрачная копия через
helper: 'clone'
- Произвольный элемент как helper
- Перемещение сразу нескольких объектов
Загрузка файлов перетаскиванием
Реализовать drag-and-drop загрузку файлов на сервер можно следующим образом:
- Отменяем действие браузера на dragover
- Получаем файлы из события drop
- Отправляем их на сервер AJAX запросом
Сортировка списков
Можно изменять порядок элементов в списке путем drag-and-drop:
- Подключить плагин Sortable
- Применить к списку
$('.list').sortable()
Порядок элементов будет автоматически сохраняться.
Перетаскивание между окнами браузера
Реализовать перетаскивание объектов между вкладками или окнами браузера можно используя события:
- dragstart и dragend - для сохранения данных о перемещении
- drop - для получения данных в другом окне
Оптимизация производительности
При использовании большого количества перетаскиваемых объектов или сложных анимаций, может возникнуть необходимость оптимизации производительности drag and drop.
Отключение эффектов
Если не нужны анимации перемещения элементов, их можно отключить через опцию helper
:
$('.item').draggable({ helper: 'original' });
В этом случае перемещаться будет сам элемент без дополнительных эффектов.
Кэширование helper элемента
Для комплексных вспомогательных объектов имеет смысл кэшировать HTML разметку, а не генерировать ее заново:
var helperTemplate = $('<div/>'); $('.item').draggable({ helper: function() { return helperTemplate.clone(); } });
Использование requestAnimationFrame
Для плавной анимации перемещения лучше вместо setTimeout
использовать requestAnimationFrame
.
Оптимизация DOM доступа
Избегать частого обращения к DOM для получения позиции и размеров элементов. Кэшировать значения заранее.
Уменьшение количества обновлений
Отключить ненужные или ресурсозатратные вычисления в обработчиках событий mousemove и scroll при перетаскивании.
Кроссбраузерная поддержка
Чтобы реализовать корректную работу drag and drop функциональности в разных браузерах, нужно учитывать некоторые нюансы.
Поддержка старых браузеров
Для работы в устаревших браузерах без поддержки HTML5, можно использовать полифиллы:
- Filer.js
- DragDropMixin
Либо отказаться от drag and drop с сохранением основного функционала.
Touch события на мобильных
Для корректной работы на сенсорных устройствах, нужно дополнительно обрабатывать события:
- touchstart / touchend вместо mousedown / mouseup
- touchmove вместо mousemove
Чтобы избежать ошибок, можно использовать полифиллы вроде jquery-compat или проверять поддержку API перед инициализацией drag and drop.
Тестирование на разных устройствах
Проверить корректную работу функциональности в разных браузерах и на мобильных устройствах вручную или автотестами.
По результатам тестирования доработать код для корректного поведения скриптов во всех целевых браузерах.