Подробное объяснение собственных событий перетаскивания h5

JavaScript HTML

Это 4-й день моего участия в августовском испытании обновлений.Подробности о событии:Испытание августовского обновления

событие перетаскивания

Типы событий перетаскивания

Перетаскивание — это когда пользователь, удерживая кнопку мыши на объекте, перетаскивает его в другое место, а затем отпускает кнопку мыши, чтобы поместить туда объект.

Существует несколько типов перетаскиваемых объектов, включая узлы элементов, изображения, ссылки, выделенный текст и т. д. На веб-страницах, за исключением узлов элементов, которые нельзя перетаскивать по умолчанию, другие (изображения, ссылки, выделенный текст) можно перетаскивать напрямую. Чтобы сделать узел элемента перетаскиваемым, узелdraggableсвойство установлено наtrue.

<div draggable="true">
  此区域可拖拉
</div>

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

draggableатрибуты могут использоваться на любом узле элемента, но изображения (<img>) и ссылки (<a>) без этого атрибута можно перетаскивать. Для них при использовании этого свойства часто устанавливается значениеfalse, предотвращая перетаскивание обоих элементов.

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

При перетаскивании узла элемента или выделенного текста постоянно запускаются события перетаскивания, включая некоторые из следующих событий.

  • drag: во время процесса перетаскивания непрерывно запускать перетаскиваемый узел (с интервалом в несколько сотен миллисекунд).
  • dragstart: Запускается на перетаскиваемом узле, когда пользователь начинает перетаскивание, событиеtargetАтрибут — это перетаскиваемый узел. Обычно перетаскиваемые данные должны быть указаны в функции слушателя этого события.
  • dragend: Запускается на перетаскиваемом узле, когда перетаскивание закончилось (отпустите кнопку мыши или нажмите клавишу ESC), событиеtargetАтрибут — это перетаскиваемый узел. это сdragstartсобытие, запущенное на том же узле. Независимо от того, происходит ли перетаскивание по окнам или оно прерывается на полпути,dragendСобытия всегда срабатывают.
  • dragenter: при перетаскивании в текущий узел срабатывает один раз на текущем узле, и событиеtargetСвойство является текущим узлом. Обычно в функции слушателя этого события указывают, разрешать ли перетаскиваемые данные сбрасывать (сбрасывать) на текущем узле. Если текущий узел не имеет функции прослушивания события или функция прослушивателя не выполняет никаких операций, это означает, что данные не могут быть удалены на текущем узле. В функции прослушивателя этого события также задается визуальное отображение перетаскивания в текущий узел.
  • dragover: при перетаскивании на текущий узел он будет продолжать срабатывать на текущем узле (с разницей в несколько сотен миллисекунд), а событиеtargetСвойство является текущим узлом. Это событие связано сdragenterРазница между событиями в том,dragenterСобытие срабатывает при входе в узел, затем, пока узел не вышел,dragoverСобытия будут продолжаться.
  • dragleave: Запускается на текущем узле, когда операция перетаскивания выходит за пределы текущего узла, событиеtargetСвойство является текущим узлом. Если вы хотите визуально отобразить текущий узел операции перетаскивания, установите его в функции прослушивателя этого события.
  • drop: Запускается на целевом узле, когда перетаскиваемый узел или выделенный текст передаются на целевой узел. Обратите внимание, что если текущий узел не позволяетdrop, событие не сработает, даже если кнопка мыши будет отпущена над узлом. Если пользователь нажмет клавишу ESC для отмены операции, событие не будет запущено. Функция прослушивания этого события отвечает за выборку данных перетаскивания и выполнение соответствующей обработки.

В следующем примере показано, как динамически изменить цвет фона перетаскиваемого узла.

div.addEventListener('dragstart', function (e) {
  this.style.backgroundColor = 'red';
}, false);

div.addEventListener('dragend', function (e) {
  this.style.backgroundColor = 'green';
}, false);

В приведенном выше кодеdivКогда узел перетаскивается, цвет фона меняется на красный, а когда перетаскивание заканчивается, он снова становится зеленым.

Ниже приведен пример, показывающий, как перетащить узел из текущего родительского узла в другой родительский узел.

/* HTML 代码如下
 <div class="dropzone">
   <div id="draggable" draggable="true">
     该节点可拖拉
   </div>
 </div>
 <div class="dropzone"></div>
 <div class="dropzone"></div>
 <div class="dropzone"></div>
*/

// 被拖拉节点
var dragged;

document.addEventListener('dragstart', function (event) {
  // 保存被拖拉节点
  dragged = event.target;
  // 被拖拉节点的背景色变透明
  event.target.style.opacity = 0.5;
}, false);

document.addEventListener('dragend', function (event) {
  // 被拖拉节点的背景色恢复正常
  event.target.style.opacity = '';
}, false);

document.addEventListener('dragover', function (event) {
  // 防止拖拉效果被重置,允许被拖拉的节点放入目标节点
  event.preventDefault();
}, false);

document.addEventListener('dragenter', function (event) {
  // 目标节点的背景色变紫色
  // 由于该事件会冒泡,所以要过滤节点
  if (event.target.className === 'dropzone') {
    event.target.style.background = 'purple';
  }
}, false);

document.addEventListener('dragleave', function( event ) {
  // 目标节点的背景色恢复原样
  if (event.target.className === 'dropzone') {
    event.target.style.background = '';
  }
}, false);

document.addEventListener('drop', function( event ) {
  // 防止事件默认行为(比如某些元素节点上可以打开链接),
  event.preventDefault();
  if (event.target.className === 'dropzone') {
    // 恢复目标节点背景色
    event.target.style.background = '';
    // 将被拖拉节点插入目标节点
    dragged.parentNode.removeChild(dragged);
    event.target.appendChild( dragged );
  }
}, false);

Есть несколько моментов, на которые следует обратить внимание в отношении событий перетаскивания.

  • Процесс перетаскивания запускает только указанные выше события перетаскивания, хотя мышь движется, события мыши не будут запускаться.
  • Перетащите файл из ОС в браузер, не срабатываетdragstartа такжеdragendмероприятие.
  • dragenterа такжеdragoverФункция прослушивателя событий используется для извлечения перетаскиваемых данных (то есть для того, чтобы перетаскиваемый элемент мог быть удален). Поскольку большинство областей веб-страницы не подходят в качестве целевых узлов для перетаскивания элементов, настройки по умолчанию для этих двух событий таковы, что текущему узлу не разрешено принимать перетаскиваемые элементы. Если вы хотите удалить данные на целевом узле, вы должны сначала предотвратить поведение этих двух событий по умолчанию.
<div ondragover="return false">
<div ondragover="event.preventDefault()">

В приведенном выше коде без отмены события перетаскивания или предотвращения поведения по умолчанию вы не можетеdivПоместите перетащенный узел на узел.

Интерфейс DragEvent

События перетаскивания наследуютсяDragEventинтерфейс, который наследуется отMouseEventинтерфейс иEventинтерфейс.

Браузер изначально предоставляетDragEvent()Конструктор, используемый для создания экземпляра объекта события перетаскивания.

new DragEvent(type, options)

DragEvent()Конструктор принимает два параметра, первый параметр — это строка, указывающая тип события, которое требуется, второй параметр — объект конфигурации события, который используется для установки свойств события, и этот параметр необязательный. объект конфигурации в дополнение к принятиюMouseEventинтерфейс иEventСвойства конфигурации интерфейса также могут быть установленыdataTransferсобственность либоnull, либоDataTransferЭкземпляр интерфейса.

DataTransferОбъект экземпляра используется для чтения и записи данных, передаваемых в событии перетаскивания.Подробности см. в разделе «Интерфейс передачи данных» ниже.

Обзор интерфейса DataTransfer

Все экземпляры событий перетаскивания имеютDragEvent.dataTransferАтрибуты используются для чтения и записи данных, которые необходимо передать. Значение этого свойства равноDataTransferЭкземпляр интерфейса.

Браузер изначально предоставляетDataTransfer()конструктор для генерацииDataTransferобъект экземпляра.

var dataTrans = new DataTransfer();

DataTransfer()Конструктор не принимает никаких параметров.

Перетаскиваемые данные делятся на два аспекта: тип данных (он же формат) и значение данных. Тип данных — это строка MIME (например,text/plain,image/jpeg), значение данных представляет собой строку. Вообще говоря, если вы перетаскиваете фрагмент текста, данные по умолчанию соответствуют этому тексту; если вы перетаскиваете ссылку, данные по умолчанию соответствуют URL-адресу ссылки.

