Head

Content

Démo en image avec un travail de commande sympathique pour l’agence Kerozen…

 

Et un bonus, qui préfigure un prochain tuto sur les sprites animés !

 

Précharger les images avec Processing.js en « API Mode », c’est à dire « Full-Javascript », c’est un vrai truc de chaffouin :)

Côté gestion des images, il faut d’abord comprendre que Processing est basé sur l’instantanéité de l’accès aux images, typos, etc. du dossier data/.
On travaille en mode « Application », en considérant que tout est à disposition immédiatement.

A l’inverse, Processing.js fonctionne sur le web : le script js est exécuté depuis votre navigateur, alors que les images sont sur le serveur…
On a donc un délai de chargement avant de pouvoir accéder aux images.
D’où la nécessité de mettre en place un préchargement des images.

Dans la documentation officielle, plusieurs fonctions de chargement des images sont indiquées : loadimage(), et requestImage() (celle-ci n’est pas facile à trouver, d’ailleurs).

Dans tous les cas, il est recommandé dans la doc d’indiquer les images à charger via des commentaires « spéciaux », à placer au tout début du sketch principal, qui n’étaient pas présents dans Processing :

/* @pjs preload="img1.jpg img2.jpg img3.jpg"; */

C’est prometteur, mais à l’usage :

  1. - ça n’empêche pas le script de démarrer, et les images apparaissent brusquement plus tard en cours d’animation, une fois chargées, une par une…
  2. - ça marche quand on publie directement un fichier .pde ou qu’on écrit le code dans une balise <script type=« application/processing »> (voir la doc et les 2 façons « simples » de publier avec Pjs), mais je n’ai jamais réussi à les faire fonctionner en « API mode », c’est à dire en Javascript direct…

Pas de solution « native » si on veut mélanger pjs+jquery, quoi…

J’ai donc essayé le préchargement en Javascript pur (attention, les pages indiquées piquent les yeux) :
http://www.editeurjavascript.com/scripts/scripts_images_2_2.php
http://www.paperblog.fr/1000777/une-fonction-javascript-pour-precharger-vos-images-lourdes/
Verdict : ben l’image devient accessible en Javascript, mais Pjs les charge visiblement d’une autre façon… aucun intérêt.

J’ai bien failli abandonner là, surtout quand j’ai constaté qu’en utilisant simplement requestImage() au lieu de loadimage(), on ne rencontre aucun problème sans rien spécifier de plus : la fonction supporte très bien l’asynchronicité !

C’est déjà ça, mais les images apparaissent avec un temps de retard, ce qui ne me satisfait pas, évidement :)

Bref, après bien des essais infructueux et complexe, je suis tombé sur cette info clé dans la doc de requestImage() :

« While the image is loading, its width and height will be 0« …
On peut donc détecter si l’image est dispo, grâce à sa propriété width !


Après, c’est une question d’astuce pour structurer le sketch principal, et lui dire d’attendre que les images soient chargées avant de s’exécuter !


Et voici la solution technique retenue, et ça se passe dans le sketch principal :

function pjsFunc(canvas) {

canvas.setup = function(){
   ...

   // création des PImages
   footer = pCanvas.requestImage("img/footer.gif");
   besher = pCanvas.requestImage("img/besher.gif");

   // liste des PImages à précharger
   preloadListe = new Array(footer, besher);

   // état du préchargement
   preload_ok = false;
};

canvas.draw = function(){

   // le code qu'on doit exécuter qu'on soit en preload ou pas
   pCanvas.background(255, 255, 255);

   if(preload_ok){ // preload terminé, mode "normal"

      // écriture des images
      pCanvas.image(besher, 150, 100);
      pCanvas.image(footer, 450, 300);

           ...

   } else { // preload en cours

      // on scanne chaque image de la liste une par une
      nbPreloaded = 0;
      for(i=0; i<preloadListe.length; i++){
         if(preloadListe[i].width > 0){
            // l'image est chargée
            nbPreloaded++;
         }
      }
      if(nbPreloaded>=preloadListe.length){
         // elles sont toutes chargées
         preload_ok = true;

         // c'est ici qu'on passe du mode "preload" au mode "normal", on peut donc prévoir des action JQuery à lancer seulement quand les images pjs sont chargées, au démarrage du mode "normal" :)
         $('#loader').fadeOut('fast');
         // là je cache simplement la div qui affiche le préchargement
      }
   }
};
};

Certes, c’est un peu lourd de modifier ainsi son sketch, mais ça fonctionne parfaitement bien et c’est un coup à prendre… d’autre part je ne crois pas qu’on puisse compter sur une autre solution dans l’immédiat.

Je prendrai certainement la peine par la suite de créer une fonction qui gère tout ça de matière plus « compacte »…

Il ne vous reste plus qu’à combiner ça avec une div de « préchargement » #loader toute simple (placée au-dessus du reste via CSS/z-index), avec par exemple un gif animé, qu’on masque une fois chargé (grâce à JQuery) :)

C’est simple et efficace, complètement transversal, facile à réutiliser… je ne suis pas mécontent de l’avoir trouvé, cette solution !

Et puis j’ai même trouvé un site qui vous permettra d’avoir le gif animé de vos rêves en quelques clics : http://www.preloaders.net/en

Gifs en 3D, circulaires, horizontaux, smiley, etc, vous trouverez tout ce qu’il vous faut, à votre (mauvais) goût !