Interfejs API przeciągania i upuszczania HTML5

Ten post zawiera podstawowe informacje o przeciąganiu i upuszczaniu.

Utwórz elementy, które można przeciągać

W większości przeglądarek domyślnie zaznaczone fragmenty tekstu, obrazy i linki można przeciągać. Na przykład jeśli przeciągniesz link na stronie internetowej, zobaczysz małe pole z tytuł i adres URL, które można upuścić na pasku adresu lub na pulpicie, aby utworzyć lub przejdź do linku. Aby przeciągać treści innego typu, muszą używać interfejsów API typu „przeciągnij i upuść” HTML5.

Aby obiekt można było przeciągać, ustaw dla niego atrybut draggable=true. Prawie elementy można przeciągać, w tym obrazy, pliki, linki, pliki na swojej stronie.

Poniższy przykład pokazuje interfejs do zmiany kolejności kolumn układ z siatką CSS. Podstawowe znaczniki kolumn wyglądają tak: atrybut draggable dla każdej kolumny ustawiony na true:

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

Oto kod CSS elementów kontenera i ramki. Jedyna usługa porównywania cen powiązana z funkcja przeciągania to cursor: move usłudze. Pozostała część kodu określa układ i styl kontenera i ramki.

.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;
}

Na tym etapie możesz przeciągnąć elementy, ale nic więcej się nie wydarzy. Aby dodać musisz użyć interfejsu JavaScript API.

Nasłuchuj zdarzeń przeciągania

Aby monitorować proces przeciągania, możesz nasłuchiwać dowolnych z tych zdarzeń:

Aby przeciągać elementy, musisz mieć jakiś element źródłowy (gdzie przeciąga się ładunek danych (przeciągany obiekt) i cel (obszar do złapania spadku). Elementem źródłowym może być niemal dowolny element. to strefa lub zbiór stref, które akceptują dane użytkownika i chce się upuścić. Nie wszystkie elementy mogą być celami. Cel nie może na przykład: nie musi być obrazem.

Rozpoczynanie i kończenie sekwencji przeciągania

Po zdefiniowaniu atrybutów draggable="true" w treści załącz plik dragstart modułu obsługi zdarzeń, aby rozpocząć sekwencję przeciągania dla każdej kolumny.

Ten kod ustawia przezroczystość kolumny na 40%, gdy użytkownik zaczyna ją przeciągać. a potem wróć do 100% po zakończeniu zdarzenia przeciągania.

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);
});

Wynik można zobaczyć w tej demonstracji błędu. Przeciągnij element, a następnie zmiany przezroczystości. Element źródłowy ma zdarzenie dragstart, więc ustawienie Od this.style.opacity do 40% użytkownik widzi wizualną informację, że dany element jest aktualnie przenoszone zaznaczenie. Po upuszczenie elementu powraca do 100% przezroczystości, nawet jeśli nie zdefiniowano jeszcze zachowania spadku rozdzielczości.

Dodaj więcej wskazówek wizualnych

Aby pomóc użytkownikowi zrozumieć, jak korzystać z Twojego interfejsu, użyj Moduły obsługi zdarzeń dragenter, dragover i dragleave. W tym przykładzie para klucz-wartość kolumny to elementy docelowe, które można przeciągać. Pomóż użytkownikowi w aby to zrozumieć, ustaw obramowanie przerywane, gdy przytrzymuje on przeciągnięty element . W CSS możesz na przykład utworzyć klasę over dla: które są celami pomijanymi:

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

Następnie skonfiguruj w JavaScripcie moduły obsługi zdarzeń i dodaj klasę over, gdy kolumna zostanie przeciągnięta i usuwana, gdy przeciągany element opuści dany element. W funkcji dragend pamiętaj, aby usunąć również klasy na końcu przeciągania.

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);
  });
});

Warto wspomnieć o kilku kwestiach:

  • Działanie domyślne, dla zdarzenia dragover należy ustawić właściwość dataTransfer.dropEffect na "none". Właściwość dropEffect została opisana w dalszej części tej strony. Na razie, pamiętaj, że uniemożliwia to wywołanie zdarzenia drop. Aby zastąpić to ustawienie zachowanie, wywołaj e.preventDefault(). Kolejną sprawdzoną metodą jest powrót false w tym samym module obsługi.

  • Moduł obsługi zdarzeń dragenter służy do przełączania klasy over zamiast dragover Jeśli użyjesz metody dragover, zdarzenie będzie uruchamiane wielokrotnie, gdy użytkownik przytrzymuje przeciągany element nad kolumną, powodując przełączenie klasy CSS kilka razy. Sprawia to, że przeglądarka wykonuje wiele niepotrzebnych zadań związanych z renderowaniem, co może wpływać na wygodę użytkowników. Zdecydowanie zalecamy zminimalizowanie danych. Jeśli musisz użyć dragover, rozważ ograniczania lub wyciszania detektora zdarzeń.

