Why should you use a drag-and-drop Android app maker?

HTML5 Drag & Drop: Komplet Guide til Mobilen

21/01/2022

Rating: 4.99 (4429 votes)

I en verden, hvor intuitive brugerflader er afgørende for succesfulde digitale oplevelser, står træk-og-slip-funktionalitet som en hjørnesten i moderne webdesign. Denne interaktion, der er velkendt fra desktop-miljøer, tillader brugere at manipulere elementer på en hjemmeside med en enkel bevægelse – at trække et element fra ét sted og slippe det et andet. HTML5 introducerede et indbygget Drag & Drop API, der lovede at gøre denne funktionalitet universelt tilgængelig. Men som med mange webstandarder har vejen til ægte cross-browser og cross-device kompatibilitet været brolagt med udfordringer, især når det kommer til mobile enheder. Denne artikel dykker ned i HTML5 Drag & Drop API'et, dets understøttelse på tværs af platforme, og hvordan du kan sikre en problemfri oplevelse, selv på de mest udfordrende mobilbrowsere.

Does HTML 5 support drag & drop?
The HTML 5 drag'n'drop API allows you to implement drag'n'drop on most desktop browsers and some mobile browsers. Unfortunately, you'll notice most mobile browsers don't support it, so no iPad (or Nexus) action for you! Chrome>=96 on Android>=7 and Safari on iOS/iPadOS>=15 are reported to support drag and drop natively!

Uanset om du udvikler en kompleks webapplikation, der kræver filoverførsler, sortering af lister, eller blot ønsker at forbedre brugervenligheden, er forståelsen af Drag & Drop API'et og dets faldgruber essentiel. Vi vil udforske, hvornår indbygget understøttelse er tilstrækkelig, og hvornår et polyfill bliver din bedste ven, for at opnå den ønskede kompatibilitet og brugervenlighed for alle dine brugere.

Indholdsfortegnelse

Hvad er HTML5 Drag & Drop API'et?

HTML5 Drag & Drop API'et er et sæt JavaScript-grænseflader, der gør det muligt for webudviklere at implementere træk-og-slip-funktionalitet direkte i webbrowsere. Dette API definerer en række begivenheder, der udløses under en træk-og-slip-operation:

  • dragstart: Udløses, når brugeren begynder at trække et element. Her specificeres de data, der skal overføres.
  • drag: Udløses gentagne gange under trækoperationen.
  • dragenter: Udløses, når det trukne element kommer ind over et gyldigt dropzone-element.
  • dragover: Udløses gentagne gange, mens det trukne element er over et gyldigt dropzone-element. Dette er ofte det sted, hvor du forhindrer standardhandlingen for at tillade et drop.
  • dragleave: Udløses, når det trukne element forlader et gyldigt dropzone-element.
  • drop: Udløses, når det trukne element slippes over et gyldigt dropzone-element. Her kan de overførte data læses og behandles.
  • dragend: Udløses, når trækoperationen afsluttes, uanset om elementet blev sluppet eller ej.

Kernen i API'et er DataTransfer-objektet, som bruges til at holde de data, der trækkes under operationen. Dette objekt tillader overførsel af forskellige datatyper (f.eks. tekst, URL'er, filer) og håndtering af træk-effekter (f.eks. kopiering, flytning, linkning).

Understøttelse på Desktop og Mobilbrowsere

Historisk set har HTML5 Drag & Drop API'et haft en solid understøttelse på desktop-browsere. Chrome, Firefox, Safari, Opera, Brave, Internet Explorer 11 og Edge understøtter alle den indbyggede funktionalitet uden de store problemer. Dog er der, som vi vil se, stadig subtile forskelle i implementeringen, der kan kræve særlig opmærksomhed for at sikre ensartet adfærd.

Den virkelige udfordring har dog altid ligget i mobile browsere. I mange år var træk-og-slip-funktionalitet praktisk talt ikke-eksisterende på touch-baserede enheder som smartphones og tablets. Dette skyldtes, at API'et primært var designet til musebaserede interaktioner og ikke naturligt oversatte til touch-begivenheder (som touchstart, touchmove, touchend).

