Přetahování myší „myší“

Drag’n’Drop je skvělé řešení rozhraní. Vezmeme-li něco a přetáhneme, je to jasný a jednoduchý způsob, jak dělat mnoho věcí, od kopírování a přesouvání dokumentů (jako ve správcích souborů) až po objednávání (vkládání položek do košíku).

V moderním HTML standardně existuje sekce o Drag and Drop se speciálními událostmi, jako je dragstart, dragend atd.

Tyto události nám umožňují podporovat speciální druhy drag’n’drop, jako je manipulace s přetažením souboru ze správce souborů OS a jeho přetažením do okna prohlížeče. Potom může JavaScript přistupovat k obsahu těchto souborů.

Ale nativní události přetažení mají také omezení. Nemůžeme například zabránit přetažení z určité oblasti. Také nemůžeme provést tažení pouze „vodorovně“ nebo „svisle“. A existuje mnoho dalších úkolů drag’n’drop, které pomocí nich nelze provést. Podpora mobilních zařízení pro tyto události je také velmi slabá.

Takže zde uvidíme, jak implementovat Drag’n’Drop pomocí událostí myši.

Algoritmus Drag’n’Drop

Základní algoritmus Drag’n’Drop vypadá takto:

  1. Zapnuto mousedown – připravit prvek na přesun, pokud potřeba (možná vytvořit jeho klon, přidat do něj třídu nebo cokoli jiného).
  2. Poté jej mousemove přesuňte změnou left/top s position:absolute.
  3. Zapnuto mouseup – provádět všechny akce související s dokončením drag’n ‚drop.

Toto jsou základní informace. Později uvidíme, jak na další funkce, jako je zvýraznění aktuálních základních prvků, když je přetahujeme.

Zde je implementace přetažení koule:

Pokud spustíme kód, můžeme si všimnout něčeho zvláštního. Na začátku drag’n’dropu se koule „rozvětvuje“: začneme přetahovat její „klon“.

Zde je příklad akce:

Zkuste přetáhnout myší myší a uvidíte takové chování.

Je to proto, že prohlížeč má vlastní podporu drag’n’drop pro obrázky a některé další prvky. Spouští se automaticky a je v konfliktu s naším.

Chcete-li jej deaktivovat:

Nyní bude vše v pořádku.

V akci:

Další důležitý aspekt – sledujeme mousemove na document, ne na ball. Na první pohled se může zdát, že myš je vždy nad míčem a můžeme na ni umístit mousemove.

Ale jak si pamatujeme, mousemove se spouští často, ale ne pro každý pixel. Takže po rychlém pohybu může ukazatel vyskočit z koule někde uprostřed dokumentu (nebo dokonce i mimo okno).

Takže bychom měli poslouchat document chytit to.

Správné umístění

Ve výše uvedených příkladech se míč vždy pohybuje tak, aby jeho střed byl pod ukazatelem:

To není špatné, ale má to vedlejší efekt. Abychom zahájili drag’n’drop, můžeme mousedown kdekoli na míči. Pokud to ale „vezmeme“ z jeho okraje, pak koule najednou „skočí“, aby se vystředila pod ukazatel myši.

Bylo by lepší, kdybychom ponechali počáteční posun prvku vzhledem k ukazateli.

Pokud například začneme táhnout za okraj koule, ukazatel by měl během tažení zůstat přes okraj.

Aktualizujme náš algoritmus:

Konečný kód s lepším umístěním:

V akci (uvnitř <iframe>) :

Rozdíl je zvláště patrný, když míč přetáhneme za pravý dolní roh. V předchozím příkladu míč „vyskočí“ pod ukazatel. Nyní plynule sleduje ukazatel z aktuální polohy.

Potenciální cílové body (droppables)

V předchozích příkladech mohl míč být upuštěn „kdekoli“ a zůstat. V reálném životě obvykle vezmeme jeden prvek a hodíme ho na jiný. Například „soubor“ do „složky“ nebo něco jiného.

