API drag and drop / Promesses en JS

Master Internet, Données et Connaissances

Alexandre Niveau

Enseignement des technologies du Web

 

API drag and drop / Promesses en JS

Notes de cours

Travail personnel

Objectifs

Le premier exercice est une application directe des promesses en JS. Le second manipule le drag and drop, avec un peu d'API File et de canevas (pour la découpe). N'hésitez pas à utiliser des promesses et/ou async/await — mais vous n'êtes pas obligé·e.

Exercice 1 — Promesses JS #

  1. Écrire une fonction getImage(url) qui prend une URL en paramètre sous forme de chaîne de caractères, et renvoie un élément img dont le src est l'URL donnée. Je précise au cas où qu'il n'est pas question de faire une requête HTTP ici !
  2. Écrire une fonction displayDimensions(img) qui prend un élément img en paramètre et qui affiche ses dimensions (largeur et hauteur) dans la console.
  3. Utiliser ces deux fonctions pour afficher les dimensions de l'image suivante : https://ensweb.users.info.unicaen.fr/tp/promesses/img/rust_mite.jpg. Si vous obtenez 0×0, pouvez-vous expliquer pourquoi ? Est-ce toujours le cas si vous actualisez ? Et si vous faites un hard reload (ctrl-maj-R sous Firefox) ?
  4. En fait, on voudrait n'exécuter displayDimensions qu'après que l'image ait fini de charger. Une solution pourrait être d'ajouter un callback en paramètre de getImage, mais ici on va utiliser des promesses.

    Faire en sorte que getImage, au lieu de renvoyer l'image HTML, renvoie une promesse qui se résout en l'image HTML une fois celle-ci chargée (et est rejetée si l'URL est incorrecte). Appeler displayDimensions par la méthode then() de la promesse renvoyée.

  5. Que se passe-t-il si vous passez une mauvaise URL à getImage ? Ajoutez un catch à la fin de la chaîne, qui affiche l'erreur dans la console.
  6. On vous fournit un service qui renvoie une URL d'image aléatoire : https://ensweb.users.info.unicaen.fr/tp/promesses/random-image/. Les images sont utilisables librement, elles proviennent du site PublicDomainPictures.net.

    Écrire une fonction getRandomUrl() qui interroge le service, et renvoie une promesse se résolvant en le résultat de la requête. Tester en faisant une chaîne de promesses avec getRandomUrl, getImage et displayDimensions.

  7. Écrire une fonction addRandomImage() qui interroge le service, crée une image et l'ajoute à la page. La fonction doit renvoyer une promesse se résolvant en l'image ajoutée une fois que celle-ci est chargée. On utilisera les fonctions précédemment écrites, d'abord sous forme de chaîne de promesses, puis avec await (sans oublier de déclarer addRandomImage comme étant async).
  8. Chaîner quelques appels de addRandomImage : on doit voir les images apparaître les unes après les autres.
  9. Lancer plusieurs addRandomImage en parallèle, et changer la couleur de fond de la page lorsque tout est terminé.

Exercice 2 — Générateur de puzzles #

On va créer une application légère permettant de générer un puzzle à partir d'une image et d'y jouer. Les pièces du puzzle seront simplement des rectangles, pour simplifier la programmation.

Pour commencer, faire une page avec deux zones, une pour les pièces en vrac (« zone de départ ») et une pour la résolution du puzzle.

Mise en place de l'interface du puzzle

  1. Écrire une fonction qui « divise » la zone de résolution en n lignes et m colonnes : on ajoutera tout simplement n×m éléments div qu'on affichera comme désiré grâce à Grid Layout. (Il n'est pas nécessaire que les différentes cellules soient visibles.)
  2. Récupérer cette archive contenant 9 pièces de puzzle, et les afficher dans un ordre aléatoire (à chaque fois différent) dans la zone des pièces. Découper la zone de résolution en 3×3. (Au cas où vous en auriez besoin : chaque pièce fait 205×115 pixels, l'image reconstituée faisant donc 615×345.)
  3. Faire en sorte qu'il soit possible de faire glisser chaque pièce vers toute cellule vide de la zone de résolution. S'assurer que le mouvement échoue si la cellule contient déjà une pièce.
  4. Faire en sorte qu'il soit possible de déplacer les pièces de la zone de résolution vers une autre cellule vide ou vers la zone de départ.

Amélioration de l'interface

  1. Faire en sorte que lors du glissement d'une pièce, celle-ci apparaisse dans la cellule couramment survolée (avec des couleurs un peu estompées).
  2. Faire en sorte que lorsque toutes les pièces sont placées, un message apparaisse indiquant si le puzzle est correctement terminé ou non.

Le jeu n'est pas très ergonomique : si on s'est trompé de position initiale pour un groupe de pièces, il faut les déplacer une par une.

  1. Faire en sorte qu'on puisse déplacer une pièce vers une cellule non vide, auquel cas la pièce déjà présente doit être renvoyée dans la zone de départ.
  2. Optionnel : Faire en sorte qu'il soit possible, en maintenant la touche « control » enfoncée, de déplacer ensemble toutes les pièces adjacentes à la pièce sélectionnée. Si le groupe est déposé par-dessus des pièces déjà placées, elles doivent être renvoyées dans la zone de départ.

Optionnel : Génération du puzzle

  1. Ajouter à la page un formulaire avec un widget d'upload ainsi que deux champs qui permettront de rentrer le nombre de pièces désiré, en largeur et en hauteur, pour le puzzle.
  2. Faire en sorte qu'à la soumission du formulaire, si le fichier est une image, elle soit découpée en morceaux suivant la largeur et la hauteur indiquées.
  3. Modifier le code de l'interface du puzzle pour qu'elle utilise les pièces ainsi découpées, et que les cellules de la zone de résolution soient cohérentes (en nombre et en taille) avec le découpage.