Перетаскивание — это распространенное пользовательское действие, встречающееся во многих графических пользовательских интерфейсах.
Существуют готовые библиотеки JavaScript для добавления функции перетаскивания в ваше приложение. Однако в некоторых ситуациях библиотека может быть недоступна, или ее использование может быть связано с издержками или зависимостями, которые не нужны вашему проекту. В таких ситуациях найти альтернативное решение поможет знание API-интерфейсов, доступных в современных браузерах.
Так, HTML Drag and Drop API использует модель событий DOM для получения информации о перетаскиваемом элементе и обновления этого элемента после перетаскивания. С обработчиками событий JavaScript вы можете превратить любой элемент в перетаскиваемый элемент или в цель перетаскивания.
В этом обучающем модуле мы построим пример перетаскиваемого элемента, используя HTML Drag and Drop API с JavaScript без расширений для использования обработчиков событий.
Для данного обучающего руководства вам потребуется следующее:
Наш проект будет состоять из контейнера с двумя типами дочерних элементов:
Откройте окно терминала и создайте новый каталог проекта:
- mkdir drag-and-drop-example
Затем перейдите в этот каталог:
- cd drag-and-drop-example
Создайте в этом каталоге файл index.html
:
- nano index.html
Добавьте базовый код веб-страницы HTML:
<!DOCTYPE html>
<html>
<head>
<title>My Drag-and-Drop Example</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
</body>
</html>
Добавьте между тегами <body>
перетаскиваемый элемент draggable
и элемент dropzone
(цель перетаскивания):
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
>
draggable
</div>
</div>
<div
class="example-dropzone"
>
dropzone
</div>
</div>
Сохраните и закройте файл. Затем создайте файл style.css
:
- nano style.css
Добавьте стили элементов в файл index.html
:
.example-parent {
border: 2px solid #DFA612;
color: black;
display: flex;
font-family: sans-serif;
font-weight: bold;
}
.example-origin {
flex-basis: 100%;
flex-grow: 1;
padding: 10px;
}
.example-draggable {
background-color: #4AAE9B;
font-weight: normal;
margin-bottom: 10px;
margin-top: 10px;
padding: 10px;
}
.example-dropzone {
background-color: #6DB65B;
flex-basis: 100%;
flex-grow: 1;
padding: 10px;
}
При этом в приложение будет добавлено определенное форматирование. Теперь вы можете открыть файл index.html
в браузере и увидеть элементы draggable
<div>
и dropzone
<div>
.
Затем мы явно сделаем первый <div>
перетаскиваемым, добавив атрибут draggable
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
>
draggable
</div>
</div>
<div
class="example-dropzone"
>
dropzone
</div>
</div>
Сохраните и закройте файл.
В заключение снова откройте файл index.html
в браузере. Если мы нажмем на элемент draggable
<div>
и перетащим его через экран, потребуется визуальная индикация перемещения.
По умолчанию атрибут draggable
имеет значение auto
. Это означает, что поведение браузера по умолчанию определяет, является ли элемент перетаскиваемым. Обычно это значит, что выделенный текст, изображения и ссылки можно перетаскивать, не задавая draggable="true"
.
Теперь у нас есть файл HTML с перетаскиваемым элементом. Мы перейдем к добавлению обработчиков onevent
.
Сейчас, если мы отпустим мышь при перетаскивании перетаскиваемого элемента, ничего не произойдет. Чтобы при перетаскивании элементов DOM активировалось действие, нам необходимо использовать Drag and Drop API:
ondragstart
: этот обработчик событий прикрепляется к нашему элементу draggable
и срабатывает при возникновении события dragstart
.ondragover
: этот обработчик событий прикрепляется к нашему элементу dropzone
и срабатывает при возникновении события dragover
.ondrop
: этот обработчик событий прикрепляется к нашему элементу dropzone
и срабатывает при возникновении события drop
.Примечание. Всего доступно восемь обработчиков событий: ondrag
, ondragend
, ondragenter
, ondragexit
, ondragleave
, ondragover
, ondragstart
и ondrop
. В нашем примере они требуются не все.
Вначале разместим ссылку на новый файл script.js
в нашем файле index.html
:
<body>
...
<script src="script.js"></script>
</body>
Затем создадим новый файл script.js
:
- nano script.js
Объект DataTransfer
будет отслеживать информацию, связанную с текущим перетаскиванием. Чтобы обновить наш элемент после перетаскивания, нам нужен прямой доступ к объекту DataTransfer
. Для этого мы можем выбрать свойство dataTransfer
события DragEvent
элемента DOM.
Примечание. Объект DataTransfer
технически может отслеживать информацию нескольких элементов, перетаскиваемых одновременно. В нашем примере мы ограничимся перетаскиванием одного элемента.
Метод setData
объекта dataTransfer
можно использовать, чтобы задать информацию о состоянии перетаскивания текущего элемента. Для этого нужны два параметра:
Наша цель — переместить элемент draggable
в новый родительский элемент. Нам нужна возможность выбрать элемент draggable
с уникальным идентификатором id
. Мы можем задать id
перетаскиваемого элемента с помощью метода setData
, чтобы его можно было использовать позднее.
Давайте снова откроем файл script.js
и создадим новую функцию для использования setData
:
function onDragStart(event) {
event
.dataTransfer
.setData('text/plain', event.target.id);
}
Примечание. Сообщается, что в версиях Internet Explorer с 9 по 11 возникают проблемы при использовании 'text/plain'
. Для этих версий браузера следует использовать формат 'text'
.
Чтобы обновить стили CSS перетаскиваемого элемента, мы можем снова получить доступ к его стилям, используя событие DOM, и установив желаемые стили для currentTarget
.
Дополним нашу функцию и изменим значение backgroundColor
на yellow
:
function onDragStart(event) {
event
.dataTransfer
.setData('text/plain', event.target.id);
event
.currentTarget
.style
.backgroundColor = 'yellow';
}
Примечание. Любые изменяемые стили потребуется снова обновлять вручную после перетаскивания, если вы используете только стили на время перетаскивания. Если вы измените что-то в начале перетаскивания, перетащенный элемент сохранит новый стиль, если вы снова его не измените.
Теперь у нас есть функция JavaScript для начала перетаскивания.
Мы можем добавить ondragstart
в элемент draggable
в файле index.html
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
draggable
</div>
</div>
<div class="example-dropzone">
dropzone
</div>
</div>
Откройте файл index.html
в браузере. Если вы теперь попытаетесь перетащить элемент, будут применены стили, декларированные в нашей функции:
Однако если отпустить элемент, ничего не произойдет.
Следующим в этой последовательности срабатывает обработчик событий ondragover
.
Поведение определенных элементов DOM по умолчанию, в том числе <div>
в браузерах, обычно не принимает отпускание. Такое поведение перехватит поведение, которое мы пытаемся реализовать. Чтобы гарантированно получить желаемое поведение при отпускании, мы применим preventDefault
.
Давайте снова откроем файл script.js
и создадим новую функцию для использования preventDefault
: Добавьте в конец файла следующий код:
function onDragOver(event) {
event.preventDefault();
}
Теперь мы можем добавить ondragover
в элемент dropzone
в файле index.html
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
draggable
</div>
</div>
<div
class="example-dropzone"
ondragover="onDragOver(event);"
>
dropzone
</div>
</div>
На этом этапе мы еще не написали код для обработки завершения перетаскивания. Последним в этой последовательности срабатывает обработчик событий ondrop
.
Вернемся в файл script.js
и создадим новую функцию.
Мы можем сослаться на ранее сохраненные данные, используя метод setData
объекта dataTransfer
. Мы будем использовать метод getData
объекта dataTransfer
. Мы задали данные id
, и поэтому результат выполнения будет выглядеть так:
function onDrop(event) {
const id = event
.dataTransfer
.getData('text');
}
Выберем элемент draggable
с полученным id
:
function onDrop(event) {
// ...
const draggableElement = document.getElementById(id);
}
Выберем элемент dropzone
:
function onDrop(event) {
// ...
const dropzone = event.target;
}
Добавим элемент draggable
в dropzone
:
function onDrop(event) {
// ...
dropzone.appendChild(draggableElement);
}
Сбросим объект dataTransfer
:
function onDrop(event) {
// ...
event
.dataTransfer
.clearData();
}
Теперь мы можем добавить ondrop
в элемент dropzone
в файле index.html
:
<div class="example-parent">
<div class="example-origin">
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
draggable
</div>
</div>
<div
class="example-dropzone"
ondragover="onDragOver(event);"
ondrop="onDrop(event);"
>
dropzone
</div>
</div>
Сделав это, мы завершили реализацию функции перетаскивания. Откройте файл index.html
в браузере и перетащите элемент draggable
в dropzone
.
В нашем примере мы рассмотрели сценарий с одним перетаскиваемым элементом и одной целевой зоной. Мы можем использовать несколько перетаскиваемых элементов, несколько целей, и настроить все это с помощью других обработчиков событий Drag and Drop API.
Приведем пример возможного использования этого API: список задач с перетаскиваемыми задачами, которые вы можете перетаскивать из столбца «Сделать»
в столбец «Сделано»
.
Чтобы создать собственный список задач, добавьте дополнительные перетаскиваемые элементы с уникальными id
в файл index.html
:
<div class="example-parent">
<h1>To-do list</h1>
<div class="example-origin">
To-do
<div
id="draggable-1"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 1
</div>
<div
id="draggable-2"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 2
</div>
<div
id="draggable-3"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 3
</div>
<div
id="draggable-4"
class="example-draggable"
draggable="true"
ondragstart="onDragStart(event);"
>
thing 4
</div>
</div>
<div
class="example-dropzone"
ondragover="onDragOver(event);"
ondrop="onDrop(event);"
>
Done
</div>
</div>
Откройте index.html
в браузере и перетащите элементы из столбца «Сделать» в столбец «Сделано». Вы создали приложение списка задач и протестировали его работу.
В этой статье мы создали приложение списка задач, чтобы изучить возможности функции перетаскивания, доступной в современных браузерах.
Drag and Drop API предоставляет много разных возможностей настроить действия в дополнение к перетаскиванию. Например, вы можете обновлять стили CSS перетаскиваемых элементов. Также вместо перемещения вы можете копировать перетаскиваемый элемент так, чтобы при отпускании он реплицировался.
Помните, что хотя многие браузеры поддерживают эту технологию, вы не можете на нее полагаться, если ваша целевая аудитория включает устройства, не поддерживающие данную функцию.
Чтобы узнать больше обо всех элементах, которые вы можете перетаскивать с помощью Drag and Drop API, ознакомьтесь с соответствующей документацией MDN.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!