Dokończ dodawanie

Aby przetworzyć usunięcie, dodaj detektor zdarzenia drop. W: drop musisz zapobiec domyślnemu działaniu przeglądarki w przypadku utraty wyników, to zwykle jakieś irytujące przekierowanie. W tym celu zadzwoń pod numer e.stopPropagation().

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

Pamiętaj, aby zarejestrować nowy moduł obsługi wraz z innymi modułami obsługi:

  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);
  });

Jeśli na tym etapie uruchomisz kod, element nie zostanie umieszczony w nowej lokalizacji. Do aby to osiągnąć, użyj DataTransfer obiektu.

Właściwość dataTransfer przechowuje dane wysłane w wyniku przeciągania. dataTransfer jest ustawiana w zdarzeniu dragstart i odczytywana lub obsługiwana w zdarzeniu utraty. Łączę e.dataTransfer.setData(mimeType, dataPayload) umożliwia ustawienie MIME obiektu typ i ładunek danych.

W tym przykładzie umożliwimy użytkownikom zmianę kolejności kolumn. Aby to zrobić, musisz najpierw zapisać kod HTML elementu źródłowego, gdy przeciąganie rozpoczyna się:

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

  dragSrcEl = this;

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

W zdarzeniu drop przetwarzasz upuszczenie kolumny, ustawiając wartości w kolumnie źródłowej kod HTML do kodu HTML kolumny docelowej, w której zostały umieszczone dane. Ten obejmuje sprawdzenie, czy użytkownik nie wraca do tej samej kolumny, przeciągnięty z dysku.

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

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

  return false;
}

Wynik sprawdzisz w tej prezentacji. Aby to zrobić, musisz mieć za pomocą przeglądarki na komputerze. Interfejs API „przeciągnij i upuść” nie jest obsługiwany na urządzeniach mobilnych. Przeciągnij zwolnij kolumnę A u góry kolumny B i zwróć uwagę, jak zmieniają się miejsca:

Więcej właściwości przeciągania

Obiekt dataTransfer udostępnia właściwości, aby przekazać wizualną informację zwrotną użytkownika podczas przeciągania i kontrolować, jak każdy punkt upuszczania reaguje na określonego typu danych.

  • dataTransfer.effectAllowed ogranicza „typ przeciągania” co użytkownik może wykonać na elemencie. To jest używane w modelu przetwarzania metodą „przeciągnij i upuść”, aby zainicjować interfejs dropEffect podczas wydarzenia dragenter i dragover. Właściwość może mieć te wartości: none, copy, copyLink, copyMove, link, linkMove, move, all i uninitialized.
  • dataTransfer.dropEffect kontroluje opinię otrzymywaną przez użytkownika podczas dragenter i dragover zdarzeń. Gdy użytkownik najeżdża kursorem na element docelowy, kursor wskazuje typ operacji, która zostanie wykonana, np. kopiowanie lub ruch. Efekt może mieć jedną z tych wartości: none, copy, link, move.
  • e.dataTransfer.setDragImage(imgElement, x, y) oznacza, że zamiast domyślnego „ducha” przeglądarki opinii, ustawić ikonę przeciągania.

Prześlij plik

W tym prostym przykładzie kolumna pełni funkcję zarówno źródła, jak i elementu docelowego przeciągania. Ten może pojawić się w interfejsie, w którym poprosimy użytkownika o zmianę kolejności elementów. Czasami element docelowy przeciągania i źródło mogą być różnymi typami elementów, jak w interfejsie w którym użytkownik musi wybrać jedno zdjęcie jako główne produktu, przez przeciąganie wybranego obrazu na miejsce docelowe.

Funkcja „Przeciągnij i upuść” jest często używana, aby umożliwić użytkownikom przeciąganie elementów z komputera między wiele instancji aplikacji. Główna różnica występuje w module obsługi drop. Zamiast użycia dataTransfer.getData(), aby uzyskać dostęp do plików, ich dane znajdują się w pliku Właściwość dataTransfer.files:

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.
  }
}

Więcej informacji na ten temat znajdziesz w Niestandardowe przeciąganie i upuszczanie

Więcej zasobów