HTML5 Drag & Drop API

In diesem Beitrag werden die Grundlagen von Drag-and-drop erläutert.

Ziehbare Inhalte erstellen

In den meisten Browsern sind Textauswahl, Bilder und Links standardmäßig ziehbar. Wenn Sie beispielsweise einen Link auf einer Webseite ziehen, sehen Sie ein kleines Feld mit einem Titel und URL, die Sie in die Adressleiste oder den Desktop einfügen können, oder navigieren Sie zum Link. Um andere Inhaltstypen ziehbar zu machen, die HTML5 Drag & Drop APIs verwenden.

Wenn Sie ein Objekt ziehbar machen möchten, legen Sie draggable=true für dieses Element fest. Fast Alles lässt sich per Drag-and-drop öffnen, darunter Bilder, Dateien, Links, Dateien -Markup auf Ihrer Seite.

Im folgenden Beispiel wird eine Schnittstelle erstellt, um Spalten neu anzuordnen, CSS-Raster dargestellt werden. Die grundlegende Auszeichnung für die Spalten sieht folgendermaßen aus, wobei das Attribut draggable für jede Spalte, die auf true gesetzt ist:

<div class="container">
  <div draggable="true" class="box">A</div>
  <div draggable="true" class="box">B</div>
  <div draggable="true" class="box">C</div>
</div>

Hier ist der CSS-Code für die Container- und Box-Elemente. Das einzige Preisvergleichsportal für die Ziehfunktion ist die cursor: move Property. Der Rest des Codes steuert das Layout und den Stil des Containers. und Box-Elementen.

.container {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 10px;
}

.box {
  border: 3px solid #666;
  background-color: #ddd;
  border-radius: .5em;
  padding: 10px;
  cursor: move;
}

Nun können Sie die Elemente ziehen, aber sonst passiert nichts. Hinzufügen müssen Sie die JavaScript API verwenden.

Auf Drag-Events warten

Um den Drag-Prozess zu überwachen, können Sie auf eines der folgenden Ereignisse warten:

Für den Drag-Flow benötigen Sie ein Quellelement, beginnt), die Datennutzlast (das gezogene Objekt) und ein Ziel (ein Bereich, Fallenlassen). Das Quellelement kann fast jedes Element sein. Die Das Ziel ist die Drop-Zone oder die Gruppe von Drop-Zonen, die die Daten akzeptieren, die der Nutzer hat. und versuchen, sie fallen zu lassen. Nicht alle Elemente können Ziele sein. Ihr Ziel darf beispielsweise ein Bild sein.

Ziehfolge starten und beenden

Nachdem Sie die draggable="true"-Attribute für Ihre Inhalte definiert haben, hängen Sie ein dragstart-Event-Handler zum Starten der Ziehsequenz für jede Spalte.

Mit diesem Code wird die Deckkraft der Spalte auf 40% festgelegt, wenn der Nutzer beginnt, sie zu ziehen. und setzen Sie ihn wieder auf 100 %, wenn das Zieh-Ereignis endet.

function handleDragStart(e) {
  this.style.opacity = '0.4';
}

function handleDragEnd(e) {
  this.style.opacity = '1';
}

let items = document.querySelectorAll('.container .box');
items.forEach(function (item) {
  item.addEventListener('dragstart', handleDragStart);
  item.addEventListener('dragend', handleDragEnd);
});

Das Ergebnis ist in der folgenden Glitch-Demo zu sehen. Ziehen Sie ein Element und die Deckkraft ändert. Da das Quellelement das Ereignis dragstart enthält, wird die Einstellung this.style.opacity auf 40% gibt dem Nutzer visuelles Feedback, dass dieses Element die aktuell verschobene Auswahl. Wenn Sie das Element ablegen, wird das Quellelement wird wieder auf 100% Deckkraft zurückgesetzt, obwohl Sie das Drop-Verhalten noch nicht definiert haben.

Zusätzliche visuelle Hinweise hinzufügen

