Skapa en Parkering Spel Med HTML Dra och Släppa API

0
72

Bland de många JavaScript-Api: er lagts till i HTML5 var att Dra och Släppa (som vi kommer att hänvisa till det som DnD i denna artikel) som förde native DnD stöd till webbläsaren, vilket gör det lättare för utvecklare att implementera denna interaktiva inslag i program. Den fantastiska sak som händer när man har blivit lättare att genomföra är att människor börjar göra alla typer av dumma, opraktiska saker med det, som vi gör i dag: en parkering spel!

DnD kräver bara ett par saker att fungera:

  • Något att dra
  • Någonstans att släppa
  • JavaScript-event handlers på målet för att tala om för webbläsaren att det kan släppa

Vi kommer att börja med att skapa vår draggables.

Dra

Både <img> och <a>(href-attribut) element är flyttbara som standard. Om du vill dra ett annat element, måste du ställa in den flyttbara tillskriva sant.

Vi börjar med HTML som ställer upp bilderna för våra fyra fordon: brandbil, ambulans, bil och cykel.

<ul class=”fordon”>
<li>
<!– Brandbil –>
<!– <kod> < img > <code> – element behöver inte en <code>flyttbara<code> attribut som andra delar –>
<img id=”eld-truck” alt=”brandbil” src=”https://cdn.glitch.com/20f985bd-431d-4807-857b-e966e015c91b%2Ftruck-clip-art-fire-truck4.png?1519011787956″/>
</li>
<li>
<!– Ambulans –>
<img id=”ambulans” alt=”ambulans” src=”https://cdn.glitch.com/20f985bd-431d-4807-857b-e966e015c91b%2Fambulance5.png?1519011787610″>
</li>
<li>
<!– Bil –>
<img id=”bil” alt=”bil” src=”https://cdn.glitch.com/20f985bd-431d-4807-857b-e966e015c91b%2Fcar-20clip-20art-1311497037_Vector_Clipart.png?1519011788408″>
</li>
<li>
<!– Cykel –>
<img id=”bike” alt=”cykel” src=”https://cdn.glitch.com/20f985bd-431d-4807-857b-e966e015c91b%2Fbicycle-20clip-20art-bicycle3.png?1519011787816″>
</li>
</ul>

Eftersom bilder är flyttbara som standard kommer du att se att dra någon av dem skapar en ghost image.

Bara att lägga till en flyttbar attribut till ett element som inte har en bild eller länk är egentligen allt du behöver för att göra ett inslag flyttbara i de flesta webbläsare. För att göra flyttbara element i alla webbläsare, du behöver definiera några event handlers. De är också användbara för att lägga till extra funktionalitet som en gräns om ett element dras runt eller ett ljud om det slutar att dras med. För dessa, du kommer att behöva några drag event handlers, så låt oss titta på dem.

Dra Händelser

Det finns tre drag-relaterade händelser som du kan lyssna till men vi kommer enbart att använda två: dragstart och dragend.

  • dragstart – Utlösas så snart som vi börjar att dra. Det är där vi kan definiera dra data och dra effekt.
  • dragend – Utlöses när en flyttbara element är tappade. Detta event är i allmänhet sparken direkt efter drop zone ‘ s drop-händelse.

Vi kommer att gå igenom vad de dra data och dra effekten är kort.

låt dras; // Håller koll på vad som dras – vi kommer att använda denna senare!

funktion onDragStart(event) {
låt target = evenemanget.- mål.
om (mål && target.nodnamn = = = “IMG”) { // Om målet är en bild
släpade = mål;
händelsen.dataöverföring.setData(‘text’, target.id);
händelsen.dataöverföring.dropEffect = ‘flytta’;
// Gör det en halv transparent när den dras
händelsen.- målet.style.opacitet = .3;
}
}

funktion onDragEnd(event) {
om (händelse.mål && event.- målet.nodnamn = = = “IMG”) {
// Återställ öppenhet
händelsen.- målet.style.opacitet = “; // Återställ opacitet när du drar slutar
släpade = null;
}
}

// Lägger till händelse lyssnare
const fordon = dokument.querySelector(‘.fordon’);
fordon.addEventListener(‘dragstart’, onDragStart);
fordon.addEventListener(‘dragend’, onDragEnd);

Det finns ett par saker som händer i denna kod:

  • Vi definierar dra data. Varje drag händelse har en egenskap som kallas dataöverföring som lagrar den data. Du kan använda setData(typ av data) metod för att lägga till en dras objektet för att dra data. Vi lagra dras bildens ID som typ “text” – i linje 7.
  • Vi kan lagra de element som dras i en global variabel. Jag vet, jag vet. Global är farliga för avgränsning men här är varför vi gör det: även om du kan lagra dras objektet med hjälp av setData, du kan inte hämta den med hjälp av händelsen.dataöverföring.getData() i alla webbläsare (utom Firefox), eftersom de dra data är skyddat läge. Du kan läsa mer om det här. Jag ville nämna att definiera dra data bara så att du vet om det.
  • Vi är inställningen den dropEffect att flytta. Den egenskapen dropEffect används för att styra den feedback användaren ges under en dra-och-släpp operationen. Till exempel, det förändringar som markören visas medan du drar. Det finns tre effekter: kopiera, flytta och länk.
    • kopiera – Indikerar att data som dras kommer att vara kopierad från dess källa till drop läge.
    • flytta – Indikerar att data som dras kommer att flyttas.
    • länk – Visar att någon form av relation skapas mellan källan och släpp platser.

Nu har vi dra och släppa fordon men ingenstans att släppa dem:

Se Penna 1 – Kan du parkera här? genom att Omayeli Arenyeka (@yelly) på CodePen.

Släppa

Som standard, när du drar en del, enda element som <input> – kommer att kunna acceptera det som en droppe. Vi kommer att innehålla våra “dropzone” i en <del> – element, så vi måste lägga släppa event handlers så att den kan godta droppar precis som ett formelement.

För det första, eftersom det är ett tomt element som vi kommer att behöva ställa in en bredd, höjd och färg för bakgrunden på det så vi kan se det på skärmen.

Det är dessa parametrar som vi har tillgängliga för drop händelser:

  • dragenter – Utlöses i det ögonblick en flyttbar punkt går in i en hittas området. Minst 50% av den flyttbara element måste vara inne drop zone.
  • dragover – samma som dragenter, men det kallas upprepade gånger medan flyttbara objekt är inom drop zone.
  • dragleave – Utlöses när en flyttbar punkt har flyttat från en drop zone.
  • drop – Utlöses när den flyttbara objekt har släppts och drop området går med på att acceptera att sjunka.

funktion onDragOver(event) {
// Förhindra standard för att möjliggöra släpp
händelsen.preventDefault();
}

funktion onDragLeave(event) {
händelsen.- målet.style.bakgrund = “;
}

funktion onDragEnter(event) {
const target = evenemanget.- mål.
if (target) {
händelsen.preventDefault();
// Ställ in dropEffect att flytta
händelsen.dataöverföring.dropEffect = ‘flytta’
– målet.style.bakgrund = ‘#1f904e’;
}
}

function onDrop(event) {
const target = evenemanget.- mål.
if ( target) {
– målet.style.backgroundColor = “;
händelsen.preventDefault();
// Get-id av målet och lägga till den flyttade element till målet: s DOM
drog.parentNode.removeChild(släpade);
drog.style.opacitet = “;
– målet.appendChild(släpade);
}
}

const dropZone = dokument.querySelector(‘.drop-zone”);
dropZone.addEventListener (“drop”, onDrop);
dropZone.addEventListener(‘dragenter’, onDragEnter);
dropZone.addEventListener(‘dragleave’, onDragLeave);
dropZone.addEventListener(‘dragover’, onDragOver);

Om du undrar varför vi fortsätter att kalla händelsen.preventDefault() det är på grund av standard webbläsare tar dock något som helst mål är inte ett giltigt släpp mål. Detta är inte sant hela tiden för alla webbläsare, men det är bättre att vara säker än ledsen! Anropa preventDefault() på dragenter, dragover och släpp händelser, informerar webbläsaren att det nuvarande målet är en giltig släpp mål.

Nu har vi en enkel dra-och-släpp program!

Se Penna 2 – Kan du parkera här? genom att Omayeli Arenyeka (@yelly) på CodePen.

Det är roligt, men inte riktigt lika frustrerande som parkering. Vi måste skapa vissa regler för att få det att hända.

Regler och Validering

Jag kom upp med lite random parkering regler, och jag vill uppmuntra dig att skapa dina egna. Parkering skyltar brukar ha dagar och tider du kan parkera samt vilka typer av fordon är tillåtna att parkera vid denna tidpunkt. När vi skapar våra flyttbara objekt, vi hade fyra fordon: en ambulans, en brandbil, en vanlig bil och en cykel. Så, vi kommer att skapa regler för dem.

  1. Ambulans parkering bara: måndag till fredag, klockan 9 till 3am.
  2. Fire truck parkering: Alla dagar under helgen.
  3. Vanlig bil parkering: måndag till fredag, 3am att 3pm.
  4. Cykelparkering: måndag till fredag, 3 pm till 9 pm.

Vi kan nu översätta dessa regler kod. Vi kommer att använda två bibliotek för att hantera tid och intervall: Ögonblick och Nu-utbud.

Skript redan finns i Codepen att lägga till någon ny demo, men om du utvecklar utanför Codepen du kan kopiera eller länka upp dem här:

<skriften skjuta src=”https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.js”></script>
<skriften skjuta src=”https://cdnjs.cloudflare.com/ajax/libs/moment-range/3.1.1/moment-range.js”></script>

Sedan skapar vi ett objekt att lagra all parkering regler.

fönstret[‘ögonblick-rad’].extendMoment(nu);

