Drag “n” Drop egéreseményekkel

A Drag’n’Drop nagyszerű interfész megoldás. Valaminek a felvétele és az elhúzása egyértelmű és egyszerű módja sok dolognak, a dokumentumok másolásától és áthelyezésétől (mint a fájlkezelőknél) a megrendelésig (elemek kosárba dobása).

A modern HTML-ben alapértelmezés szerint van egy szakasz a Húzás és a speciális eseményekről, például dragstart, dragend és így tovább.

Ezek az események lehetővé teszik számunkra a különféle drag’n’drop támogatását, például egy fájl áthúzását az OS fájlkezelőből és a böngésző ablakába való dobást. Ekkor a JavaScript hozzáférhet az ilyen fájlok tartalmához.

De a natív Drag Eseményeknek is vannak korlátai. Például nem akadályozhatjuk meg az elhúzást egy bizonyos területről. Nem tehetjük meg, hogy a húzás csak “vízszintes” vagy “függőleges”. És még sok más drag’n’drop feladat van, amelyeket nem lehet felhasználni. Ezenkívül a mobileszközök támogatása az ilyen eseményekhez nagyon gyenge.

Tehát itt megtudjuk, hogyan lehet megvalósítani a Drag’n’Drop egéreseményeket.

Drag’n’Drop algoritmus

Az alap Drag’n’Drop algoritmus a következőképpen néz ki:

  1. mousedown – előkészíti az elemet mozgatásra, ha szükséges (esetleg hozzon létre belőle egy klónt, adjon hozzá osztályt vagy bármi mást).
  2. Ezután mousemove tovább helyezheti a a következővel: position:absolute.
  3. mouseup – a drag’n befejezésével kapcsolatos összes művelet végrehajtása ‘drop.

Ezek az alapok. Később megtudhatjuk, hogyan lehet más funkciókat, például kiemelni az aktuális mögöttes elemeket, miközben áthúzzuk őket.

Itt van a labda húzásának megvalósítása:

Ha futtatjuk a kódot, valami furcsát észlelhetünk. A drag’n’drop elején a labda “elágazik”: elkezdjük húzni a “klónját”.

Íme egy példa a műveletben:

Próbálja meg húzni az egérrel az egeret, és ilyen viselkedés lesz látható.

Ez azért van, mert a böngésző saját drag’n’drop támogatással rendelkezik a képekhez és néhány más elem. Automatikusan fut, és ütközik a miénkkel.

Kikapcsolásához:

Most minden rendben lesz.

Műveletben:

Egy másik fontos szempont – mousemove -t a document -en követjük, nem pedig a ball -en. Első látásra úgy tűnhet, hogy az egér mindig a labda felett van, és rátehetjük az mousemove -t.

De mint emlékszünk, mousemove gyakran vált ki, de nem minden pixelre. Tehát gyors mozgás után a mutató ugrani tud a labdáról a dokumentum közepén (vagy akár az ablakon kívül).

Tehát hallgatnunk kell a document hogy elkapja.

Helyes pozícionálás

A fenti példákban a labdát mindig úgy mozgatjuk, hogy középpontja a mutató alatt legyen:

Nem rossz, de van mellékhatása. A drag’n’drop megindításához mousedown bárhol a labdán elhelyezhetjük. De ha “kiveszi” az éléből, akkor a labda hirtelen “ugrik”, hogy az egérmutató alatt középre kerüljön.

Jobb lenne, ha megtartanánk az elem kezdeti elmozdulását a mutatóhoz képest.

Ha például a labda szélénél fogva kezdünk el húzni, akkor a mutatónak az élen kell maradnia húzás közben.

Frissítsük algoritmusunkat:

A végső kód jobb elhelyezéssel:

Működésben (belül <iframe>) :

A különbség különösen akkor érzékelhető, ha a labdát annak jobb alsó sarkánál fogva húzzuk. Az előző példában a labda “ugrik” a mutató alá. Most folyékonyan követi a mutatót az aktuális helyzetből.

Potenciális esési célok (leejthetők)

Az előző példákban a labda csak “bárhová” dobják le, hogy maradjanak. A való életben általában az egyik elemet vesszük, és a másikra dobjuk. Például egy “fájlt” egy “mappába” vagy valami mást.