Verwenden Sie die Methode dragenter-, dragover- und dragleave-Event-Handler. In diesem Beispiel hat der Parameter Spalten sind nicht nur ziehbar, sondern auch Ablageziele. Helfen Sie dem Nutzer, indem sie die Rahmenlinie gestrichelt darstellen lassen, wenn sie ein verschobenes Element über ein Element halten. Spalte. In Ihrem CSS können Sie beispielsweise eine over-Klasse für Elemente, die Drop-Ziele sind:

.box.over {
  border: 3px dotted #666;
}

Richten Sie dann in Ihrem JavaScript die Event-Handler ein und fügen Sie die over-Klasse hinzu, wenn wird die Spalte verschoben. Sie wird entfernt, sobald das gezogene Element geschlossen wird. In dragend, entfernen wir auch die Klassen am Ende der ziehen.

document.addEventListener('DOMContentLoaded', (event) => {

  function handleDragStart(e) {
    this.style.opacity = '0.4';
  }

  function handleDragEnd(e) {
    this.style.opacity = '1';

    items.forEach(function (item) {
      item.classList.remove('over');
    });
  }

  function handleDragOver(e) {
    e.preventDefault();
    return false;
  }

  function handleDragEnter(e) {
    this.classList.add('over');
  }

  function handleDragLeave(e) {
    this.classList.remove('over');
  }

  let items = document.querySelectorAll('.container .box');
  items.forEach(function(item) {
    item.addEventListener('dragstart', handleDragStart);
    item.addEventListener('dragover', handleDragOver);
    item.addEventListener('dragenter', handleDragEnter);
    item.addEventListener('dragleave', handleDragLeave);
    item.addEventListener('dragend', handleDragEnd);
    item.addEventListener('drop', handleDrop);
  });
});

In diesem Code sind einige Punkte zu beachten:

  • Die Standardaktion für das Ereignis dragover besteht darin, die Eigenschaft dataTransfer.dropEffect auf "none" Die Eigenschaft dropEffect wird weiter unten auf dieser Seite behandelt. Fürs Erste Sie sollten nur wissen, dass das drop-Ereignis dadurch nicht ausgelöst wird. Um dies zu überschreiben rufen Sie e.preventDefault() an. Eine weitere gute Praxis ist, false im selben Handler.

  • Der dragenter-Event-Handler wird zum Umschalten der over-Klasse verwendet dragover Wenn Sie dragover verwenden, wird das Ereignis wiederholt ausgelöst, während der Nutzer das per Drag-and-drop verschobene Element über eine Spalte enthält, wodurch die CSS-Klasse wiederholt. Dadurch führt der Browser viele unnötige Rendering-Aufgaben durch, was sich auf die User Experience auswirken kann. Wir empfehlen dringend, Wenn Sie dragover verwenden müssen, Drosseln oder Entprellen des Ereignis-Listeners.

Absolviere den Drop

Fügen Sie dem drop-Ereignis einen Event-Listener hinzu, um das Löschen zu verarbeiten. Im drop müssen Sie das Standardverhalten des Browsers für Drops, ist normalerweise eine lästige Weiterleitung. Rufen Sie dazu e.stopPropagation() auf.

function handleDrop(e) {
  e.stopPropagation(); // stops the browser from redirecting.
  return false;
}

Achten Sie darauf, den neuen Handler zusammen mit den anderen Handlern zu registrieren:

  let items = document.querySelectorAll('.container .box');
  items.forEach(function(item) {
    item.addEventListener('dragstart', handleDragStart);
    item.addEventListener('dragover', handleDragOver);
    item.addEventListener('dragenter', handleDragEnter);
    item.addEventListener('dragleave', handleDragLeave);
    item.addEventListener('dragend', handleDragEnd);
    item.addEventListener('drop', handleDrop);
  });

Wenn Sie den Code zu diesem Zeitpunkt ausführen, wird das Element nicht am neuen Speicherort abgelegt. Bis Verwenden Sie dazu den DataTransfer -Objekt enthält.

Die Eigenschaft dataTransfer enthält die Daten, die bei einer Drag-Aktion gesendet werden. dataTransfer wird im Ereignis dragstart festgelegt und im Drop-Ereignis gelesen oder verarbeitet. Anrufen Mit e.dataTransfer.setData(mimeType, dataPayload) können Sie das MIME des Objekts festlegen Typ und Datennutzlast.

In diesem Beispiel lassen wir die Nutzenden die Reihenfolge der Spalten neu anordnen. Dazu müssen Sie zunächst den HTML-Code des Quellelements speichern, Beginn:

function handleDragStart(e) {
  this.style.opacity = '0.4';

  dragSrcEl = this;

  e.dataTransfer.effectAllowed = 'move';
  e.dataTransfer.setData('text/html', this.innerHTML);
}

Im drop-Ereignis verarbeiten Sie das Löschen der Spalte, indem Sie den Wert der Quellspalte HTML zum HTML der Zielspalte hinzu, in der Sie die Daten abgelegt haben. Dieses stellt sicher, dass Nutzende nicht wieder in dieselbe Spalte wechseln, z. B. von der Seite gezogen wird.

function handleDrop(e) {
  e.stopPropagation();

  if (dragSrcEl !== this) {
    dragSrcEl.innerHTML = this.innerHTML;
    this.innerHTML = e.dataTransfer.getData('text/html');
  }

  return false;
}

Das Ergebnis können Sie sich in der folgenden Demo ansehen. Dafür ist eine Desktop-Browser. Die Drag & Drop API wird auf Mobilgeräten nicht unterstützt. Ziehen und lassen Sie die Spalte A über der Spalte B los und achten Sie darauf, wie sich die Positionen ändern:

Weitere Eigenschaften zum Ziehen

Das dataTransfer-Objekt stellt Eigenschaften bereit, um dem während des Drag-Vorgangs nutzen und steuern, wie jedes Drop-Ziel auf eine Datentyp.

  • dataTransfer.effectAllowed schränkt die Art des Drag die die Nutzenden mit dem Element ausführen können. Es wird verwendet im Drag-and-drop-Verarbeitungsmodell zum Initialisieren von dropEffect während die Ereignisse dragenter und dragover. Die Unterkunft kann die folgende Werte: none, copy, copyLink, copyMove, link, linkMove, move, all und uninitialized.
  • dataTransfer.dropEffect steuert das Feedback, das der Nutzer während der dragenter und dragover erhält. Ereignisse. Wenn der Nutzer den Zeiger über ein Zielelement hält, wird das Objekt Der Cursor zeigt an, welche Art von Vorgang stattfinden wird, z. B. eine Kopie oder einen Zug. Der Effekt kann einen der folgenden Werte annehmen: none, copy, link, move.
  • e.dataTransfer.setDragImage(imgElement, x, y) bedeutet, dass statt des standardmäßigen "Ghost Image" des Browsers Feedback geben, ein Ziehsymbol festlegen.

Datei hochladen

In diesem einfachen Beispiel wird eine Spalte sowohl als Drag-Quelle als auch Ziehziel verwendet. Dieses in einer Benutzeroberfläche passieren, in der Nutzende aufgefordert werden, Elemente neu anzuordnen. In einigen Situationen Das Drag-Ziel und die Quelle können unterschiedliche Elementtypen sein, wie in einer Oberfläche bei denen Nutzende ein Bild als Hauptbild für ein Produkt auswählen müssen, das ausgewählte Bild auf ein Ziel zieht.

Drag-and-drop wird häufig verwendet, damit Nutzer Elemente von ihrem Desktop einer Anwendung. Der Hauptunterschied liegt im drop-Handler. Anstelle von dataTransfer.getData() nicht auf die Dateien zugreifen dürfen. Die Daten befinden sich in der dataTransfer.files-Property:

function handleDrop(e) {
  e.stopPropagation(); // Stops some browsers from redirecting.
  e.preventDefault();

  var files = e.dataTransfer.files;
  for (var i = 0, f; (f = files[i]); i++) {
    // Read the File objects in this FileList.
  }
}

Weitere Informationen hierzu finden Sie in Benutzerdefiniertes Drag-and-drop:

Weitere Ressourcen