Web workers — Canvas

Master Internet, Données et Connaissances

Alexandre Niveau

Enseignement des technologies du Web

 

Web workers — Canvas

Notes de cours

Travail personnel

Objectifs

Le premier exercice est une application directe des web workers pour constater leur intérêt en pratique. Dans le deuxième, on utilise le canevas pour manipuler des images, et on mélange ça avec les web workers et l'API File. Le dernier exercice est une manipulation basique du canevas pour dessiner.

Exercice 1 — Nombres premiers #

On utilise un prétexte simple pour manipuler un peu les web workers : une appli qui calcule le n-ième nombre premier. Par exemple le premier nombre premier est 2, le deuxième est 3, le troisième est 5, etc.

  1. Créer une page avec deux formulaires, qui vont nous servir à tester avec ou sans workers. Chaque formulaire doit contenir un input (pour un nombre), un output et un bouton.
  2. Écrire une fonction is_prime(z) qui teste si le nombre entier z donné est premier. Ne pas viser l'efficacité ! L'objectif ici est de tester des fonctions qui prennent du temps à s'exécuter de toute façon…
  3. Écrire une fonction nth_prime(n) qui retourne le n-ième nombre premier (comme expliqué plus haut). On utilisera évidemment la fonction précédente, et on ne cherchera pas à faire quelque chose de malin !
  4. Faire en sorte que le premier formulaire calcule le n-ième nombre premier dans son output, avec n l'entier donné en input par l'internaute.
  5. Donnez un input suffisamment grand pour que le calcul prenne du temps ; en fonction de la machine et de votre implémentation, avec un n de l'ordre de 100 000 ça devrait déjà être pas mal (augmentez progressivement pour que le calcul prenne au moins quelques secondes). Constater que l'UI de la page n'est pas utilisable du tout.
  6. Utiliser un web worker pour que le second formulaire fasse le même calcul, mais dans un autre thread (et potentiellement, en fonction de la machine, dans un autre cœur). Constater que l'UI de la page reste majoritairement utilisable.
    Attention, les navigateurs peuvent mettre en cache le script exécuté par les workers, et ne pas le mettre à jour lors d'un rafraîchissement de la page, ce qui est très ennuyeux lors du développement. Si vous rencontrez le problème, une solution simple est d'ajouter à l'URL du script un paramètre bidon qui change à chaque appel, afin de forcer le téléchargement malgré le cache. On pourra utiliser par exemple "worker.js?v=" + new Date().getTime(). (On enlèverait évidemment ce paramètre sur un site en production.)
  7. Optionnel : ajouter une progressbar indiquant la progression du calcul.

Exercice 2 — Éditeur d’images #

On va créer un début d'application de traitement d'image.

Les bases : manipulation des pixels de l'image

  1. Créer une page avec une image et un canevas.
  2. Dessiner l'image dans le canevas. La page doit maintenant présenter deux images identiques.
  3. Inverser les couleurs de l'image dans le canevas.
  4. Au lieu d'inverser les couleurs directement au démarrage de la page, ajouter un bouton qui permette de le faire à la demande.

Délégation du travail à un thread

Normalement, le traitement de l'image n'est pas instantané : essayer avec une image relativement grosse (quelques mégaoctets). Il est donc pertinent de déléguer ce travail à un worker.

Mettre en place un worker qui récupère les données de l'image, travaille dessus, et renvoie le résultat. Il va falloir utiliser le transfert d'objet, pour éviter de copier les données entre le script et le worker.

Édition d'une image fournie par l'internaute

On va maintenant rendre notre page plus interactive.

  1. Enlever l'image, et mettre à la place un champ d'upload de fichier, qui va permettre à l'internaute de manipuler ses propres images.
  2. Lors de la sélection d'un fichier par l'internaute, s'il s'agit d'une image, elle doit se dessiner dans le canevas. NB : le moyen le plus simple est de créer un img en JS et de procéder comme précédemment (sauf que l'élément img n'apparaîtra pas sur la page).

Optionnel : amélioration de l'éditeur

Ajouter trois sliders R, G, B, avec des valeurs de 0 à 255, et les utiliser pour créer un effet de seuil ou d'écrêtage : la valeur du canal R de chaque pixel n'est gardée que si elle est supérieure au seuil, sinon elle est mise à 0 (ou à 255, ou au seuil, au choix).

Exercice 3 — Application de dessin #

On va manipuler le canevas HTML5 en faisant une petite application de dessin. Créer une nouvelle page avec un canevas.

  1. Dessiner un point là où l'internaute clique sur le canevas.
  2. Ajouter un contrôle permettant de changer la taille du pinceau (par exemple un input de type range).
  3. Ajouter un bouton permettant de passer en « mode arc-en-ciel », c'est-à-dire que la couleur du pinceau passe progressivement par plusieurs couleurs (idéalement, les couleurs de l'arc-en-ciel, mais on se contentera de quelque chose de simple pour commencer).
  4. Ajouter un bouton permettant de télécharger le dessin effectué. Pour ce faire, utiliser une des méthodes d'export des données du canevas (data-URL ou blob), créer un lien qui pointe vers le résultat, puis cliquer dessus en JavaScript (méthode HTMLElement.click()). Pour que le navigateur propose un téléchargement au lieu de se rendre à l'URL indiquée, utiliser l'attribut download de l'élément a. Le lien doit être dans le document pour qu'on puisse appeler click dessus, mais rien n'iterdit de le cacher avec du CSS.
  5. Optionnel : notre application n'est pas très pratique pour dessiner, puisque l'on passe son temps à cliquer. Faire en sorte que l'on puisse dessiner en gardant le bouton de la souris enfoncé. (Remarque : dessiner plutôt des chemins que des points, pour éviter d'obtenir des pointillés si l'internaute fait des mouvements trop grands ou trop rapides).
  6. Optionnel : afficher cette image libre de droits (source) quelque part sur la page. Quand l'internaute clique sur une des icônes, et qu'il ou elle clique ensuite sur le canevas, l'icône doit être recopiée à l'endroit où le clic a eu lieu.