Przeciągnij „n” Upuść za pomocą zdarzeń myszy

Przeciągnij i upuść to świetne rozwiązanie interfejsu. Biorąc coś, przeciągając i upuszczając to jasny i prosty sposób na robienie wielu rzeczy, od kopiowania i przenoszenia dokumentów (jak w menadżerach plików) po zamawianie (upuszczanie elementów do koszyka).

We współczesnym HTML standardowo jest sekcja dotycząca przeciągania i upuszczania ze specjalnymi zdarzeniami, takimi jak dragstart, dragend i tak dalej.

Te zdarzenia umożliwiają nam obsługę specjalnych rodzajów przeciągania i upuszczania, takich jak przeciąganie pliku z menedżera plików systemu operacyjnego i upuszczanie go w oknie przeglądarki. Następnie JavaScript może uzyskać dostęp do zawartości takich plików.

Jednak natywne zdarzenia przeciągania również mają ograniczenia. Na przykład nie możemy zapobiec przeciągnięciu z określonego obszaru. Nie możemy też sprawić, by przeciąganie było tylko „poziome” lub „pionowe”. Jest też wiele innych zadań typu „przeciągnij i upuść”, których nie można wykonać za ich pomocą. Ponadto obsługa takich zdarzeń na urządzeniach mobilnych jest bardzo słaba.

Tutaj zobaczymy, jak zaimplementować Drag’n’Drop za pomocą zdarzeń myszy.

Algorytm Drag’n’Drop

Podstawowy algorytm Drag’n’Drop wygląda następująco:

  1. On mousedown – przygotuj element do przesunięcia, jeśli potrzebne (może utworzyć jego klon, dodać do niego klasę lub cokolwiek innego).
  2. Następnie w mousemove przenieś go, zmieniając left/top with position:absolute.
  3. On mouseup – wykonaj wszystkie czynności związane z zakończeniem przeciągania 'drop.

To są podstawy. Później zobaczymy, jak wykonać inne funkcje, takie jak podświetlanie bieżących podstawowych elementów podczas przeciągania po nich.

Oto implementacja przeciągania piłki:

Jeśli uruchomimy kod, możemy zauważyć coś dziwnego. Na początku przeciągania i upuszczania kulka „rozwidla się”: zaczynamy przeciągać jej „klon”.

Oto przykład w akcji:

Spróbuj przeciągnąć i upuść myszką, a zobaczysz takie zachowanie.

Dzieje się tak, ponieważ przeglądarka ma własną obsługę przeciągania i upuszczania obrazów i kilka innych elementów. Działa automatycznie i jest w konflikcie z naszym.

Aby go wyłączyć:

Teraz wszystko będzie dobrze.

W akcji:

Kolejny ważny aspekt – śledzimy mousemove na document, a nie ball. Na pierwszy rzut oka może się wydawać, że mysz jest zawsze nad piłką i możemy umieścić na niej mousemove.

Ale jak pamiętamy, mousemove uruchamia się często, ale nie dla każdego piksela. Więc po szybkim ruchu wskaźnik może wyskoczyć z kulki gdzieś pośrodku dokumentu (lub nawet poza oknem).

Powinniśmy więc posłuchać document aby ją złapać.

Prawidłowe ustawienie

W przykładach powyżej piłka jest zawsze przemieszczana tak, że jej środek znajduje się pod kursorem:

Nieźle, ale jest efekt uboczny. Aby zainicjować przeciąganie i upuszczanie, możemy mousedown w dowolnym miejscu na piłce. Ale jeśli „zdejmiemy” ją z krawędzi, to kulka nagle „wyskoczy” i wyśrodkuje się pod kursorem myszy.

Byłoby lepiej, gdybyśmy zachowali początkowe przesunięcie elementu względem wskaźnika.

Na przykład, jeśli zaczniemy przeciągać za krawędź kulki, wówczas wskaźnik powinien pozostać nad krawędzią podczas przeciągania.

Zaktualizujmy nasz algorytm:

Ostateczny kod z lepszym pozycjonowaniem:

W akcji (wewnątrz <iframe>) :

Różnica jest szczególnie zauważalna, jeśli przeciągniemy piłkę za jej prawy dolny róg. W poprzednim przykładzie piłka „podskakuje” pod kursorem. Teraz płynnie podąża za wskaźnikiem z bieżącej pozycji.

Potencjalne obiekty upuszczone (droppables)