// En array av vardagar
const vardagar = [‘måndag’, ’tisdag’, ‘onsdag’, ‘torsdag’, ‘fredag’];
const parkingRules = {
ambulans: {
// Ambulans kan endast parkera på vardagar…
dagar: måndag-fredag,
// …från klockan 9 till 3am (nästa dag)
tid: createRange(nu().set(‘timme’, 21), nu().add(1, “dag”).set(‘timme’, 3))
},
“fire truck’: {
// Den brandbil kan obnly park på lördagar och söndagar, men hela dagen
dagar: [‘lördag’, ‘söndag’]
},
bil: {
// Den bilen kan endast parkera på vardagar…
dagar: måndag-fredag,
// …3am – 3pm (samma dag)
tid: createRange(nu().set(‘timme’, 3), nu().set(‘timme’, 15))
},
cykel: {
// Den bilen kan endast parkera på vardagar…
dagar: måndag-fredag,
// …från 3 pm – 9 pm (samma dag)
tid: createRange(nu().set(‘timme’, 15), nu().set(‘timme’, 21))
}
};

funktion createRange(start, slut) {
om (start och slut) {
tillbaka nu.intervall(start, slut);
}
}

Varje fordon i parkingRules objekt har en dagar fastighet med en rad av dagar kan det park och times egendom som är ett tidsintervall. För att få den aktuella tiden med Nu, ring ögonblick(). För att skapa ett område med hjälp av Moment-utbud, passera start-och sluttid för tillfället.sortiment funktion.

Nu, i onDragEnter och onDrop event handlers vi definierade tidigare, vi lägger till vissa kontroller för att se till att en bil kan parkera. Våra alt-attribut i img-taggen är att lagra den typ av fordon så att vi klarar av att canPark metod som kommer tillbaka om bilen kan parkeras. Vi har även lagt visuella ledtrådar (förändring i bakgrunden) för att tala om för användaren om en bil kan parkeras eller inte.

funktion onDragEnter(event) {
const target = evenemanget.- mål.
om (släpade && target) {
const vehicleType = dras.alt; // e.g cykel, ambulans
om (canPark(vehicleType)) {
händelsen.preventDefault();
// Ställ in dropEffect att flytta
händelsen.dataöverföring.dropEffect = ‘flytta’;
/* Ändra färg till grönt för att visa att det kan vara tappats /*
– målet.style.bakgrund = ‘#1f904e’;
}
else {
/* Ändra färg till rött för att visa att det inte kan tas bort. Märker vi
* don ‘ t call händelse.preventDefault() här så att webbläsaren inte
* låt en droppe som standard
*/
– målet.style.backgroundColor = ‘#d51c00’;
}
}
}

function onDrop(event) {
const target = evenemanget.- mål.
if (target) {
const data = evenemanget.dataöverföring.getData(‘text’);
const släpade = dokument.getElementById(data);
const vehicleType = dras.alt;
– målet.style.backgroundColor = “;
om (canPark(vehicleType)) {
händelsen.preventDefault();
// Get-ID av målet och lägga till den flyttade element till målet: s DOM
drog.style.opacitet = “;
– målet.appendChild(släpade);
}
}
}

Sedan skapar vi canPark metod.

funktion getDay() {
tillbaka ögonblick().format(‘dddd’); / / – format som ‘måndag’, inte 1
}

funktion getHours() {
tillbaka ögonblick().timme();
}

funktion canPark(fordon) {
/* Kolla tid och typ av fordon som dras
* för att se om det kan parkera vid denna tid
*/
om (bil && parkingRules[bilen]) {
const bestämmelser = parkingRules[bilen];
const validDays = regler.dagar.
const validTimes = regler.tider;
const curDay = getDay();
om (validDays) {
/* Om den aktuella dagen på parkering dagar för fordon
* Och om den aktuella tiden är inom intervallet
*/
tillbaka validDays.innehåller(curDay) && (validTimes ? validTimes.innehåller(nu()) : true);
/* Moment.har sortimentet innehåller en funktion som kontrollerar
* för att se om ditt sortiment innehåller en stund.
https://github.com/rotaready/moment-range#contains
*/
}
}
return false;
}

Nu är det bara bilar som är tillåtet att parkera kan parkera. Slutligen lägger vi på reglerna att skärmen och stil.

Här är det slutliga resultatet:

Se Pennan 3 – Kan du parkera här? genom att Omayeli Arenyeka (@yelly) på CodePen.

Det finns massor av sätt detta kan förbättras:

  • Auto-genererar HTML-koden för listan regler från parkingRules objekt!
  • Lägg till några ljudeffekter!
  • Lägg förmåga att dra tillbaka fordon till utgångspunkten utan att sidan uppdateras.
  • Alla de där irriterande globala variabler.

Men jag ska låta dig hantera det.

Om du är intresserad av att lära mer om DnD API och en del kritik för det, här finns en del bra läsning:

  • WHATWG Specifikation
  • Att arbeta med HTML5 Dra-och-Släpp – Pro HTML5 Programming, Kapitel 9, med Jen Simmons
  • Tillgänglig Dra och Släppa med Hjälp av WAI-ARIA – Tillgänglighet överväganden från Dev.Opera
  • Native HTML5 Dra och Släpp – HTML5 Stenar handledning
  • HTML5 dra och släppa katastrof – QuirksMode inlägg med hjälp sammanhang på DnD modul genomförande