Když mluvíme abstraktně, vezmeme „přetahovatelný“ prvek a umístíme jej na „droppable“ prvek.

potřebujete vědět:

  • kde byl prvek vypuštěn na konci Drag’n’Drop – provést odpovídající akci,
  • a pokud možno znáte droppable přetahujeme se, abychom ho zvýraznili.

Řešení je trochu zajímavé a jen trochu ošidné, pojďme ho tedy popsat zde.

Co může být první nápad? Pravděpodobně nastavíme mouseover/mouseup manipulátory na potenciální droppable?

Ale to nefunguje.

Problém je v tom, že když jsme přetažením je přetahovatelný prvek vždy nad ostatními prvky.Události myši se dějí pouze na horním prvku, nikoli na těch pod ním.

Níže jsou například dva prvky <div>, červený nahoře na modrém jeden (zcela kryje). Neexistuje způsob, jak zachytit událost na modré, protože červená je nahoře:

Totéž s přetahovatelným prvkem. Míč je vždy nahoře nad ostatními prvky, takže na něm dochází k událostem. Bez ohledu na to, jaké obslužné rutiny nastavíme na nižší prvky, nebudou fungovat.

Proto prvotní myšlenka umístit obslužné rutiny na potenciální droppable v praxi nefunguje. Nebudou běžet.

Takže, co dělat?

Existuje metoda zvaná document.elementFromPoint(clientX, clientY). Vrátí nejvíce vnořený prvek na daných souřadnicích relativních k oknu (nebo null, pokud jsou dané souřadnice mimo okno).

Můžeme jej použít v kterékoli z naše obslužné rutiny událostí myši, aby detekovaly potenciální droppable pod ukazatelem, například takto:

Poznámka: před voláním (*) musíme míč skrýt. Jinak obvykle budeme mít na těchto souřadnicích kouli, protože jde o horní prvek pod ukazatelem: elemBelow=ball. Takže to skryjeme a okamžitě znovu zobrazíme.

Pomocí tohoto kódu můžeme kdykoli zkontrolovat, nad kterým prvkem „letíme“. A zvládnout pokles, když k tomu dojde.

Rozšířený kód onMouseMove k vyhledání prvků „droppable“:

V níže uvedeném příkladu, když je míč přetažen přes fotbalovou branku, je branka zvýrazněna.

Nyní máme v proměnné currentDroppable během celého procesu aktuální „cílový cíl“, který letíme, a můžeme jej použít ke zvýraznění nebo jakékoli jiné věci.

Shrnutí

Zvažovali jsme základní algoritmus Drag’n’Drop.

Klíčové komponenty:

  1. Tok událostí: ball.mousedowndocument.mousemoveball.mouseup (nezapomeňte zrušit nativní ondragstart).
  2. Na začátku přetažení – nezapomeňte na počáteční posun ukazatele vzhledem k prvku: shiftX/shiftY a ponechat to během přetahování.
  3. Zjistit droppable prvky und e ukazatel pomocí document.elementFromPoint.

Na tomto základě můžeme hodně pokládat.

  • Na mouseup můžeme intelektuálně dokončit pokles: měnit data, přesouvat prvky.
  • Můžeme zvýraznit prvky, nad kterými letíme.
  • My může omezit přetahování o určitou oblast nebo směr.
  • Pro mousedown/up můžeme použít delegování událostí. Obslužný program událostí pro velkou oblast, který kontroluje event.target, může spravovat Drag’n’Drop pro stovky prvků.
  • A tak dále.

Existují rámce, které nad ní staví architekturu: DragZone, Droppable, Draggable a další třídy. Většina z nich dělá podobné věci, jaké jsou popsány výše, takže by jim nyní mělo být snadné porozumět. Nebo si vytvořte vlastní, jak vidíte, že je to dost snadné, někdy jednodušší než přizpůsobení řešení třetí strany.

Write a Comment

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *