How do I drag and drop an image?

HTML Træk og Slip: Guide for Fotografer

Som fotografer er vi vant til at flytte rundt på elementer – det være sig i vores kompositioner, i billedredigering eller endda fysisk i studiet. På en hjemmeside er evnen til at 'trække og slippe' elementer lige så intuitiv for brugeren. Denne funktionalitet, kendt som Drag and Drop, er en standarddel af HTML5 og giver dig mulighed for at skabe dynamiske og interaktive weboplevelser. Men hvad sker der, når det ikke virker, og hvordan får du det til at fungere korrekt?

Træk og Slip-funktionen, eller Drag and Drop, er en meget almindelig interaktion på internettet. Det er processen, hvor du 'griber' et objekt med musemarkøren og flytter det til en anden placering på skærmen. Dette er utrolig nyttigt til at omarrangere lister, uploade filer (selvom dette kræver mere end kun HTML Drag and Drop API'en), eller som i et simpelt eksempel, flytte et billede eller et tekstelement.

HTML Drag and Drop API'en gør det muligt for elementer at blive trukket og slippet. Selvom det kan virke simpelt for brugeren, involverer implementeringen en række trin og hændelser, som skal konfigureres korrekt for, at det virker.

How do I enable drag and drop functionality?
DO THE DROP - ONDROP1Call preventDefault() to prevent the browser default handling of the data (default is open as link on drop)2Get the dragged data with the dataTransfer. getData() method. ...3The dragged data is the id of the dragged element ("img1")4Append the dragged element into the drop element.
Indholds

Sådan Aktiverer Du Træk og Slip

Grundlaget for at gøre et element trækkeligt er utrolig simpelt. Du skal blot tilføje attributten draggable="true" til det HTML-element, du ønsker at gøre trækkeligt. Dette fortæller browseren, at dette element potentielt kan initierer en træk-operation.

<img id="mitBillede" src="billede.jpg" draggable="true">

eller for et tekstelement:

<p id="minTekst" draggable="true">Denne tekst kan trækkes</p>

Uden denne attribut vil elementet ikke reagere på en træk-gestus på den måde, som Drag and Drop API'en forventer.

Hændelserne Bag Træk og Slip

Træk og Slip-processen er drevet af en række JavaScript-hændelser, der udløses på forskellige stadier af interaktionen. For at implementere funktionen korrekt skal du lytte efter og reagere på disse hændelser.

1. Når trækket starter: ondragstart

Den første vigtige hændelse er ondragstart. Denne udløses, når brugeren begynder at trække et element. Her skal du specificere, hvilke data der skal overføres under træk-operationen. Dette gøres ved at bruge dataTransfer-objektet, som er en del af hændelsesobjektet. Metoden dataTransfer.setData(format, data) bruges til at sætte data.

I et typisk eksempel sætter man elementets ID som data, med formatet "text". Dette ID kan så bruges senere til at finde elementet, der blev trukket.

function dragstartHandler(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}

Denne funktion kaldes, når ondragstart-hændelsen udløses på det trækkelige element:

<img id="img1" src="img_logo.gif" draggable="true" ondragstart="dragstartHandler(event)">

Her sættes dataen til elementets eget ID (ev.target.id), og formatet er "text".

2. Hvor må der slippes?: ondragover

Som standard kan data/elementer ikke bare slippes hvor som helst i browseren. For at tillade, at et element kan slippes i et bestemt område (en "dropzone"), skal du lytte efter ondragover-hændelsen på det element, der skal fungere som dropzone. Inden i hændelseshandleren for ondragover skal du kalde event.preventDefault().

Hvorfor preventDefault()? Fordi browserens standardhåndtering for ondragover er at *ikke* tillade et slip. Ved at kalde preventDefault() overskriver du denne standardadfærd og signalerer til browseren, at et slip er tilladt her.

function dragoverHandler(ev) {
ev.preventDefault(); // Tillad slip
}

Denne funktion kaldes på det element, der skal være dropzone:

<div id="div1" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)"></div>

3. Når slippet sker: ondrop

Den endelige hændelse er ondrop, som udløses, når det trækkelige element slippes over et gyldigt dropzone-element. I handleren for ondrop skal du først og fremmest igen kalde event.preventDefault().

Denne gang er formålet med preventDefault() at forhindre browserens standardhåndtering af det droppede data, som for eksempel kunne være at åbne dataen som et link, hvis det var et URL. Efter at have forhindret standardhandlingen, kan du hente de data, der blev sat i ondragstart, ved hjælp af dataTransfer.getData(format).

Formatet, du bruger i getData(), skal matche det format, du brugte i setData() (f.eks. "text"). Når du har dataen (typisk elementets ID), kan du finde det originale element ved hjælp af f.eks. document.getElementById() og udføre den ønskede handling, som i det simple eksempel er at flytte elementet til dropzonen ved at tilføje det som et child-element.

Why is my drag and drop not working?
Try restarting your computer and see if the issue persists. 2. Check Mouse Settings: Make sure that your mouse settings are correctly configured. Go to ``Settings'' > ``Devices'' > ``Mouse'' and ensure that drag and drop functionality is enabled. 3.
function dropHandler(ev) {
ev.preventDefault(); // Forhindr standardhandling (f.eks. åbning som link)
const data = ev.dataTransfer.getData("text"); // Hent data (elementets ID)
ev.target.appendChild(document.getElementById(data)); // Flyt elementet
}

Denne funktion er knyttet til dropzone-elementets ondrop-attribut:

<div id="div1" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)"></div>

Det er kombinationen af disse hændelser og deres korrekte håndtering, der får Drag and Drop til at virke.

Browser Understøttelse

HTML Drag and Drop API'en er bredt understøttet i moderne browsere. Her er en oversigt over, fra hvilken version understøttelsen er fuld:

API Internet Explorer Edge Firefox Chrome Safari Opera
Drag and Drop 4.0 12.0 3.5 4.0 6.0 12.0

Som tabellen viser, har API'en været understøttet i lang tid på tværs af de store browsere.

Eksempler på Implementering

Lad os se på de eksempler, der illustrerer de ovennævnte principper:

Eksempel 1: Træk et Billede

Dette er det klassiske eksempel, hvor et billede gøres trækkeligt og kan slippes i en specifik <div>.

<!DOCTYPE HTML>
<html>
<head>
<script>
function dragstartHandler(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function dragoverHandler(ev) {
ev.preventDefault();
}
function dropHandler(ev) {
ev.preventDefault();
const data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>

<p>Træk W3Schools billedet ind i det andet rektangel:</p>

<div id="div1" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)" style="border:1px solid black; width:350px; height:100px;"></div>
<img id="img1" src="img_logo.gif" draggable="true" ondragstart="dragstartHandler(event)" width="336" height="69">

</body>
</html>

Her har vi en <div> med ID'et "div1", som er vores dropzone. Den lytter efter ondragover (for at tillade slip) og ondrop (for at håndtere selve slippet). Billedet har ID'et "img1" og er gjort trækkeligt med draggable="true". Det lytter efter ondragstart for at sætte billedets ID som data.

Eksempel 2: Træk en Overskrift

HTML Drag and Drop er ikke begrænset til billeder. Du kan gøre næsten ethvert HTML-element trækkeligt.

<script>
function dragstartHandler(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function dragoverHandler(ev) {
ev.preventDefault();
}
function dropHandler(ev) {
ev.preventDefault();
const data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>

<p>Træk H1 elementet ind i rektanglet:</p>

<div id="div1" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)" style="border:1px solid black; width:350px; height:100px;"></div>
<h1 id="h1" draggable="true" ondragstart="dragstartHandler(event)">W3Schools.com</h1>

</body>
</html>

Dette eksempel er næsten identisk med det første, men bruger en <h1>-tag i stedet for et <img>-tag. Principperne forbliver de samme.

Eksempel 3: Træk et Link

Selv links (<a>-tags) kan gøres trækkelige, selvom deres standardadfærd ved slip normalt er at navigere til linkets URL.

<script>
function dragstartHandler(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function dragoverHandler(ev) {
ev.preventDefault();
}
function dropHandler(ev) {
ev.preventDefault();
const data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>

<p>Træk link elementet ind i rektanglet:</p>

<div id="div1" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)" style="border:1px solid black; width:350px; height:100px;"></div>
<a id="link1" href="https://w3schools.com" draggable="true" ondragstart="dragstartHandler(event)">W3Schools.com</a>

</body>
</html>

Her ser vi igen den samme struktur og de samme JavaScript-funktioner. Det vigtige at bemærke er, at event.preventDefault() i dropHandler er afgørende for at forhindre browseren i at følge linkets href, når elementet slippes.

Hvorfor Virker Mit Træk og Slip Ikke? (Almindelige Faldgruber)

Hvis du har forsøgt at implementere Drag and Drop baseret på eksemplerne, men det ikke virker, er der sandsynligvis en afgørende detalje, du har overset. Her er de mest almindelige årsager:

  1. Mangler draggable="true": Elementet, du prøver at trække, er simpelthen ikke markeret som trækkeligt. Browseren vil ikke starte træk-processen for det.
  2. Mangler event.preventDefault() i ondragover: Din dropzone tillader ikke slip. Uden preventDefault() i ondragover-handleren, vil browseren ikke tillade ondrop-hændelsen at blive udløst på det element. Dette er den mest almindelige årsag til, at slip-delen ikke virker.
  3. Mangler event.preventDefault() i ondrop: Selvom slippet teknisk set sker, kan browserens standardhandling for det droppede data overskrive din egen logik. For eksempel, hvis du trækker et billede eller et link, kan browseren forsøge at åbne det i stedet for at lade din JavaScript-kode håndtere det.
  4. Fejl i setData() eller getData(): Du sætter ikke data korrekt i ondragstart, eller du forsøger at hente data med et forkert format i ondrop. Sørg for, at format-strengen (f.eks. "text") er den samme begge steder.
  5. JavaScript-fejl: En fejl i din JavaScript-kode (f.eks. en stavefejl, en forkert variabelnavn, eller en fejl i DOM-manipulationen) kan forhindre processen i at fuldføre. Tjek browserens udviklerkonsol for fejlmeddelelser.
  6. Elementet findes ikke, når det droppes: Hvis du fjerner det originale element fra DOM'en i ondragstart (hvilket ikke er typisk for en simpel flytning, men kan ske i mere komplekse scenarier), vil document.getElementById(data) i ondrop fejle.

Ved systematisk at tjekke disse punkter kan du ofte finde årsagen til, at dit Drag and Drop ikke virker som forventet.

Ofte Stillede Spørgsmål

Hvad er dataTransfer-objektet?
dataTransfer-objektet indeholder de data, der overføres under en træk-operation, samt information om træk-operationen selv (f.eks. hvilken type træk der udføres, visuelle effekter). Det bruges med setData() til at gemme data og getData() til at hente data.
Hvorfor skal jeg bruge event.preventDefault() i både ondragover og ondrop?
I ondragover bruges det til at overskrive browserens standardadfærd, som er at ikke tillade slip i de fleste elementer. I ondrop bruges det til at forhindre browserens standardhåndtering af det droppede data (f.eks. at åbne et link eller et billede), så din egen kode kan håndtere slippet.
Kan jeg overføre mere end bare elementets ID?
Ja, du kan sætte og hente forskellige typer data ved hjælp af dataTransfer.setData() og getData(). Du kan f.eks. overføre tekststrenge, JSON-data, URLs osv., så længe du bruger matchende formater (de såkaldte "data types" eller "formats", som f.eks. "text", "URL", "application/json").
Hvordan kan jeg ændre markøren eller udseendet under trækket?
dataTransfer-objektet har også en effectAllowed-egenskab, der kan bruges i ondragstart til at angive, hvilke typer operationer der er tilladt (f.eks. 'copy', 'move', 'link'). I ondragover kan du bruge event.dataTransfer.dropEffect til at angive den visuelle feedback til brugeren (f.eks. 'copy', 'move'). Dette påvirker typisk markørens udseende.

Konklusion

HTML Drag and Drop API'en er et kraftfuldt værktøj til at skabe intuitive og interaktive webgrænseflader. Ved at forstå de centrale begreber – draggable-attributten og de tre primære hændelser ondragstart, ondragover og ondrop, samt vigtigheden af event.preventDefault() og brugen af dataTransfer-objektet – kan du implementere træk og slip-funktionalitet på dine egne hjemmesider. Selvom det kan virke komplekst ved første øjekast, er strukturen logisk, og når du først har styr på hændelsesflowet og dataoverførslen, åbner det op for mange muligheder for at forbedre brugeroplevelsen.

Så næste gang du undrer dig over, hvorfor dit træk og slip ikke virker, så tag et kig på de grundlæggende krav: Er elementet trækkeligt? Tillader din dropzone slip ved at forhindre standardhandlingen i ondragover? Håndterer din ondrop-funktion slippet korrekt ved at forhindre standardhandlingen og hente de korrekte data?

Hvis du vil læse andre artikler, der ligner HTML Træk og Slip: Guide for Fotografer, kan du besøge kategorien Fotografi.

Avatar photo

Franne Voigt

Mit navn er Franne Voigt, jeg er en 35-årig fotograf fra Danmark med en passion for at fange øjeblikke og dele mine erfaringer gennem min fotoblog. Jeg har arbejdet med både portræt- og naturfotografi i over et årti, og på bloggen giver jeg tips, teknikker og inspiration til både nye og erfarne fotografer. Fotografi er for mig en måde at fortælle historier på – én ramme ad gangen.

Go up