Когда начинается событие перетаскивания, разработчик может указать тип данных и значение данных. В процессе перетаскивания проявитель проходитdragenterа такжеdragoverФункция прослушивателя событий, которая проверяет тип данных, чтобы определить, разрешено ли отбрасывать перетаскиваемый объект. Например, в области, где разрешено отбрасывать только ссылки, проверьте, соответствует ли перетаскиваемый тип данныхtext/uri-list.

происходитьdropКогда происходит событие, функция слушателя извлекает перетаскиваемые данные и обрабатывает их.

Свойства экземпляра DataTransfer

DataTransfer.dropEffect

DataTransfer.dropEffectСвойство используется для установки эффекта отбрасывания перетаскиваемого узла, который влияет на форму мыши при перетаскивании по соответствующей области. Может принимать следующие значения.

  • копировать: скопировать перетаскиваемый узел
  • move: переместить перетащенный узел
  • ссылка: создать ссылку на перетаскиваемый узел
  • none: нельзя удалить перетаскиваемый узел

Помимо указанных выше значений, установка других значений недействительна.

target.addEventListener('dragover', function (e) {
  e.preventDefault();
  e.stopPropagation();
  e.dataTransfer.dropEffect = 'copy';
});

В приведенном выше коде, как только перетаскиваемый элементdrop, принятый регион реплицирует узел.

dropEffectсвойства, как правило, вdragenterа такжеdragoverУстановите в функции слушателя событий, дляdragstart,drag,dragleaveДля этих трех событий это свойство не действует. Поскольку это свойство действительно только для области, которая принимает перетаскиваемый узел, оно не влияет на сам перетаскиваемый узел. После входа в целевую область поведение перетаскивания будет инициализировано для заданного эффекта.

DataTransfer.effectAllowed

DataTransfer.effectAllowedСвойство устанавливает эффекты, разрешенные в этом перетаскивании. Может принимать следующие значения.

  • копировать: скопировать перетаскиваемый узел
  • move: переместить перетащенный узел
  • ссылка: создать ссылку на перетаскиваемый узел
  • копироватьСсылка: разрешитьcopyилиlink
  • copyMove: разрешитьcopyилиmove
  • ссылкаПереместить: разрешитьlinkилиmove
  • все: разрешить все эффекты
  • none: нельзя удалить перетаскиваемый узел
  • неинициализированный: значение по умолчанию, эквивалентноеall

Если эффект не разрешен, пользователь не может добиться этого эффекта в целевом узле.

Это свойство связано сdropEffectСвойства — это две стороны одного и того же. Первый устанавливает эффект, разрешенный перетаскиваемым узлом, а второй устанавливает эффект области, которая принимает перетаскивание, и они часто используются вместе.

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

source.addEventListener('dragstart', function (e) {
  e.dataTransfer.effectAllowed = 'move';
});

target.addEventListener('dragover', function (e) {
  e.dataTransfer.dropEffect = 'move';
});

если толькоdropEffectсвойства иeffectAllowedСреди свойств естьnone, это невозможно сделать на целевом узлеdropработать.

DataTransfer.files

DataTransfer.filesСвойство представляет собой объект FileList, содержащий набор локальных файлов, которые можно использовать для передачи в операции перетаскивания. Если это перетаскивание не затрагивает файлы, это свойство является пустым объектом FileList.

Ниже приведен пример получения перетаскиваемого файла.

// HTML 代码如下
// <div id="output" style="min-height: 200px;border: 1px solid black;">
//   文件拖拉到这里
// </div>

var div = document.getElementById('output');

div.addEventListener("dragenter", function( event ) {
  div.textContent = '';
  event.stopPropagation();
  event.preventDefault();
}, false);

div.addEventListener("dragover", function( event ) {
  event.stopPropagation();
  event.preventDefault();
}, false);

div.addEventListener("drop", function( event ) {
  event.stopPropagation();
  event.preventDefault();
  var files = event.dataTransfer.files;
  for (var i = 0; i < files.length; i++) {
    div.textContent += files[i].name + ' ' + files[i].size + '字节\n';
  }
}, false);

В приведенном выше коде с помощьюdataTransfer.filesСвойства для чтения информации о перетаскиваемом файле. Если вы хотите прочитать содержимое файла, вам нужно использоватьFileReaderобъект.

div.addEventListener('drop', function(e) {
  e.preventDefault();
  e.stopPropagation();

  var fileList = e.dataTransfer.files;
  if (fileList.length > 0) {
    var file = fileList[0];
    var reader = new FileReader();
    reader.onloadend = function(e) {
      if (e.target.readyState === FileReader.DONE) {
        var content = reader.result;
        div.innerHTML = 'File: ' + file.name + '\n\n' + content;
      }
    }
    reader.readAsBinaryString(file);
  }
});

DataTransfer.types

DataTransfer.typesСвойство представляет собой массив только для чтения, где каждый элемент представляет собой строку, содержащую перетаскиваемый формат данных (обычно значение MIME). Например, если перетаскивание представляет собой текст, соответствующий элементtext/plain.

Вот пример, проверивdataTransferТип атрибута, который определяет, разрешить ли выполнение на текущем узлеdropработать.

function contains(list, value){
  for (var i = 0; i < list.length; ++i) {
    if(list[i] === value) return true;
  }
  return false;
}

function doDragOver(event) {
  var isLink = contains(event.dataTransfer.types, 'text/uri-list');
  if (isLink) event.preventDefault();
}

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

DataTransfer.items

DataTransfer.itemsСвойство возвращает подобный массиву объект только для чтения (экземпляр DataTransferItemList), каждый член которого является объектом (экземпляром DataTransferItem) для этого перетаскивания. Если текущее перетаскивание не содержит объектов, возвращается пустой объект.

Экземпляр DataTransferItemList имеет следующие свойства и методы.

  • length: Возвращает количество участников
  • add(data, type): добавить указанный контент и тип (например,text/htmlа такжеtext/plain) строка как элемент
  • add(file):addДругое использование метода, добавление файла в качестве члена
  • remove(index): удалить член в указанной позиции
  • clear(): удалить всех членов

Экземпляры DataTransferItem имеют следующие свойства и методы.

  • kind: возвращает тип члена (stringещеfile).
  • type: возвращает тип члена (обычно значение MIME).
  • getAsFile(): Если перетаскиваемый файл, вернуть файл, в противном случае вернутьnull.
  • getAsString(callback): если перетаскиваемая строка является строкой, передайте символ указанной функции обратного вызова для обработки. Этот метод является асинхронным, поэтому необходимо передать функцию обратного вызова.

Ниже приведен пример.

div.addEventListener('drop', function (e) {
  e.preventDefault();
  if (e.dataTransfer.items != null) {
    for (var i = 0; i < e.dataTransfer.items.length; i++) {
      console.log(e.dataTransfer.items[i].kind + ': ' + e.dataTransfer.items[i].type);
    }
  }
});

Экземплярные методы передачи данных

DataTransfer.setData()

DataTransfer.setData()Этот метод используется для установки данных, переносимых событием перетаскивания. Этот метод не имеет возвращаемого значения.

event.dataTransfer.setData('text/plain', 'Text to drag');

Приведенный выше код добавляет простые текстовые данные для текущего события перетаскивания.

Этот метод принимает два параметра, оба из которых являются строками. Первый параметр представляет тип данных (например,text/plain), второй параметр — это конкретные данные. Если указанный тип данных находится вdataTransferЕсли атрибут не существует, данные будут добавлены, в противном случае исходные данные будут заменены новыми данными.

Если текстовое поле перетаскивается или выделенный текст перетаскивается, соответствующие текстовые данные будут добавлены кdataTransferсвойства, не нужно задавать вручную.

<div draggable="true">
  aaa
</div>

В приведенном выше коде перетащите это<div>Элементы автоматически несут текстовые данныеaaa.

использоватьsetDataметод замены исходных данных.

<div
  draggable="true"
  ondragstart="event.dataTransfer.setData('text/plain', 'bbb')"
>
  aaa
</div>

В приведенном выше коде данные перетаскивания на самом делеbbb, вместоaaa.

Ниже добавлены другие типы данных. из-заtext/plainЭто наиболее часто поддерживаемый формат.Для обеспечения совместимости рекомендуется всегда сохранять данные в текстовом формате в конце.

var dt = event.dataTransfer;

// 添加链接
dt.setData('text/uri-list', 'http://www.example.com');
dt.setData('text/plain', 'http://www.example.com');

// 添加 HTML 代码
dt.setData('text/html', 'Hello there, <strong>stranger</strong>');
dt.setData('text/plain', 'Hello there, <strong>stranger</strong>');

// 添加图像的 URL
dt.setData('text/uri-list', imageurl);
dt.setData('text/plain', imageurl);

Данные могут предоставляться сразу в нескольких форматах.

var dt = event.dataTransfer;
dt.setData('application/x-bookmark', bookmarkString);
dt.setData('text/uri-list', 'http://www.example.com');
dt.setData('text/plain', 'http://www.example.com');

В приведенном выше коде при сохранении трех типов данных об одном и том же событии событие перетаскивания может относиться к разным объектам.dropразные значения. Обратите внимание, что первый формат является настраиваемым форматом, который не может быть прочитан браузерами по умолчанию, а это означает, что только узел с развернутым определенным кодом можноdrop(читать) эти данные.

DataTransfer.getData()

DataTransfer.getData()Метод принимает строку (представляющую тип данных) в качестве параметра и возвращает данные указанного типа (обычно используется с событием).setDataдобавлен метод). Возвращает пустую строку, если данные указанного типа не существуют. обычно толькоdropПосле запуска события данные могут быть получены.

Ниже приведенdropФункция прослушивателя событий используется для получения данных указанного типа.

function onDrop(event) {
  var data = event.dataTransfer.getData('text/plain');
  event.target.textContent = data;
  event.preventDefault();
}

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

getDataМетод возвращает строку, которую необходимо проанализировать вручную, если она содержит несколько фрагментов данных.

function doDrop(event) {
  var lines = event.dataTransfer.getData('text/uri-list').split('\n');
  for (let line of lines) {
    let link = document.createElement('a');
    link.href = line;
    link.textContent = line;
    event.target.appendChild(link);
  }
  event.preventDefault();
}

В приведенном выше кодеgetDataМетод возвращает набор ссылок, которые должны быть разрешены сами по себе.

Значение типа указывается какURL, вы можете удалить первую действующую ссылку.

var link = event.dataTransfer.getData('URL');

В следующем примере показано извлечение данных из различных типов данных.

function doDrop(event) {
  var types = event.dataTransfer.types;
  var supportedTypes = ['text/uri-list', 'text/plain'];
  types = supportedTypes.filter(function (value) { types.includes(value) });
  if (types.length) {
    var data = event.dataTransfer.getData(types[0]);
  }
  event.preventDefault();
}

DataTransfer.clearData()

DataTransfer.clearData()Метод принимает строку (указанный тип данных) в качестве параметра, удаляет данные указанного типа, принадлежащего события. Если вы не укажете тип, удалите все данные. Если указанный тип не существует, вызывая метод не дает никакого эффекта.

event.dataTransfer.clearData('text/uri-list');

Приведенный выше код очищает событиеtext/uri-listтип данных.

Этот метод не удаляет перетаскиваемый файл, поэтому после вызова этого методаDataTransfer.typesсвойства могут все еще возвращатьсяFilesТип (при условии, что есть перетаскивание файла).

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

DataTransfer.setDragImage()

Во время перетаскивания (dragstartПосле запуска события браузер отобразит изображение, которое перемещается с помощью мыши, представляющее перетаскиваемый узел. Это изображение создается автоматически, обычно показывая внешний вид перетаскиваемого узла, нет необходимости настраивать его самостоятельно.

DataTransfer.setDragImage()способ настроить это изображение. Он принимает три параметра. первый<img>узел или<canvas>узел, если он опущен или какnull, используется внешний вид перетаскиваемого узла, второй и третий параметры - абсцисса и ордината мыши относительно левого верхнего угла картинки.

Ниже приведен пример.

/* HTML 代码如下
 <div id="drag-with-image" class="dragdemo" draggable="true">
   drag me
 </div>
*/

var div = document.getElementById('drag-with-image');
div.addEventListener('dragstart', function (e) {
  var img = document.createElement('img');
  img.src = 'http://path/to/img';
  e.dataTransfer.setDragImage(img, 0, 0);
}, false);