Absztrakt módon egy “húzható” elemet veszünk, és a “dobható” elemre dobjuk.

Mi tudnia kell:

  • hová esett az elem a Drag’n’Drop végén – a megfelelő művelet végrehajtásához,
  • és lehetőleg ismerje a áthúzódik, hogy kiemelje.

A megoldás egyfajta érdekes és csak egy kicsit trükkös, szóval itt térjünk ki rá.

Mi lehet az első ötlet? Valószínűleg a mouseover/mouseup kezelőket állítja be potenciális dobhatókra?

De ez nem működik.

A probléma az, hogy amíg mi húzáskor a húzható elem mindig a többi elem felett áll.Az egéresemények csak a legfelső elemen történnek, az alattuk levőkön nem.

Például az alábbiakban két <div> elem látható, piros a kék tetején az egyik (teljesen lefedi). A kék eseményen nem lehet eseményt elkapni, mert a piros van a tetején:

Ugyanez egy húzható elemmel. A labda mindig fent van a többi elem felett, ezért események történnek rajta. Bármilyen kezelőt állítunk is alacsonyabb elemekre, azok nem fognak működni.

Éppen ezért a gyakorlatban nem működik az az eredeti elképzelés, hogy a kezelőket potenciális dobhatókra helyezzük. Nem fognak futni.

Szóval, mit kell tenni?

Van egy módszer, amelynek neve: document.elementFromPoint(clientX, clientY). Visszaadja a legtöbb beágyazott elemet az adott ablak-relatív koordinátákon (vagy null, ha az adott koordináták nincsenek az ablakon).

Bármelyikben felhasználhatjuk egéresemény-kezelőink felismerik a mutató alatt a potenciálisan leejthetőt, így:

Felhívjuk figyelmét: el kell rejtenünk a labdát a (*) hívás előtt. Ellenkező esetben általában ezeken a koordinátákon van egy gömbünk, mivel ez a mutató alatti legfelső elem: elemBelow=ball. Tehát elrejtjük, és azonnal újra megjelenítjük.

Ezzel a kóddal bármikor ellenőrizhetjük, hogy melyik elem felett “repülünk” át. És kezeljük a dobást, amikor ez megtörténik. > onMouseMove kiterjesztett kódja az “eldobható” elemek megtalálásához:

Az alábbi példában a labda a futballkapu fölé húzva a cél kiemelésre kerül.

Mostantól megvan a jelenlegi “drop target”, amelyen átrepülünk, a currentDroppable változóban az egész folyamat során, és ezzel kiemelhetjük vagy egyéb dolgok.

Összegzés

Alapvető Drag’n’Drop algoritmust vettünk figyelembe.

A legfontosabb összetevők:

  1. Események folyamata: ball.mousedowndocument.mousemoveball.mouseup (ne felejtsd el lemondani a natívat ondragstart).
  2. A húzás kezdetén – emlékezzen a mutató kezdeti elmozdulására az elemhez képest: shiftX/shiftY és tartsa a húzás alatt.
  3. Az észrevehető elemeket észlelheti und tegye a mutatót a document.elementFromPoint használatával.

Sokat fektethetünk ezen az alapon.

  • On mouseup intellektuálisan véglegesíthetjük a cseppet: megváltoztathatjuk az adatokat, elemeket mozgathatunk.
  • Kiemelhetjük azokat az elemeket, amelyeken átrepülünk.
  • Mi korlátozhatja a húzást egy bizonyos terület vagy irány szerint.
  • Használhatjuk az események delegálását a mousedown/up számára. Egy nagy területű eseménykezelő, amely ellenőrzi a event.target elemeket, több száz elem kezelésével képes kezelni a Drag’n’Drop elemet.
  • És így tovább.

Vannak olyan keretrendszerek, amelyek építenek rá architektúrát: DragZone, Droppable, Draggable és más osztályok. Legtöbben a fent leírtakhoz hasonló dolgokat csinálnak, ezért most már könnyen érthetőnek kell lenniük. Vagy tekerje meg a sajátját, amint láthatja, hogy ez elég egyszerű, néha könnyebb, mint adaptálni egy harmadik féltől származó megoldást.

Write a Comment

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük