2 librairies

Il existe 2 librairies Javascript pour intégrer un sketch Processing dans une page web : processing.js et p5.js .

Pré-requis : Dans les 2 cas, il faut importer les fichiers librairies sur le serveur et ajouter une balise <script> sur la page web pour inclure cette librairie à la page.

Comparons :

  • processing.js permet de lire directement le code d’un sketch issu de l’IDE Processing.
    Donc, pas besoin d’avoir de connaissances Javascript pour s’en sortir !
  • p5.js est une conversion complète de Processing en Javascript, donc vous allez écrire en JavaScript !
    p5.js est la version officielle reconnue par Processing, et il existe un manuel de transition.
    De plus, p5.js peut être étendu avec des bibliothèques complémentaires : p5.dom.js (pour créer et manipuler des éléments HTML : curseurs, boutons, formulaires), p5.sound.js .

Bref :  processing.js fait de la compilation à la volée tandis que p5.js fait de la traduction de code (quelques notions de Javascript seront nécessaires mais davantage de possibilités).

processing.js

Démarrer

  • Télécharger la librairie sur le site http://processingjs.org/download/  : soit la version classique processing.js (800 Ko), soit la version minimale processing.min.js (230 Ko).
  • Avec FileZilla, envoyer ce fichier sur votre site web par FTP. Par exemple : dans un répertoire /SKETCH .
  • Avec FileZilla, envoyer aussi votre sketch et les images (du dossier data) dans ce même répertoire /SKETCH .. à sa base.
    Conseil : Renommer le sketch en .txt (peu importe le nom du fichier) [ car l’extension .txt est connue et autorisée par la plupart des serveurs .. y compris par WordPress]. :
  • Construire une page Jeu1.html en incluant ces éléments :
    • une balise script pour la librairie
    • un canvas pour le visuel du sketch
    • mettre les fichiers images du sketch en PRELOAD /*@pjs : preload="image1.jpg,image2.jpg";*/
    <!DOCTYPE html>
    <html lang="fr">
     <head>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="CSS.css" />
        <title>animation</title>
        <script src="SKETCH/processing.min.js"></script>
     </head > 
     <body> 
         <p> Pour que l'image du sketch fonctionne, il faut ajouter 
             cette ligne au début du code du sketch :
             /* @pjs preload="SKETCH/ecurie.jpg"; */ 
          
             Ci-dessous le canvas sketch :
        </p>
        <canvas data-processing-sources="SKETCH/sketch_ecurie.txt"/></canvas>
     </body> 
    </html>
  • Voici un exemple de code pour sketch_ecurie.txt :
    /* @pjs preload="SKETCH/ecurie.jpg"; */ 
    PImage ecurie;
    PGraphics masque;
    int BLACK = color(0);
    
    void setup() {
      size(400, 290, P2D);
      ecurie = loadImage("SKETCH/ecurie.jpg");
      
      //On crée un masque : une image de fond noir
      masque = createGraphics(ecurie.width, ecurie.height, JAVA2D);
      masque.beginDraw();
      masque.background(0);
      masque.endDraw();
      
      //masque.loadPixels() crée un tableau de pixels masque.pixels[i]
      masque.loadPixels();
    }
    
    void draw() { 
      //dessine un rond blanc et actualise le tableau de pixels du masque
      if (mouseX != 0 && mouseY != 0) { 
        masque.beginDraw();
        masque.fill(255);
        masque.stroke(255);
        masque.ellipse(mouseX, mouseY, 50, 50);
        masque.endDraw();
        masque.loadPixels();
      }
    
      //On dessine l'image de l'écurie puis le masque
      image(ecurie, 0, 0);
      maskPixels();
    }
    
    void maskPixels() {
      //On crée un tableau de pixels du sketch : pixels[i]
      loadPixels();
    
      //si le pixel du masque est noir, alors le pixel du sketch passe au noir
      for (int i = 0; i < masque.pixels.length; i++) {
        if (masque.pixels[i] == BLACK)  pixels[i] = BLACK;
      }
      
      //On re-actualise l'affichage du sketch (l'écurie avec des pixels noirs)
      updatePixels();
    }

Les polices de caractère

C’est le CSS qui doit charger les polices de caractère :

@font-face {
    font-family: 'Coiny';
    src: url('SKETCH/Coiny-Regular.ttf');
    font-weight: normal;
    font-style: normal;
}
@font-face {
    font-family: 'Gloria';
    src: url('SKETCH/GloriaHallelujah.ttf');
    font-weight: normal;
    font-style: normal;
}

Puis on peut les utiliser directement dans le sketch :

PFont font1, font2;
void setup() {
  size(1000, 150, P2D);
  font1 = loadFont("Coiny",48); 
  font2 = loadFont("Gloria",36);
  fill(0);
  textAlign(CENTER);
} 
void draw() {
   background(#FCFCFC);
   textFont(font1);
   text("OIB",500,60);
   if (200<mouseX && mouseX<800 && 20<mouseY && mouseY<90){
    textFont(font2);
    text("Option Internationale au Baccalauréat",500,100);
  }
}

Restriction

Un bon nombre de notions de Processing n’existe pas dans processing.js

p5.js p5js

p5.js est une librairie permettant d’insérer une animation Processing sur une page web HTML, en Javascript.

Démarrer

  • Télécharger la librairie p5js « complete » (650 Ko)
    HTML_p5jsDownload
  • Décompresser le fichier obtenu « p5.zip » (clic droit > Extraire) … vous obtenez un répertoire « p5 ».
  • Avec Filezilla, il suffit de copier le contenu du dossier « empty-exemple » sur votre site WEB, c’est-à-dire : le dossier « librairies » et les 2 fichiers « index.html » et « sketch.js ».
    HTML_p5Filezilla
  • Modifier le fichier « sketch.js » pour ajouter une figure :
    function setup() {
      createCanvas(200, 200);
      fill(150); //remplissage gris
      stroke(0); //contour noir
    }
    
    function draw() {
      rect(50, 50, 80, 120);
    }
  • Ca y est … l’exemple est opérationnel, il suffit d’ouvrir votre site Web dans le navigateur … et voici un rectangle gris (l’exemple de base du sketch) !
    HTML_p5-ExempleDepart

Transition :  Processing => p5.js

Mots-clés

Quelques mots-clés de Processing changent dans p5.js :

  • size() devient  createCanvas().
  • mousePressed (la variable) devient mouseIsPressed.
  • int, float, … devient var . En fait, Javascript ne connait qu’un seul type de nombre (les float), donc pas de transtypage, pas de 200f (pour déclarer un float).
  • En plus des événements de la souris, s’ajoutent les événements tactiles qui fonctionnent de la même façon :
    • mouseX ~ touchX
    • mouseY ~ touchY
    • mousePressed() ~ touchStarted()
    • mouseDragged() ~ touchMoved()
    • mouseReleased() ~ touchEnded()
    • Il y a un tableau touches[]  qui contient la listes des coordonnées correspondant au chemin de chaque doigt.
  • pushMatrix() / popMatrix() et pushStyle() / popStyle() sont remplacés par push() et pop() (Matrix et Style sont mémorisés ensemble).

Mode Global ou Instance

Il existe 2 styles de programmation :

Mode  Global  Mode Instance
var x = 100;
var y = 100;

function setup() {
  createCanvas(200,200);
}

function draw() {
  background(0);
  fill(255);
  ellipse(x,y,50,50);
}
var sketch = function( p ) {

  var x = 100; 
  var y = 100;

  p.setup = function() {
    p.createCanvas(700, 410);
  };

  p.draw = function() {
    p.background(0);
    p.fill(255);
    p.rect(x,y,50,50);
  };
};

var myp5 = new p5(sketch);

Le mode Global nous est plus familier … mais il peut amener quelques soucis si on utilise aussi d’autres librairies Javascript dans la même page web ou plusieurs sketchs ‘Processing’ car les objets sont définis ‘globalement’ c’est-à-dire du point de vue de la page web !!! Ci-dessus, les variables x et y sont globales et si un autre sketch de cette même page web utilise aussi des variables x et y, ça va être la catastrophe !

Le mode Instance est plus sécurisant car il crée une instance du sketch (c’est myp5) et les variables x et y sont des variables internes à l’objet (donc au sketch). On travaille dans un environnement limité au sketch. Le code new p5(sketch) lance le constructeur du sketch, puis on remarque que dans function(p) chaque instruction et chaque méthode est précédée de « p. » (ex : p.background(0); ) pour que l’instruction ou la méthode ne concerne que le sketch ‘p’. (‘p’ est le nom basique du sketch dans cette fonction).

On peut aussi faire une Instance anonyme, c’est-à-dire ne pas nommer la variable sketch … c’est plus court (ça fait 2 lignes de moins) mais moins lisible. Voici, le même sketch en une instance anonyme :

var myp5 = new p5( function( p ) {
  var x = 100; 
  var y = 100;

  p.setup = function() {
    p.createCanvas(700, 410);
  };

  p.draw = function() {
    p.background(0);
    p.fill(255);
    p.rect(x,y,50,50);
  };
});

Insertion dans une page HTML.

Pour insérer l’animation dans la page web, le plus simple consiste à :

  • Créer un bloc div vide avec un identifiant id dans le code HTML (dans body) de la page : <div id='p5sketch'></div>
  • Puis construire le sketch en précisant le nom de l’identifiant en second paramètre : var myp5 = new p5(sketch,'p5sketch');

Ainsi le sketch va être créé à l’intérieur du bloc div.

<html>
<head>
  <meta charset="UTF-8">
  <script language="javascript" type="text/javascript" src="libraries/p5.js"></script>
  <script language="javascript" type="text/javascript" src="sketch.js"></script>
  <style> body {padding: 0; margin: 0;} </style>
</head>
<body>
  <h1>Mon animation Processing</h1>
  <p>Un 1er exemple :</p>
  <div id="p5sketch"></div>
  <p>... tout simplement !!!</p>
</body>
</html>
var sketch = function( p ) {
    var x = 0;
    
    p.setup = function() {
      p.createCanvas(480, 270);
      p.stroke(0); 
      p.fill(150);
      p.frameRate(10);
    };

    p.draw = function() {
      p.background(255,200,240);
      p.fill(p.random(255),p.random(255),p.random(255));
      x++;
      p.rect(x,150,20,40);
    };
};
var myp5 = new p5(sketch,"p5sketch");

HTML_p5jsExempleEmbarqué

Récupérer une variable HTML

Pour créer un curseur (dont la valeur est une variable p5.js), on a 2 méthodes pour l’insérer :

  • à l’intérieur du Canvas : dans le sketch
  • à l’extérieur du Canvas : dans un <form> HTML
    <!DOCTYPE html>
    <html>
      <head>
        <meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
        <style> body {padding: 0; margin: 0;} </style>
        <script src="../p5.min.js"></script>
        <script src="../addons/p5.dom.min.js"></script>
        <script src="../addons/p5.sound.min.js"></script>
        <script src="sketch.js"></script>
      </head>
      <body>
        <form name="form1">
          <label >Valeur de Rouge : </label>
          <input id="curseurR" type="range" min="1" max="255" value="1">
        </form>
      </body>
    </html>
    var xCentre, yCentre, r=1;
     
    function setup() {
      createCanvas(300,200);
      xCentre = width/2;
      yCentre = height/2;
    } 
     
    function draw() {
        background(0);
    
        //on récupère la veleur du curseur ayant l'id 'curseurR'
        r = select('#curseurR').value();
    
        for (var y = height ; y > 0 ; y = y-20){ 
          stroke( r , 100 , 100 );
          line ( xCentre , yCentre , 0 , y);
          stroke ( 255-r , 100 , 100 );
          line ( xCentre , y , width , y);
        }
    }

Problème : la synchro des méthodes

Comme JavaScript est « multi-tâche », c’est-à-dire qu’il démarre la construction de toutes les choses en même temps pour terminer le plus vite possible … alors l’exécution ne respecte pas vraiment l’ordre du sketch … ! Ce qui peut être très embêtant !

Exemple : changer la couleur d’un rectangle et que ce rectangle n’a pas encore été construit parce que la méthode précédente est encore en cours d’exécution !

=> Pour remédier à ces soucis, il existe des fonctions spéciales qui permettent de remettre un peu d’ordre dans la synchronisation :

  • preload : dans un sketch, on peut rajouter une fonction preload() qui sera automatiquement exécutée avant le setup() (et le setup() attendra bien la fin du preload() pour démarrer).
  • une fonction de « callback » : toutes les méthodes du sketch possèdent un argument optionnel « callback » qui est une fonction appelée qu’une fois la méthode exécutée dans sa totalité (donc vraiment finie).