Processing : afficher et modifier des images

Processing : afficher et modifier des images

Je veux pouvoir charger des images (png ou jpg en principe) et pouvoir les positionner et les dimensionner comme je le veux. Je veux aussi pouvoir les teinter comme je l’entend.

J’explore donc ici les moyens de :

  • utiliser la classe PImage ;
  • charger une image avec loadImage() et éventuellement la redimensionner ;
  • attraper une portion d’une image, avec get() ;
  • utiliser des filtres, par exemple pour mettre en noir et blanc ou en niveau de gris ;
  • Rendre l’image transparente, avec ce qui est opaque soit blanc, soit en niveaux de gris clair ;
  • donner une couleur à cette image transparente ;
  • utiliser les images comme fond (background) ou les positionner à divers endroits.

charger une image et l’afficher comme fond d’écran

Pour qu’une image puisse être utilisée comme fond d’écran, elle doit impérativement être exactement à la taille de cet écran.

Dans le sketch ci-dessous, je réalise les opérations suivantes :

Dans setup()

  1. définir la taille de l’écran, ici 720 x 540 px ;
  2. définir un mode couleur HSB (voir l’article Processing : exploration des couleurs HSB et de l’ordre des dessins)
  3. Charger une image qui s’appelle test-fond-AL-2017-12.png et se trouve sur mon ordinateur dans le répertoire “C:/Processing Scripts/Patrice 2018 04/img”
  4. redimensionner l’image pour qu’elle fasse la largeur de l’écran et la hauteur de l’écran

Dans draw(), qui s’éxécute en boucle (noter que j’aurais pu tout mettre dans setup) :

  1. Définir une couleur de remplissage en mode HSB ;
  2. définir différentes variables aléatoires
  3. tous les 50 counter (sinon ça défile trop vite)
    1. redéfinir que le fond de l’écran est constitué par l’image ;
    2. tracer un rectangle sur ce fond, de position et dimension aléatoire
    3. par dessus ce rectangle, dessiner l’image, redimensionnée pour que le rectangle soit comme un cadre.
/* tests_images --------------------- 
* V0-A 
*/

String repertoire = "c:/REPERTOIRE/img" ;      // CHANGER pour le bon répertoire !!!!
String fileFond= "test-fond-AL-2017-12.png" ;
PImage imgbkg ; 

float xpos, ypos, w, h ;
color c ;
int counter = 0 ;

void setup() {
  size(720, 540, JAVA2D); // 16/9 : 960x540 et 4/3 720*540

  colorMode(HSB, 360, 100, 100, 100);   

  // voir fichier exemple processing /images/BackgroundImage
  imgbkg = loadImage( repertoire + "/" + fileFond );
  imgbkg.resize( width, height) ;
    
}


void draw() {
  
  c = color (random(360), 70, 70, 100) ; 
  fill(c) ;
  
  w = random( 20, width / 2 ) ;
  xpos = random ( 10, width - w - 10 ) ;
  h = random( 20, height / 2 ) ;
  ypos = random (10,  height - h - 10 ) ;  

  
  if (counter % 50 == 0 ) {
    background( imgbkg ) ;
    rect( xpos, ypos, w + 10, h + 10 ) ;
    image( imgbkg, xpos + 5, ypos + 5, w, h ) ;
  }
  
  counter ++ ;
}

Et voici ce que celà donne (ici en gif) : l’image est affichée comme fond et aussi dans un encart. Dans l’encart, elle est retaillée à la taille du rectangle.

Afficher seulement une partie de l’image avec get()

get() permet de récupérer des pixels d’une l’image (cf l’aide de Processing.org) .

On peut récupérer tous les pixels, donc toute l’image ou seulement une partie.

Dans le sketch qui suit, j’utilise newimg = img.get(50, 50, w, h );  pour créer une image newimg qui correspond à un rectangle positionné en (50,50), de largeur w et de hauteur l.

J’utilise aussi c = img.get(160, 190); pour lire la couleur d’un pixel spécifique (coordonnées 160,190) de l’image img.

Processing : utilisation de PImage et get()

Processing : utilisation de PImage et get()

Cette image est produite par ce sketch :

/* tests_images --------------------- 
* V0-A 
*/

String repertoire = "c:/REPERTOIRE/img" ; // CHANGER pour le bon répertoire !!!!
String fileFond= "test-fond-AL-2017-12.png" ;
PImage img, imgbkg, newimg ; 
color c ;
int w, h ;

void setup() {
  size(720, 540, JAVA2D); // 16/9 : 960x540 et 4/3 720*540

  colorMode(HSB, 360, 100, 100, 100);   

  // l'image d'origine, sans modification
  img = loadImage( repertoire + "/" + fileFond );
  
  // une image identique mais simplement redimensionnée
  imgbkg = img ;
  imgbkg.resize( width, height) ;  
  
  // une portion de l'image d'origine
  w = int( img.width * 0.3 ) ;
  h = int( img.height * 0.8 ) ;
  newimg = img.get(50, 50, w, h );
  
  // cette couleur sera celle du pixel (160,190) de l'image img
  c = img.get(160, 190);
  
}


void draw() {

  noStroke() ;
  fill(120,70,70,100) ;
  background( imgbkg ) ;

  rect(width/10-5, height/10-5, width/2+10, height/2+10);
  image( img, width/10, height/10, width/2, height/2) ; 

  fill(c) ;  
  rect( width/10-5, height*3/4, 200, 55 ) ;

  rect( width * 6/10 + 15, height/10 - 5, w + 10, h +10 );  
  image( newimg, width * 6/10 + 20, height/10 ) ;
}

background( imgbkg ) ;  produit le fond correspondant à l’image (qui a été redimensionnée à la taille de l’écran dans le setup).

image( img, width/10, height/10, width/2, height/2) ;  produit l’image encadrée de vert, en haut de la moitié gauche de l’écran.

fill(c) ;   et  rect( width/10-5, height*3/4, 200, 55 ) ;  produisent le rectangle de couleur rose. La couleur rose a été extraite du pixel de coordonnées  (160,190) de l’image par la commande c = img.get(160, 190);  dans setup().

Enfin image( newimg, width * 6/10 + 20, height/10 ) ; produit l’image à droite, c’est une portion de l’image d’origine. Elle a été obtenue par la commande newimg = img.get(50, 50, w, h );  dans setup().

tint, filter, pixel

Pour ce qui suit, je me suis aidée des informations du site processing.org et de deux pages d’un tutoriel, en anglais, sur la gestion des images avec Processing : cette page sur la teinte des images et cette page sur les filtres de transformation. Quant à l’image d’une oeuvre de Kandinsky, elle provient aussi de ces tutoriels. On peut la télécharger ici.

explication des différentes images obtenues

Le sketch qui suit illustre différentes possibilités de traitement d’une même image. Toutes ces possibilités sont visualisées sur un même écran de Processing :

Processing : utilisation de PImage et filter()

Processing : utilisation de PImage et filter()

Processing : utilisation de PImage et filter() - Positions

J’appelle A à D les lignes, 1 à 5 les colonnes et les différentes images correspondent à :

  • A1 l’image telle quelle, redimensionnée ;
  • A2 l’image avec une transparence ;
  • A3 un rectangle de couleur mauve qui est utilisée ensuite pour teinter des images ;
  • B1 l’image source passée en noir et blanc avec le filtre filter(THRESHOLD, 0.5)
  • B2 l’image précédente inversée avec le filtre filter(INVERT)
  • B3 l’image inversée teintée avec avec le filtre tint(196,85,189, 255);  (un mauve) puis tint(255, 255);  qui remet la teinte à neutre (pas de teinte, pas de transparence)
  • B4 l’image inversée passée dans une « moulinette » qui transforme tous les pixels noirs en pixels noirs et transparents. On a alors uniquement les pixels blancs qui sont visibles lors de l’affichage
  • B5 l’image inversée et transparente de B4 est tintée en mauve.
  • Les différentes colonnes de la ligne C sont les mêmes qu’en ligne B sauf qu’au départ on met l’image en niveau de gris avec le filtre filter(GRAY)  .  La “moulinette” pour transformer en image transparente est différente.
  • En ligne D, on observe deux images transparentes. La première en D1 est le résultat d’une fonction créée dans le sketch, pour les images en noir et blanc. La deuxième, en D3 est une autre fonction qui passe en niveaux de gris.  Ces deux fonctions font la même chose que ce qui est réalisé de manière décomposée en lignes B et C.

Le code complet pour obtenir ce résultat est le suivant (attention ne pas oublier de placer l’image kandinsky dans le répertoire data du script) :

/* tests_images --------------------- 
* Source http://www.cs.sfu.ca/CourseCentral/166/tjd/using_images.html
* et     http://www.cs.sfu.ca/CourseCentral/166/tjd/image_tint.html
* kandinsky.jpg utilisée http://www.cs.sfu.ca/CourseCentral/166/tjd/_downloads/kandinsky.jpg

*
* résultat = image img-img-filter-3.png
*/

PImage img ;
PImage imgBw, imgBwInvert, imgBwTransp ; 
PImage imgGrey, imgGreyInvert, imgGreyTransp ; 
PImage testBW, testGrey ;

int w, h ;
int xpos, ypos, interval ;


void setup() {
  // load the image file from the "data" folder
  img = loadImage("kandinsky.jpg");

  // set the window to be the same dimensions as the image
  size(1098, 757);  

  // l'image devient noir et blanc
  imgBw = img.get() ; // a copy of original
  imgBw.filter(THRESHOLD, 0.5);
  
  // L'image noir et blanc est inversée
  imgBwInvert =  img.get() ; // a copy of original
  imgBwInvert.filter(THRESHOLD, 0.5);
  imgBwInvert.filter(INVERT) ;
  
  // créer une image transparente à partir de imgBwInvert
  /*
  * https://forum.processing.org/one/topic/turn-white-pixels-transparent.html
  */
  int x, y , i ; // pour lire les pixels
  imgBwTransp = createImage( imgBwInvert.width, imgBwInvert.height, ARGB );
  
  for( x = 0; x < imgBwInvert.width; x++ ){
    for( y = 0; y < imgBwInvert.height; y++ ){
      i = ( ( y * imgBwInvert.width ) + x );
      if( imgBwInvert.pixels[i] == color( 0, 0, 0 ) ){
        // pixel noir devient transparent
        imgBwTransp.pixels[i] = color( 0, 0, 0, 0 );
      } 
      else {
        // autre couleur reste en l'état
        imgBwTransp.pixels[i] = imgBwInvert.pixels[i];
      }
    }
  }
  
  
  

  // l'image devient en grey scale
  imgGrey = img.get() ; // a copy of original
  imgGrey.filter(GRAY);
  
  // L'image grise est inversée
  imgGreyInvert = img.get() ; // a copy of original
  imgGreyInvert.filter(GRAY);
  imgGreyInvert.filter(INVERT) ;

  // créer une image transparente à partir de imgGreyInvert
  /*
  * https://forum.processing.org/one/topic/turn-white-pixels-transparent.html
  * avec des ajustements pour conserver les niveaux de gris
  */

  imgGreyTransp = createImage( imgGreyInvert.width, imgGreyInvert.height, ARGB );
  float red , green , blue, alpha ;
  boolean lightGrey = false ;
  
  for( x = 0; x < imgGreyInvert.width; x++ ){
    
    for( y = 0; y < imgGreyInvert.height; y++ ){

      i = ( ( y * imgGreyInvert.width ) + x );
      
      red = red(imgGreyInvert.pixels[i]) ;
      green = green(imgGreyInvert.pixels[i]) ;
      blue = blue(imgGreyInvert.pixels[i]) ;
      alpha = alpha(imgGreyInvert.pixels[i]) ;
      
      if ( red < 150 ) {
        
        if ( ( red == green ) && ( red == blue ) ) {
        
          lightGrey = true ;
        
        } 
        
      } else if (red >= 150)  {      
          
        // it's either not grey or it's dark grey
        lightGrey = false ;
      }

      if( !lightGrey ){
        
        // dark grey turned to same color without transparency
        imgGreyTransp.pixels[i] = color( red, green, blue, 255 );
      } 
      else {
        // la couleur est transformée en noire transparent
        imgGreyTransp.pixels[i] = color( 0, 0, 0, 0 );
      }
    }
  }

  // utiliser la fonction pour rendre transparente et blanche une image
  testBW = img.get() ; // a copy of original  
  testBW = fnbwTransp(testBW) ;

  // utiliser la fonction pour rendre transparente et en niveau de gris clair une image
  testGrey = img.get() ; // a copy of original  
  testGrey = fnGreyTransp(testGrey) ;
  
  
  // pour positionner et dimensionner les images
  w = width / 6 ;
  h = height / 5 ;
  interval = 20 ;
  xpos = interval ;
  ypos = interval ;
}

void draw() {
  
  background(img) ;

  // ----------------------------------- LIGNE 1 -----
  ypos = interval ;
  // l'image d'origine en petite taille
  xpos = interval ;
  image(img, xpos, ypos, w, h);  

  // ne change pas la couleur mais met de la transparence
  tint(255, 126);
  xpos =  2 * interval + w ;
  image(img, xpos, ypos, w, h);  
  // remet la couleur et la transparence normale
  tint(255, 255);

  // pour avoir une idée de la couleur de tint
  fill (196,85,189, 255); // un mauve 
  xpos =  3 * interval + 2 * w ;
  rect (   xpos, ypos, w, h );  

  xpos =   4 * interval + 3 * w ;


  // ----------------------------------- LIGNE 2 -----
  ypos = 2 * interval + h ;
  
  // les images noir et blanc

  xpos =  interval ;
  image(imgBw, xpos, ypos, w, h);  
  xpos =  2 * interval + w ;
  image(imgBwInvert, xpos, ypos, w, h);  
  // colorer l'image
  tint(196,85,189, 255); // un mauve 
  xpos =  3 * interval + 2 * w ;
  image(imgBwInvert, xpos, ypos, w, h);  
  // remet la couleur et la transparence normale
  tint(255, 255);
  
  xpos =  4 * interval + 3 * w ;
  image(imgBwTransp, xpos, ypos, w, h);  

  // colorer l'image transparente
  tint(196,85,189, 255); // un mauve 
  xpos =  5 * interval + 4 * w ;
  image(imgBwTransp, xpos, ypos, w, h);  
  // remet la couleur et la transparence normale
  tint(255, 255);  
  
  // ----------------------------------- LIGNE 3 -----
  // les images grises
  xpos =  interval ;
  ypos = 3 * interval + 2 * h ;
  image(imgGrey, xpos, ypos, w, h);  
  xpos =  2 * interval + w ;
  image(imgGreyInvert, xpos, ypos, w, h); 
  // ne change pas la couleur mais met de la transparence
  tint(255, 126);
  xpos =  3 * interval + 2 * w ;
  // colorer l'image
  tint(196,85,189, 255); // un mauve 
  image(imgGreyInvert, xpos, ypos, w, h);  
  // remet la couleur et la transparence normale
  tint(255, 255);  
  
  xpos =  4 * interval + 3 * w ;
  image(imgGreyTransp, xpos, ypos, w, h);  

  // colorer l'image transparente
  tint(196,85,189, 255); // un mauve 
  xpos =  5 * interval + 4 * w ;
  image(imgGreyTransp, xpos, ypos, w, h);  
  // remet la couleur et la transparence normale
  tint(255, 255);  
  
  // ----------------------------------- LIGNE 4 -----
  ypos = 4 * interval + 3 * h ;
  
  // via les fonctions
  xpos =  interval ;
  image(testBW, xpos, ypos, w, h);  

  xpos =  3 * interval + 2 * w ;
  image(testGrey, xpos, ypos, w, h);  

}

PImage fnbwTransp( PImage img ) {
  
  PImage result ; 
  
  img.filter(THRESHOLD, 0.5);    // now black & white
  img.filter(INVERT) ;      // black becomes white and white becomes black

  // source https://forum.processing.org/one/topic/turn-white-pixels-transparent.html    
  int x, y , i ; // pour lire les pixels  

  // must be ARGB so that transparency may be added
  result = createImage( img.width, img.height, ARGB ); 

    for( x = 0; x < img.width; x++ ){
    for( y = 0; y < img.height; y++ ){
      i = ( ( y * img.width ) + x );
      if( img.pixels[i] == color( 0, 0, 0 ) ){
      // pixel noir devient transparent
      result.pixels[i] = color( 0, 0, 0, 0 );
      } 
      else {
      // autre couleur reste en l'état
      result.pixels[i] = img.pixels[i];
      }
    }
    }

  return result ; // une image blanche avec tout le reste transparent
  
}


/*
* fonction pour retourner une image avec niveaux de gris clair transparente
* on peut ensuite la teinter comme on veut
*/

PImage fnGreyTransp( PImage img ) {
  
  PImage result = createImage( img.width, img.height, ARGB ); 
  
  img.filter(GRAY);    // now grey scale (niveau de gris)
  img.filter(INVERT) ;  // black becomes white and white becomes black

  // source https://forum.processing.org/one/topic/turn-white-pixels-transparent.html  
  //  avec des ajustements pour conserver les niveaux de gris
  
  int x, y , i ; // pour lire les pixels  
  float red , green , blue,  alpha  ;
  boolean lightGrey = false ;
  
  for( x = 0; x < img.width; x++ ){
    
    for( y = 0; y < img.height; y++ ){

      i = ( ( y * img.width ) + x );
      
      red = red(img.pixels[i]) ;
      green = green(img.pixels[i]) ;
      blue = blue(img.pixels[i]) ;
      // alpha = alpha(img.pixels[i]) ;
      
      if ( red < 150 ) {
      
        if ( ( red == green ) && ( red == blue ) ) {
      
          lightGrey = true ;
      
        } 
      
      } else if (red >= 150)  {      
        
        // it's either not grey or it's dark grey
        lightGrey = false ;
      }

      if( !lightGrey ){
      
        // dark grey turned to same color without transparency
        result.pixels[i] = color( red, green, blue, 255 );
      } else {
        // la couleur est transformée en noire transparent
        result.pixels[i] = color( 0, 0, 0, 0 );
      }
    }
  }

  return result ; // une image blanche avec tout le reste transparent
  
}

Aparté théorique sur la notion de “niveau de gris”

Lorsqu’on parle de niveau de gris, on a une couleur qui a deux caractéristiques :

  • les valeurs de R, G et B sont identiques ;
  • le niveau correspond au ratio entre la valeur de R (ou G ou B) et 256 : R = 126 correspond à un niveau de gris de 50%.

Pour une couleur (obtenue par exemple avec c = img.get(160, 190);  comme précédemment), on peut savoir quelle sont les valeurs de rouge, vert et bleu, et même transparence, avec les fonctions respectivement red(), green(c), blue(c), alpha(c).

Ce sont ces caractéristiques qu’on utilise pour rendre une image teintable, avec nuances.

Rendre une image teintable et transparente

C’est réalisé avec la fonction fnbwTransp. Cette fonction est réalisée sur une image PImage img et renvoie une PImage puisqu’elle est définie comme PImage fnbwTransp( PImage img ) {} .

La “moulinette” qui transforme les pixels noirs en pixels transparents est inspirée d’une discussion sur le forum processing.  L’idée générale en est la suivante :

  • on crée une image vide appelée result, de dimensions celles de img (notre source) et au format ARGB, donc avec prise en compte de la transparence Alpha. Cette image est créée avec result = createImage( img.width, img.height, ARGB );
  • on balaie l’image source, img, pixel par pixel.
    • Si la couleur du pixel est noir – color( 0, 0, 0 )  – alors la couleur du pixel correspondant dans l’image result est  color( 0, 0, 0, 0 )  – noir aussi mais transparent.
    • Si la couleur du pixel n’est pas le noir, alors la couleur du du pixel correspondant dans l’image result est la couleur du pixel d’origine de img.

La fonction retourne l’image résultante, une image dont tous les pixels noirs sont devenus transparents.

Rendre une image teintable, avec nuances, et transprente

On utilise là la fonction fnGreyTransp. Elle est semblable à fnbwTransp mais elle gère des niveaux d’intensité de la couleur. On utilise le même principe que dans fnbwTransp  mais la différence est dans les décisions lors du balayage des pixels d’img :

  • si le niveau de rouge est inférieur à 150 (on a un gris variant de très clair à assez clair)
    • si rouge = vert = bleu, alors on est en niveau de gris et  lightGrey = true  ;
  • si le niveau de rouge est > 150 ou bien rouge n’est pas identique à vert et bleu, alors   lightGrey = false  ;

Et ensuite on a deux possibilités :

  • si   lightGrey = true , alors le pixel correspondant de result est noir et totalement transparent (valeur 0 de transparence)
  • si   lightGrey = false , alors on donne au pixel correspondant de result l’exacte valeur de la couleur du pixel de img, avec une transparence nulle (valeur 255 de transparence).

Et maintenant !?

J’aimerais bien faire la même chose en p5.js pour avoir des sketch plus facilement présentables en ligne.

Mais avant, je vais probablement explorer la gestion des couches avec PGraphics, et aussi des masques, avec mask().

Un “color picker” dans les réglages de notre extension WordPress

Un “color picker” dans les réglages de notre extension WordPress

Nous allons améliorer la page de réglage de notre extension WordPress, en y ajoutant un champ de type “color picker” et en affichant les données complémentaires définies avec les champs. Dans les articles précédents de cette série (), nous avons progressivement construit l’extension et sa page de réglage. A la fin du précédent article, l’extension correspondait au contenu de ce fichier zip : clea-add-button avec éditeur wp_editor (zip).

Que voulons-nous faire ?

Notre page de réglages est capable d’afficher tous les types de champs sauf les choix de couleur. Nous voulons donc pouvoir choisir une couleur et même définir son opacité. Et pour simplifier la vie de l’administrateur du site, il faut qu’on lui dise quelles sont les couleurs utilisées par son thème, en les intégrant dans une palette sous le color picker.

Par ailleurs, notre page de réglages devra afficher les éléments complémentaires définis pour chaque champs, tels que “helper” qui contient un texte d’aide complémentaire.

Identifier les couleurs utilisées par le site

Les paramètres du thème courant sont stockés par WordPress et récupérables avec la fonction get_theme_mods(). Cette fonction nous donne un array contenant tous les paramètres, dont certains sont des couleurs.

Nous lisons donc l’array et pour chaque valeur, nous regardons s’il s’agit d’une couleur avec la fonction sanitize_hex_color_no_hash(). Cette fonction renvoie “NULL” si elle ne trouve pas un élément en hexadécimal à 3 ou 6 caractères. A chaque fois qu’elle trouve un élément non NULL, on le place dans l’array qui sera retourné pour former notre palette de couleurs.

/**********************************************************************

* find the colors used in the website's theme

**********************************************************************/
function clea_presentation_get_current_colors() {

	// to get all the current theme data in an array
	$mods = get_theme_mods();

	$color = array() ;
	
	foreach ( $mods as $key => $values ) {
		
		if ( !is_array( $values ) ) {
			
			if ( is_string( $values ) && trim( $values ) != '' ) {
				
				$hex = sanitize_hex_color_no_hash( $values ) ;
				
				if ( trim( $hex ) != '' ) {
					
					$color[ $key ] = $hex ;

				}

			}
		} 
	}

	// remove duplicate colors
	$current_colors = array_unique( $current_colors ) ;
	
	return $color ;
	
}

Pour vérifier que c’est une bonne solution, , nous ajoutons le code suivant à la fonction clea_add_button_options_page()   :

$colors = clea_add_button_get_current_colors() ;
echo "<hr /><p>Arguments</p><pre>";
print_r( $colors ) ;	
echo "</pre><hr />";

Ce code va afficher l’array de couleurs en bas de la page d’options :

Array
(
   [background_color] => ffffff
   [color_palette_primary] => 4c858d
   [color_palette_tertiary] => 423432
   [color_palette_dark_font] => ed693b
)

Nous disposons donc des informations pour constituer notre palette par défaut.

Afficher des champs “color picker”

Nous allons utiliser le “Alpha Color Picker for WordPress” développé par Braad Martin. Pour comprendre comment l’intégrer, j’ai utilisé à la fois les explications de Braad Martin et Add an Alpha RGBa Color Picker to a WordPress Plugin Input Field.

Le code pour afficher le color picker

On ajoute le cas ‘color’ comme suit :

case 'color' :

	// get the colors used by the theme
	$current_colors = clea_presentation_get_current_colors() ;
	$data_palette = "";
	
	// the color palette must be a string with colors and | separator
	// "#222|#444|#00CC22|rgba(72,168,42,0.4)" would be ok
	foreach ( $current_colors as $color ) {
		
		$data_palette .= $color . '|' ;
		
	}
	
	$data_palette = rtrim( $data_palette, '|' ) ;
	
	
	// uses https://github.com/BraadMartin/components/tree/master/alpha-color-picker
	printf( '<input type="text" class="alpha-color-picker" name="%2$s" value="%1$s" data-palette="%5$s" data-default-color="%4$s" data-show-opacity="true" />', sanitize_text_field( $value ), $name, $field, $arguments['default'], $data_palette  ) ;
	break ;	

A ce stade, celà affiche un champs de type ‘text’ avec à l’intérieur la couleur par défaut définie dans le champs. Il nous faut maintenant ajouter la feuille de style et le programme javascript conçus par le créateur de l’Alpha color Picker et un petit script en JQuery.

Les compléments à intégrer dans notre extension

Dans le répertoire “/admin” du plugin, créer les sous-répertoires “/css ” et “/js “.

Télécharger le fichier zip du dépôt “components” de Braad Martin ici sur un PC. Décompresser le fichier zip puis dans le sous-répertoire “alpha-color-picker” copier alpha-color-picker.css   et alpha-color-picker.js  respectivement dans les répertoires /admin/css  et /admin/js  de l’extension.

Les fichiers à créer

Nous devons créer deux fichiers :

  • un fichier (clea-add-button-color-trigger.js par exemple) qui contiendra le JQuery nécessaire à l’affichage
  • un fichier (clea-add-button-admin-enqueue.php par exemple) qui sera appelé par le fichier principal de l’extension et qui chargera la feuille de style et les scripts JavaScript nécessaires.

Le fichier /admin/js/clea-add-button-color-trigger.js  contient :

// source  https://github.com/BraadMartin/components/tree/master/alpha-color-picker
jQuery( document ).ready( function( $ ) {
    $( 'input.alpha-color-picker' ).alphaColorPicker();
});

Quant au fichier /admin/js/clea-add-button-admin-enqueue.php , il contient

add_action( 'admin_enqueue_scripts',  'clea_add_button_admin_enqueue_scripts' );


function clea_add_button_admin_enqueue_scripts( $hook ) {
	

	// to find the right name, go to the settings page and inspect it
	// the name is somewhere in the <body class="">
	// it will always begin with settings_page_
	if( 'settings_page_my-plugin' != $hook ) { 
	
        // echo "not the right page, this is : " ;
		// echo $hook ;
		return;
		
    }

    // for the alpha color picker
    // source : https://github.com/BraadMartin/components/tree/master/alpha-color-picker
    wp_enqueue_style(
        'alpha-color-picker',
        CLEA_ADD_BUTTON_DIR_URL . '/admin/css/alpha-color-picker.css', 
        array( 'wp-color-picker' ) // You must include these here.
    );

	wp_enqueue_script(
        'alpha-color-picker',
        CLEA_ADD_BUTTON_DIR_URL . '/admin/js/alpha-color-picker.js', 
        array( 'jquery', 'wp-color-picker' ), // You must include these here.
        null,
        true
    );
	
    // This is the JS file that will contain the trigger script.
    // Set alpha-color-picker as a dependency here.
    wp_enqueue_script(
        'clea-add-button-admin-color-js',
        CLEA_ADD_BUTTON_DIR_URL . '/admin/js/clea-add-button-color-trigger.js', 
        array( 'alpha-color-picker' ),
        null,
        true
    );
	
}

La condition if( ‘settings_page_my-plugin’ != $hook ) permet de ne pas charger le style et le JavaScript si on n’est pas sur la page d’options de notre extension.

Enfin, dans clea-add-button.php , nous ajoutons la ligne qui démarrera clea-add-button-admin-enqueue.php   :

// load styles and scripts for the admin
require_once CLEA_ADD_BUTTON_DIR_PATH . 'admin/clea-add-button-admin-enqueue.php';

le résultat

Notre page d’option affiche maintenant la couleur par défaut sous une forme différente :

Le champ "color" affiche bien une couleur maintenant.

Le champ “color” affiche bien une couleur maintenant.

Si on clique sur la couleur, un “color picker” s’ouvre. Il affiche la couleur par défaut définie dans le champ 3. On observe qu’il y a une palette de couleur en dessous, qui correspond effectivement aux couleurs du thème sur lequel j’essaie cette extension. Et en dessous, on voit une barre qui permet de gérer la transparence de la couleur choisie.

Le champ "color" affiche un "color picker" complet.

Le champ “color” affiche un “color picker” complet.

Ici nous sélectionnons la couleur orange du thème et nous demandons à ce que sa transparence soit 71%.

Choix d'une couleur de la palette puis réglage de la transparence

Choix d’une couleur de la palette puis réglage de la transparence

Ca fonctionne parfaitement et la nouvelle couleur s’enregistre correctement.

Afficher les informations complémentaires

Chaque champ affiché dans notre page d’options est défini par un array :

array(
	'field_id' 		=> 'field-2-3', 
	'label'			=> __( 'Field three : color', 'clea-add-button' ), 
	'field_callbk'	        => 'clea_add_button_settings_field_callback', 
	'menu_slug'		=> 'my-plugin', 
	'section_name'	        => 'section-2',
	'type'			=> 'color',
	'helper'		=> __( 'help 2-3', 'clea-presentation' ),
	'default'		=> 'rgba(0,0,0,0.85)'			
)

Nous utilisons toutes les clés de cet array sauf deux (‘label’ et ‘helper’). Ces deux clés contiennent respectivement le texte à afficher systématiquement pour expliciter ce qu’il faut faire et un texte d’aide complémentaire.

Pour l’afficher, avant le champs à remplir, j’ajoute le code suivant dans la fonction clea_add_button_settings_field_callback( $arguments  )  :

// If there is a help text and / or description
printf( '<span class="field_desc">' ) ;

if( isset( $arguments['helper'] ) && $helper = $arguments['helper'] ){
	printf( '<img src="%1$s/images/question-mark.png" class="alignleft" id="helper" alt="help" title="%2$s" data-pin-nopin="true">',CLEA_ADD_BUTTON_DIR_URL, $helper ) ;
}

// If there is a description
if( isset( $arguments['label'] ) && $description = $arguments['label'] ){
	printf( ' %s', $description ); // Show it
}

printf( '</span>' ) ;

La condition if( isset( $arguments[‘helper’] ) && $helper = $arguments[‘helper’] )  vérifie que $arguments[‘helper’] est défini ET qu’il n’est pas vide.

J’ai placé un fichier question-mark.png dans le répertoire /images de l’extension.

Le résultat n’est pas très joli :

Pages d'option pas très belle....

Il faut donc que j’ajoute une feuille de style pour améliorer la page d’options.

Créer une feuille de style pour la page d’options

Dans le fichier /admin/js/clea-add-button-admin-enqueue.php , nous ajoutons une ligne pour charger la feuille de style de notre page de réglages :

// options page style
wp_enqueue_style(
	'clea-add-button-admin-style',
	CLEA_ADD_BUTTON_DIR_URL . '/admin/css/clea-add-button-admin.css'
);

et dans le fichier /admin/css/clea-add-button-admin.css

/**
 * Settings page (admin)
 */
 
span.field_desc {
	display: block;
	font-style: italic;
	margin-bottom: 5px;
}

img#helper {
	margin-right: 5px;
}

Le résultat est lisible maintenant :

Page de réglage de l'extension avec feuille de style

Et maintenant ?

A ce stade notre extension correspond au contenu de ce fichier zip : clea-add-button V0.2 (zip).

Notre page de réglages fonctionne. Il ne reste plus que quelques améliorations à apporter. Ce sera l’objet du prochain article de cette série, .