W poprzednich przykładach piłka mogła zostać porzuconym „gdziekolwiek”, aby zostać. W prawdziwym życiu zwykle bierzemy jeden element i upuszczamy go na inny. Na przykład „plik” do „folderu” lub coś innego.

Mówiąc abstrakcyjnie, bierzemy element „do przeciągania” i upuszczamy go na element „do upuszczania”.

trzeba wiedzieć:

  • gdzie element został upuszczony na końcu Drag’n’Drop – aby wykonać odpowiednią akcję,
  • i, najlepiej, znać droppable my Przeciągamy się, aby to podkreślić.

Rozwiązanie jest dość interesujące i trochę skomplikowane, więc omówmy je tutaj.

Co może być pierwszy pomysł? Prawdopodobnie aby ustawić moduły obsługi mouseover/mouseup na potencjalnych elementach droppables?

Ale to nie działa.

Problem w tym, że skoro jesteśmy przeciągając, element, który można przeciągać, zawsze znajduje się nad innymi elementami.A zdarzenia myszy mają miejsce tylko w górnym elemencie, a nie pod nim.

Na przykład poniżej znajdują się dwa elementy <div>, czerwony jeden na niebieskim jeden (całkowicie zakrywa). Nie ma sposobu, aby złapać wydarzenie na niebieskim, ponieważ czerwony jest na górze:

To samo z elementem do przeciągania. Piłka jest zawsze na wierzchu nad innymi elementami, więc zdarzają się na niej wydarzenia. Bez względu na to, jakie programy obsługi ustawimy na niższych elementach, nie zadziałają.

Dlatego początkowy pomysł, aby umieścić moduły obsługi na potencjalnych elementach, nie sprawdza się w praktyce. Nie będą działać.

Więc co zrobić?

Jest metoda o nazwie document.elementFromPoint(clientX, clientY). Zwraca najbardziej zagnieżdżony element o podanych współrzędnych względem okna (lub null jeśli podane współrzędne są poza oknem).

Możemy go użyć w każdym z nasze programy obsługi zdarzeń myszy, aby wykryć potencjalne elementy, które można umieścić pod wskaźnikiem, w ten sposób:

Uwaga: musimy ukryć kulkę przed wywołaniem (*). W przeciwnym razie zwykle będziemy mieć piłkę na tych współrzędnych, ponieważ jest to górny element pod wskaźnikiem: elemBelow=ball. Więc ukrywamy to i od razu pokazujemy ponownie.

Możemy użyć tego kodu, aby sprawdzić, nad jakim elementem „przelatujemy” w dowolnym momencie. I obsłużyć spadek, gdy to nastąpi.

Rozszerzony kod onMouseMove umożliwiający znalezienie elementów „do upuszczenia”:

W poniższym przykładzie, gdy piłka jest przeciągnięta nad bramkę piłkarską, cel jest podświetlony.

Teraz mamy aktualny „cel upuszczenia”, nad którym lecimy, w zmiennej currentDroppable podczas całego procesu i możemy go użyć do podświetlenia lub inne rzeczy.

Podsumowanie

Rozważaliśmy podstawowy algorytm Drag’n’Drop.

Kluczowe komponenty:

  1. Przepływ zdarzeń: ball.mousedowndocument.mousemoveball.mouseup (nie zapomnij anulować natywnych ondragstart).
  2. Na początku przeciągania – zapamiętaj początkowe przesunięcie wskaźnika względem elementu: shiftX/shiftY i zachowaj go podczas przeciągania.
  3. Wykrywaj elementy, które można upuszczać er wskaźnik za pomocą document.elementFromPoint.

Na tym fundamencie możemy wiele położyć.

  • Na mouseup możemy intelektualnie sfinalizować zrzut: zmienić dane, przesuwać elementy.
  • Możemy zaznaczyć elementy, nad którymi latamy.
  • Możemy może ograniczyć przeciąganie o określony obszar lub kierunek.
  • Możemy użyć delegowania zdarzeń dla mousedown/up. Moduł obsługi zdarzeń o dużej powierzchni, który sprawdza event.target, może zarządzać funkcją Drag’n’Drop dla setek elementów.
  • I tak dalej.

Istnieją frameworki, które tworzą na jego podstawie architekturę: DragZone, Droppable, Draggable i inne zajęcia. Większość z nich robi podobne rzeczy do opisanych powyżej, więc teraz powinno być łatwo je zrozumieć. Lub stwórz własne, ponieważ widzisz, że jest to dość łatwe, czasem łatwiejsze niż dostosowanie rozwiązania innej firmy.

Write a Comment

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *