Ten post zawiera podstawowe informacje o przeciąganiu i upuszczaniu.
Tworzenie przeciąganych treści
W większości przeglądarek wybrany tekst, obrazy i linki można domyślnie przeciągać. Jeśli na przykład przeciągniesz link na stronie internetowej, zobaczysz małe pole z tytułem i adresem URL, które można upuścić na pasku adresu lub na pulpicie, aby utworzyć skrót lub przejść do linku. Aby umożliwić przeciąganie innych typów treści, musisz użyć interfejsów API przeciągania i upuszczania w HTML5.
Aby obiekt można było przeciągać, ustaw dla niego parametr draggable=true
. Dozwolone jest przeciąganie niemal wszystkiego, w tym obrazów, plików, linków, plików i wszelkich znaczników na stronie.
W tym przykładzie tworzymy interfejs do przestawiania kolumn rozmieszczonych za pomocą CSS Grid. Podstawowe znaczniki kolumn wyglądają tak, a atrybut draggable
każdej kolumny ma wartość 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 pudełka. Jedynym elementem CSS powiązanym z funkcją przeciągania jest właściwość cursor: move
. Pozostała część kodu kontroluje układ i styl elementów kontenera oraz pola.
.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ć zachowanie, musisz użyć interfejsu JavaScript API.
Nasłuchiwanie zdarzeń przeciągania
Aby monitorować proces przeciągania, możesz nasłuchiwać tych zdarzeń:
Aby obsłużyć przeciąganie, potrzebujesz jakiegoś elementu źródłowego (gdzie przeciąganie się zaczyna), danych (element przeciągany) i docelowego miejsca (obszar, w którym można upuścić element). Źródło może być dowolnym elementem. Docelowy obszar zrzutu to obszar zrzutu lub zestaw obszarów zrzutu, który akceptuje dane, które użytkownik próbuje zrzucić. Nie wszystkie elementy mogą być celami. Na przykład nie możesz ustawić jako celu elementu typu obraz.
Rozpoczynanie i kończenie sekwencji przeciągania
Po zdefiniowaniu atrybutów draggable="true"
w treści dołącz do niej element obsługi zdarzenia dragstart
, aby rozpocząć sekwencję przeciągania w przypadku każdej kolumny.
Ten kod ustawia przezroczystość kolumny na 40%, gdy użytkownik zaczyna ją przeciągać, i przywraca ją na 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);
});
Efekt można zobaczyć w tym filmie demonstracyjnym Glitch. Przeciągnij element, aby zmienić jego przezroczystość. Źródłowy element ma zdarzenie dragstart
, więc ustawienie wartości this.style.opacity
na 40% daje użytkownikowi wizualną informację, że ten element jest aktualnie zaznaczany. Gdy upuścisz element, element źródłowy wróci do 100% przezroczystości, nawet jeśli nie zdefiniujesz jeszcze zachowania po upuszczeniu.
Dodaj więcej wskazówek wizualnych
Aby pomóc użytkownikowi zrozumieć, jak korzystać z interfejsu, użyj przełączników zdarzeń dragenter
, dragover
i dragleave
. W tym przykładzie kolumny są nie tylko przeciągane, ale też miejscami docelowymi. Aby ułatwić użytkownikowi zrozumienie tego, ustaw kreskę obramowania, gdy użytkownik przytrzymuje przeciągnięty element nad kolumną. W CSS możesz na przykład utworzyć klasę over
dla elementów, które są elementami docelowymi:
.box.over {
border: 3px dotted #666;
}
Następnie w kodzie JavaScript skonfiguruj moduły obsługi zdarzeń, dodaj klasę over
po przeciągnięciu kolumny i usuń ją, gdy przeciągnięty element zniknie. W module obsługi dragend
usuwamy też 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);
});
});
W tym kodzie warto uwzględnić kilka kwestii:
Działanie domyślne dla zdarzenia
dragover
to ustawienie właściwościdataTransfer.dropEffect
na"none"
. WłaściwośćdropEffect
omówimy dalej na tej stronie. Na razie wystarczy wiedzieć, że uniemożliwia ono wywołanie zdarzeniadrop
. Aby zastąpić to działanie, zadzwoń pod numere.preventDefault()
. Inną sprawdzoną metodą jest zwrócenie poleceniafalse
w tym samym module obsługi.Obsługa zdarzenia
dragenter
służy do przełączania klasyover
zamiast klasydragover
. Jeśli używasz metodydragover
, zdarzenie uruchamia się wielokrotnie, gdy użytkownik przytrzymuje przeciągany element nad kolumną, co powoduje cykliczne przełączanie klasy CSS. Oznacza to, że przeglądarka wykonuje wiele niepotrzebnych zadań związanych z renderowaniem, co może negatywnie wpływać na wygodę użytkownika. Zdecydowanie zalecamy zminimalizowanie liczby ponownych wywołań. Jeśli musisz używać funkcjidragover
, rozważ ograniczenie jej działania lub stosowanie debouncowania.
Dokończ dodawanie
Aby przetworzyć usunięcie, dodaj detektor zdarzenia drop
. W obiekcie drop
musisz zapobiec domyślnemu działaniu przeglądarki w przypadku przerwania, które zwykle powoduje irytujące przekierowanie. Aby to zrobić, 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 obok innych modułów 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. Aby to zrobić, użyj obiektu DataTransfer
.
Właściwość dataTransfer
przechowuje dane wysłane w wyniku przeciągania. Funkcja dataTransfer
jest ustawiana w zdarzeniu dragstart
i odczytywana lub obsługiwana w zdarzeniu utraty. Wywołanie e.dataTransfer.setData(mimeType, dataPayload)
pozwala ustawić typ MIME i ładunek danych obiektu.
W tym przykładzie umożliwimy użytkownikom zmianę kolejności kolumn. Aby to zrobić, musisz najpierw zapisać kod HTML elementu źródłowego po rozpoczęciu przeciągania:
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 spadek kolumny, ustawiając kod HTML kolumny źródłowej na kod HTML kolumny docelowej, w której zostały przekazane dane. Obejmuje to sprawdzenie, czy użytkownik nie przeciąga elementów z powrotem do tej samej kolumny, z której je przeciągał.
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 użyć przeglądarki na komputerze. Interfejs API przeciągania i upuszczania nie jest obsługiwany na urządzeniach mobilnych. Przeciągnij kolumnę A i upuść ją na kolumnę B. Zwróć uwagę, jak zmieniają one miejsca:
Więcej właściwości przeciągania
Obiekt dataTransfer
udostępnia właściwości, aby zapewnić użytkownikowi wizualną informację zwrotną podczas przeciągania i kontrolować, jak poszczególne elementy docelowe upuszczania reagują na określony typ danych.
dataTransfer.effectAllowed
ogranicza „rodzaj przeciągania”, który użytkownik może wykonać na elemencie. Jest on używany w modelu przetwarzania metodą przeciągania i upuszczania do inicjowania zmiennejdropEffect
podczas zdarzeńdragenter
idragover
. Właściwość może mieć te wartości:none
,copy
,copyLink
,copyMove
,link
,linkMove
,move
,all
iuninitialized
.dataTransfer.dropEffect
kontroluje informacje zwrotne otrzymywane przez użytkownika podczas zdarzeńdragenter
idragover
. Gdy użytkownik najedzie kursorem na element docelowy, kursor przeglądarki wskaże, jakiego typu operacja zostanie wykonana, np. kopiowanie lub przenoszenie. Efekt może przyjmować jedną z tych wartości:none
,copy
,link
,move
.e.dataTransfer.setDragImage(imgElement, x, y)
oznacza, że zamiast domyślnej „przejrzystej” ikony w przeglądarce możesz ustawić ikonę do 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. Może się to zdarzyć w interfejsie, który prosi użytkownika o przesunięcie elementów. W niektórych przypadkach źródło i docelowy element mogą być różnych typów, np. w interfejsie, w którym użytkownik musi wybrać jedno zdjęcie jako główne zdjęcie produktu, przeciągając wybrane zdjęcie do celu.
Przeciąganie i upuszczanie jest często używane, aby umożliwić użytkownikom przeciąganie elementów z pulpitu do aplikacji. Główna różnica dotyczy elementu drop
. Zamiast dostępu do plików za pomocą parametru dataTransfer.getData()
dane te znajdują się we właściwości 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 sekcji Niestandardowe przeciąganie i upuszczanie.
Więcej zasobów
- Specyfikacja przeciągania i upuszczania
- Interfejs API MND HTML typu przeciągnij i upuść
- Jak utworzyć narzędzie do przesyłania plików metodą „przeciągnij i upuść” za pomocą kodu JavaScript wanilii
- Tworzenie gry parkingowej za pomocą interfejsu HTML Drag and Drop API
- Jak korzystać z interfejsu API HTML typu „przeciągnij i upuść” w React