Поиск по сайту:

Как создавать элементы перетаскивания с помощью ванильного JavaScript и HTML


Введение

Перетаскивание — обычное взаимодействие с пользователем, которое можно найти во многих графических пользовательских интерфейсах.

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

HTML Drag and Drop API использует модель событий DOM для получения информации о том, что перетаскивается или отбрасывается, и для обновления этого элемента при перетаскивании. С помощью обработчиков событий JavaScript вы можете превратить любой элемент в перетаскиваемый элемент или элемент, в который можно вставить.

В этом руководстве мы создадим пример перетаскивания с использованием HTML Drag and Drop API с ванильным JavaScript для использования обработчиков событий.

Предпосылки

Для выполнения этого урока вам понадобятся:

  • Современный веб-браузер с поддержкой Drag and Drop API (Chrome 4+, Firefox 3.5+, Safari 3.1+, Edge 18+).

Шаг 1 — Создание проекта и начальная разметка

Наш проект будет состоять из контейнера с двумя типами дочерних элементов:

  • Дочерние элементы, которые можно перетаскивать
  • Дочерние элементы, в которые могут быть вставлены элементы

Сначала откройте окно терминала и создайте новый каталог проекта:

  1. mkdir drag-and-drop-example

Затем перейдите в этот каталог:

  1. cd drag-and-drop-example

Затем создайте в этом каталоге файл index.html:

  1. 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> добавьте элемент перетаскиваемый и свою зону перетаскивания ( отбросить цель):

<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:

  1. 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 в браузере и заметить, что это создает перетаскиваемый <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 в браузере. Если мы нажмем на перетаскиваемый <div> и перетащим его по экрану, должно появиться визуальное указание на его перемещение.

Значением по умолчанию для атрибута draggable является auto. Это означает, что возможность перетаскивания элемента будет определяться поведением вашего браузера по умолчанию. Обычно это означает, что выделенный текст, изображения и ссылки можно перетаскивать без указания draggable=true.

Теперь у вас есть файл HTML с перетаскиваемым элементом. Мы перейдем к добавлению обработчиков onevent.

Шаг 2 — Обработка событий перетаскивания с помощью JavaScript

В настоящее время, если мы отпускаем мышь во время перетаскивания перетаскиваемого элемента, ничего не происходит. Чтобы инициировать действие при перетаскивании элементов DOM, нам нужно использовать 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:

  1. nano script.js

Объект DataTransfer будет отслеживать информацию, связанную с текущим перетаскиванием. Чтобы обновить наш элемент при перетаскивании, нам нужно получить прямой доступ к объекту DataTransfer. Для этого мы можем выбрать свойство dataTransfer из DragEvent элемента DOM.

Примечание. Объект DataTransfer технически может отслеживать информацию для нескольких элементов, перетаскиваемых одновременно. В нашем примере мы сосредоточимся на перетаскивании одного элемента.

Метод setData объекта dataTransfer может использоваться для установки информации о состоянии перетаскивания для текущего перетаскиваемого элемента. Он принимает два параметра:

  • строка, определяющая формат второго параметра
  • фактические передаваемые данные

Наша цель — переместить наш элемент перетаскиваемый в новый родительский элемент. Нам нужно иметь возможность выбрать наш элемент перетаскиваемый с уникальным 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');
}

Выберите наш элемент перетаскиваемый с полученным id:

function onDrop(event) {
  // ...

  const draggableElement = document.getElementById(id);
}

Выберите наш элемент dropzone:

function onDrop(event) {
  // ...

  const dropzone = event.target;
}

Добавьте наш элемент перетаскиваемый в 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 в браузере и перетащите элемент перетаскиваемый в зону dropzone. .

Наш пример обрабатывает сценарий с одним перетаскиваемым элементом и одной целью перетаскивания. У вас может быть несколько перетаскиваемых элементов, несколько целей перетаскивания и настройка с помощью всех других обработчиков событий Drag and Drop API.

Шаг 3 — Создание расширенного примера с несколькими перетаскиваемыми элементами

Вот еще один пример использования этого 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 в браузере и перетащите элементы из столбца «Задачи» в столбец «Готово». Вы создали приложение to-do и протестировали его функциональность.

Заключение

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

API перетаскивания предоставляет несколько вариантов настройки ваших действий помимо перетаскивания. Например, вы можете обновить стиль CSS перетаскиваемых элементов. Кроме того, вместо перемещения элемента вы можете скопировать перетаскиваемый элемент, чтобы он реплицировался при сбросе.

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

Чтобы узнать больше обо всем, что вы можете перетаскивать с помощью API перетаскивания, ознакомьтесь с документацией MDN по нему.