Heldigvis er landskabet begyndt at ændre sig. Moderne mobile browsere har forbedret deres understøttelse betydeligt:

  • Safari på iOS/iPadOS: Fra version 15 og opefter rapporteres Safari at understøtte træk-og-slip indbygget. Dette er en stor forbedring og betyder, at mange nyere Apple-enheder nu kan håndtere træk-og-slip uden et polyfill.
  • Chrome på Android: Fra version 96 og opefter på Android 7 og nyere rapporteres Chrome også at understøtte træk-og-slip indbygget.

Selvom den indbyggede understøttelse vokser, er det vigtigt at huske, at mange brugere stadig benytter ældre enheder eller browserversioner, hvor denne funktionalitet ikke er tilgængelig. Desuden kan der være specifikke scenarier eller brugerbaser, hvor et polyfill stadig er nødvendigt for at sikre fuld dækning. Det er altid tilrådeligt at konsultere ressourcer som caniuse.com og grundigt teste din implementering på tværs af de enheder og browsere, dine brugere anvender.

Oversigt over Browserkompatibilitet

Denne tabel giver et hurtigt overblik over den generelle understøttelse:

BrowserUnderstøttelseKendte Problemer
Chrome (Desktop)IndbyggetIngen kendte problemer.
Firefox (Desktop)IndbyggetIngen kendte problemer.
Safari (Desktop)IndbyggetIngen kendte problemer.
Opera (Desktop)IndbyggetSamme som Chrome.
Brave (Desktop)IndbyggetSamme som Chrome.
Internet Explorer 11IndbyggetIngen kendte problemer.
EdgeIndbyggetIngen kendte problemer.
Mobil Safari (< iOS 10)PolyfillIngen kendte problemer.
Mobil Safari (>= iOS 10)PolyfillKræver passive: false for touchmove.
Mobil Safari (>= iOS 15)Indbygget & PolyfillKan sameksistere med polyfill.
Chrome på iOSPolyfillSamme som Mobil Safari (samme motor).
Chrome på Android (< 96)PolyfillIngen kendte problemer.
Chrome på Android (>= 96)Indbygget & PolyfillUnder undersøgelse for indbygget adfærd.
Firefox på AndroidPolyfillIngen kendte problemer.

Det er vigtigt at bemærke, at Chrome på touch-enheder (f.eks. Microsoft Surface) og Firefox med aktiverede touch-begivenheder kan have særlige adfærd, hvor polyfills stadig kan være relevante, selvom desktop-versionerne normalt understøtter det indbygget.

Hvorfor et Polyfill er Nødvendigt

På trods af den forbedrede indbyggede understøttelse er der stadig mange situationer, hvor et polyfill er en uundværlig del af din værktøjskasse for at sikre bred kompatibilitet. Et polyfill er et stykke kode, der leverer funktionalitet, som ikke er indbygget i en given browser, ved at simulere den ved hjælp af anden tilgængelig teknologi.

For HTML5 Drag & Drop på mobile enheder fungerer polyfill'et mobile-drag-drop ved at fange touch-begivenheder (touchstart, touchmove, touchend) og oversætte dem til de tilsvarende standard Drag & Drop-begivenheder (dragstart, dragover, drop osv.). Dette betyder, at du ofte kan bruge din eksisterende HTML5 Drag & Drop-kode, og polyfill'et vil 'bare virke' på enheder, der ellers ikke ville understøtte det.

Nødvendigheden af et polyfill opstår fra:

  • Ældre enheder og browsere: Ikke alle brugere opgraderer deres software regelmæssigt.
  • Konsistent brugeroplevelse: Selvom en browser har indbygget understøttelse, kan adfærden variere. Et polyfill kan hjælpe med at standardisere oplevelsen.
  • Specifikke mobilbrowsere: Nogle nichebrowsere eller WebView-komponenter i apps har muligvis ikke fuld understøttelse.

Sådan Bruger du mobile-drag-drop Polyfill

Implementering af mobile-drag-drop polyfill'et er relativt ligetil. Det integreres problemfrit med eksisterende HTML5 Drag & Drop-kode.

Installation

Du kan installere pakken via populære pakkehåndteringsværktøjer:

  • npm:
    npm install mobile-drag-drop --save
  • jspm:
    jspm install npm:mobile-drag-drop

Inkludering i Dit Projekt

Afhængigt af dit projekt setup kan du inkludere polyfill'et på flere måder:

  • Globalt (via script-tags):
    <link rel="stylesheet" href="libs/mobile-drag-drop/release/default.css"><script src="libs/mobile-drag-drop/release/index.min.js"></script><!-- Valgfri import af scroll-adfærd --><script src="libs/mobile-drag-drop/release/scroll-behaviour.min.js"></script><script> MobileDragDrop.polyfill({ dragImageTranslateOverride: MobileDragDrop.scrollBehaviourDragImageTranslateOverride });</script>
  • SystemJS/JSPM:
    System.import("mobile-drag-drop");System.import("mobile-drag-drop/default.css!"); // Hvis du bruger SystemJS CSS loader plugin
  • ES2015/TypeScript/webpack:
    import { polyfill } from "mobile-drag-drop";import { scrollBehaviourDragImageTranslateOverride } from "mobile-drag-drop/scroll-behaviour";polyfill({ dragImageTranslateOverride: scrollBehaviourDragImageTranslateOverride});

Vigtigt: Implementer en dragenter-lytter!

En af de mest almindelige faldgruber ved HTML5 Drag & Drop, især i kombination med polyfills, er kravet om en dragenter-lytter. På desktop-browsere vil en drag-operation ofte tillades stille, selvom der ikke er en dragenter-handler registreret. Dette er i strid med specifikationen, som kræver, at du eksplicit tillader et drop ved at kalde event.preventDefault() i både dragenter- og dragover-begivenhederne.

Polyfill'et er afhængigt af, at du korrekt håndterer dette. Sørg for at tilføje en lytter som denne til dine potentielle dropzones:

// dragenter lytter(event) => { event.preventDefault(); // Dette er essentielt for at tillade et drop}

For iOS Safari 10.x og nyere:

iOS 10 og nyere understøtter passive event listeners. For at sikre korrekt funktionalitet og undgå problemer med scrolling under en træk-operation, kan det være nødvendigt at tilføje en global touchmove-lytter med passive: false:

window.addEventListener('touchmove', function() {}, { passive: false });

Dette er en vigtig detalje for at forhindre browseren i at optimere touch-begivenheder væk, hvilket kan forstyrre polyfill'ets evne til at fange dem.

Avancerede Konfigurationer og Tilpasning

mobile-drag-drop polyfill'et tilbyder en række konfigurationsmuligheder, der giver dig finjusteret kontrol over træk-og-slip-adfærd, især i mobile miljøer.

export interface Config { forceApply?: boolean; // Tving polyfill'et til at blive anvendt dragImageOffset?: Point; // Statisk offset for træk-billedet dragImageCenterOnTouch?: boolean; // Centrer træk-billedet på touch-koordinater iterationInterval?: number; // Interval for behandlingen af træk-operationen (standard 150ms) dragStartConditionOverride?: (event: TouchEvent) => boolean; // Overstyr logik for start af træk dragImageTranslateOverride?: DragImageTranslateOverrideFn; // Tilpasning af træk-billede position defaultActionOverride?: (event: TouchEvent) => void; // Overstyr standardhandling holdToDrag?: number; // Forsinkelse for 'hold for at trække' (ms) tryFindDraggableTarget?: (event: TouchEvent) => HTMLElement | undefined; // Find træk-element dragImageSetup?: (element: HTMLElement) => HTMLElement; // Tilpasning af træk-billede oprettelse elementFromPoint?: (x: number, y: number) => Element; // Tilpasning af element-detektion}
  • dragImageTranslateOverride: Bruges til at implementere specifikke scroll-adfærd under træk, f.eks. at holde træk-billedet synligt, selvom siden scroller.
  • dragImageOffset og dragImageCenterOnTouch: Tillader præcis placering af træk-billedet i forhold til brugerens finger eller musemarkør. Dette er afgørende for en god brugervenlighed.
  • iterationInterval: Kontrollerer ydeevnen ved at justere, hvor ofte træk-begivenheder behandles. Et lavere interval giver mere responsivitet, men kan øge CPU-forbruget.
  • dragStartConditionOverride: Giver dig mulighed for at definere din egen logik for, hvornår en træk-operation skal starte. Dette er nyttigt for at implementere specifikke gestures eller betingelser.
  • holdToDrag: En yderst nyttig funktion for mobile enheder. Den implementerer 'hold for at trække'-funktionalitet, hvilket er fantastisk til elementer, der også er scrollbare. Det forhindrer utilsigtet scrolling, når brugeren forsøger at trække.

Når holdToDrag er aktiveret, udløser det trækbare element to brugerdefinerede begivenheder:

  • dnd-poly-dragstart-pending: Udløses, når touchstart detekteres, og en træk-operation er ved at starte efter den angivne forsinkelse.
  • dnd-poly-dragstart-cancel: Udløses, hvis træk-operationen afbrydes (f.eks. ved touchmove, touchend, touchcancel eller scroll) inden for holdToDrag-forsinkelsen.

Disse begivenheder kan bruges til at give visuel feedback til brugeren, f.eks. en fremdriftsindikator, der viser, at en træk-operation er ved at starte.

Tilpasning af Træk-Billedet (Drag Image)

Træk-billedet er den visuelle repræsentation af det element, der trækkes. Du kan tilpasse det på flere måder:

  • setDragImage(): Den standardiserede måde at indstille et brugerdefineret træk-billede på. Dette er en del af det indbyggede DataTransfer-objekt.
  • CSS-klasser: Polyfill'et anvender specifikke CSS-klasser til træk-billedet, som du kan overskrive for at tilpasse udseendet og snapback-adfærden. Brug !important for at sikre, at dine stilarter prioriteres.
    .dnd-poly-drag-image { opacity: .5 !important;}.dnd-poly-drag-image.dnd-poly-snapback { transition: transform 250ms ease-out !important;}

    Klasser som .dnd-poly-drag-icon anvendes som en baseklasse, og yderligere klasser (none, copy, move, link) anvendes baseret på den aktuelle drop-effekt, hvilket giver dig mulighed for at style ikoner for de forskellige træk-typer.

  • dragImageSetup-funktion: For den mest avancerede tilpasning kan du angive en brugerdefineret dragImageSetup-funktion i polyfill-konfigurationen. Denne funktion giver dig fuld kontrol over, hvordan en kopi af det trukne element oprettes og transformeres til et træk-billede.

Kendte Problemer og Begrænsninger

Selvom polyfill'et gør et fremragende stykke arbejde med at udfylde hullerne i Drag & Drop-understøttelsen, er der et par kendte begrænsninger:

  • iFrames: Træk-og-slip-operationer på tværs af iFrames understøttes i øjeblikket ikke fuldt ud, hvilket kan begrænse funktionaliteten i visse indlejrede scenarier.
  • Pseudo-elementer (:before/:after): CSS pseudo-elementer kan ikke kopieres direkte til træk-billedet. Som standard fjernes klasser rekursivt fra træk-billedet for at undgå side-effekter, men dette kan påvirke stilarter baseret på pseudo-elementer. Du kan omgå dette med en brugerdefineret dragImageSetup-funktion.

Forskelle i Browserimplementeringer

Selv med den indbyggede HTML5 Drag & Drop API er der uoverensstemmelser i, hvordan browsere implementerer specifikke detaljer. Disse forskelle kan føre til uventet adfærd, hvis de ikke tages i betragtning. Polyfill'et hjælper med at udjævne mange af disse, men det er godt at være opmærksom på dem.

Tabel over Browserforskelle

Browserdragstartdragdragenddragenterdragoverdragleavedragexit
Firefoxevent.dataTransfer.setData(type, data) påkrævet. effectAllowed, dropEffect skal også sættes i dragenter/dragover, hvis sat i dragstart.
IE11event.preventDefault(), når registreret på body.
Polyfillevent.preventDefault() eller dropzone påkrævet.

Tomme celler betyder, at der ikke er noget særligt at tage højde for.

  • event.dataTransfer.setData(type, data): På nogle browsere, især Firefox, er det absolut nødvendigt at kalde setData i dragstart-begivenheden for at sikre, at træk-operationen overhovedet starter. Dette er en god praksis at følge universelt.
  • effectAllowed og dropEffect: Disse egenskaber på dataTransfer-objektet styrer de visuelle effekter (f.eks. om elementet kopieres eller flyttes) og om et drop er tilladt. Firefox har en specifik adfærd, hvor disse skal sættes konsekvent på tværs af dragstart, dragenter og dragover for at fungere korrekt.
  • event.preventDefault() i dragenter og dragover: Dette er den mest kritiske forskel. Ifølge specifikationen skal du kalde event.preventDefault() i dragenter og dragover for at indikere, at et drop er tilladt på det pågældende element. Hvis du ikke gør dette, vil browseren som standard afvise drop-operationen. Mange desktop-browsere er dog mere tilgivende og tillader et drop uden denne kald, hvilket kan skabe forvirring og inkonsekvent adfærd, når man flytter til mere strikte browsere eller polyfills.
  • Automatisk scrolling: De fleste browsere (IE11, Chrome, Firefox) implementerer automatisk scrolling, når et element trækkes tæt på kanten af visningsporten. Dette er en indbygget brugervenlighedsfunktion, der sjældent kræver intervention, men er god at være opmærksom på.

Anbefalinger for Bred Browserkompatibilitet

For at sikre den bedst mulige og mest robuste træk-og-slip-funktionalitet på tværs af alle browsere og enheder, herunder mobil, følg disse grundlæggende anbefalinger:

  1. Sæt altid træk-data på dragstart: Kald altid event.dataTransfer.setData(type, data) i din dragstart-lytter. Dette sikrer, at træk-operationen initialiseres korrekt på tværs af alle browsere.
  2. Håndter altid dragenter-begivenheden på potentielle dropzones: Hvis et drop er tilladt på et element, skal du altid implementere en dragenter-lytter på dette element og kalde event.preventDefault() indeni. Dette er afgørende for at overholde specifikationen og sikre, at polyfill'et fungerer korrekt.
  3. Håndter altid dragover-begivenheden på dropzones: Ligesom med dragenter, skal du forhindre standardhandlingen ved at kalde event.preventDefault() i din dragover-lytter på potentielle dropzones, hvis et drop er tilladt. Hvis du udelader dette, vil træk-operationen blive afbrudt.

Ved at følge disse retningslinjer kan du i høj grad reducere risikoen for uventet adfærd og skabe en mere pålidelig træk-og-slip-oplevelse for dine brugere, uanset hvilken enhed eller browser de anvender.

Ofte Stillede Spørgsmål (FAQ)

Understøtter HTML5 Drag & Drop mobile browsere?

Oprindeligt var understøttelsen meget begrænset. Dog har nyere versioner af Safari på iOS/iPadOS (fra version 15) og Chrome på Android (fra version 96) nu indbygget understøttelse. For ældre mobile browsere eller for at sikre konsistent adfærd på tværs af alle enheder er et polyfill som mobile-drag-drop stadig nødvendigt.

Hvad er et polyfill?

Et polyfill er et stykke JavaScript-kode, der tilføjer eller simulerer funktionalitet, som en given browser mangler indbygget. I tilfældet med HTML5 Drag & Drop på mobile enheder, oversætter polyfill'et touch-begivenheder til standard træk-og-slip-begivenheder, så din kode kan fungere som forventet.

Hvorfor skal jeg kalde event.preventDefault() i min dragenter-lytter?

Ifølge HTML5 Drag & Drop-specifikationen skal du eksplicit indikere, at et element er en gyldig dropzone. Dette gøres ved at kalde event.preventDefault() i både dragenter- og dragover-begivenhederne. Hvis du ikke gør dette, vil browseren som standard afvise drop-operationen. Polyfill'et er afhængigt af denne adfærd for at fungere korrekt.

Kan jeg tilpasse udseendet af træk-billedet?

Ja, du kan tilpasse træk-billedet på flere måder. Du kan bruge DataTransfer.setDragImage() til at angive et brugerdefineret billede eller element. Derudover anvender polyfill'et specifikke CSS-klasser (f.eks. .dnd-poly-drag-image), som du kan overskrive med din egen styling. For avanceret kontrol kan du definere en brugerdefineret dragImageSetup-funktion i polyfill-konfigurationen.

Hvad er "hold for at trække" funktionalitet?

"Hold for at trække" (holdToDrag) er en konfigurationsmulighed i mobile-drag-drop polyfill'et, der introducerer en forsinkelse, før en træk-operation starter, efter at en bruger har rørt et element. Dette er især nyttigt på mobile enheder for at forbedre brugervenligheden, da det forhindrer utilsigtede træk-operationer, når brugeren i stedet forsøger at scrolle på et træk-bart element. Den giver også visuel feedback, når træk-operationen er ved at starte.

Hvis du vil læse andre artikler, der ligner HTML5 Drag & Drop: Komplet Guide til Mobilen, kan du besøge kategorien Mobiludvikling.

Go up