Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox



L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

Fabriquer un coloriage : couleur et ColorPicker

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Par Nataly, le 08 août 2011

Une carte à colorier c'est une vingtaine de lignes de code, pas plus, et pourtant ça en arrête plus d'un. Probablement parce que ça met en œuvre des classes d'utilité ponctuelle et une vague ruse quant à l'écoute d'événement…
Je dis ruse pour vous allécher, mais il s'agit d'une technique tout à fait conventionnelle ;)

Ce tuto se propose donc avec l'alibi d'une carte à colorier de

• mettre en œuvre la classe ColorTransform
• faire connaissance avec le composant ColorPicker
• illustrer l'intérêt de la phase de capture dans l'écoute d'événements
• accessoirement apporter réponse à une question souvent croisée sur le forum : comment fabriquer un coloriage… ;-)

Puisqu'il s'agit ici de couleur, autant que RVB vous dise quelque chose et que vous sachiez reconnaitre et assigner une couleur via l'environnement de création Flash.
Pour le reste une pratique courante de AS3 suffira : syntaxe, événements, variables… rien que de très basique :)


POU1) :
Affin d'alléger le discours j'aurai recours à l'abus de langage qui consiste à parler de clip en lieu et place d'instance de symbole, mais vous n'êtes pas dupes : dans la bibliothèque, des symboles ; sur l'animation, des instances (ou occurrences). Ce sont ces instances qu'on manipule et que j'appelle clip quand il s'agit d'une occurrence de symbole de type Clip.
Conventions d'écriture :
Je précise entre crochets les raccourcis clavier. Utilisateurs de PC remplacez cmd par ctrl.

La classe ColorTransform, rappels

Utiliser la classe ColorTransform c'est, vous le savez, l'équivalent codé de ce qu'on obtient en manipulant la liste couleur du panneau propriétés.



Et dans l'exemple qui nous préoccupe, c'est l'option Teinte que nous aurions manipulée, puisque il s'agit d'appliquer une couleur unie à chacun des clips composant l'image.



Pour changer la couleur d'un pétale - par exemple - depuis l'environnement création de Flash, on sélectionnerait le clip et via le panneau propriétés on appliquerait une teinte à 100%.

Appliquer une teinte


Appliquer une teinte, en code, c'est :
fabriquer une teinte avec la classe ColorTransform et sa propriété color
• puis l'appliquer en passant par les propriétés transform et colorTransform.

Par exemple, en imaginant un clip nommé fleur, pour lui appliquer une teinte unie verte on écrirait :

// un Objet ColorTransform
var coulVert:ColorTransform= new ColorTransform();
coulVert.color=0x00FF00; // on précise une couleur 
// on applique la couleur
fleur.transform.colorTransform=coulVert;

Restituer la teinte d'origine

Retrouver la teinte d'origine - rien donc - c'est appliquer, toujours via transform.colorTransform, une “non-teinte” :

// un Objet colorTransform "vierge"
var coulSans:ColorTransform= new ColorTransform();
// on applique la non couleur
fleur.transform.colorTransform=coulSans;


Pas plus, pas moins. Ce n'est pas plus compliqué que ça :)

Le composant ColorPicker


Nous approchons de l'objectif à grands pas. S'il s'agissait d'appliquer la toujours même couleur aux différents clips composant le coloriage, on y serait déjà.
Reste à proposer une palette de couleurs.

Flash, dans sa grande générosité nous fournit le composant dédié : ColorPicker.

• Affichez le panneau Composants (Menu Fenêtres ou [cmd-F7])
• Glissez le ColorPicker sur la scène, le symbole correspondant sera automatiquement ajouté à la bibliothèque.
• Nommez l'instance comme il vous convient (pour moi ce sera cp comme colorPicker ;)).




Nous voilà prêts à faire connaissance avec cette petite merveille de composant !

Propriété selectedColor

La première des choses qu'on attend d'une palette c'est connaitre le choix de l'utilisateur…
En français on parlerait de la couleur sélectionnée, on trouve donc sans surprise une propriété selectedColor en lecture écriture. On va pouvoir aussi bien lire la couleur sélectionnée par l'utilisateur que forcer le composant à afficher une couleur de notre choix, ce qui est utile à l'initialisation si on souhaite que soit affiché autre-chose que le noir par défaut.

Vous pouvez régler cette couleur de départ, directement via l'interface en utilisant l'inspecteur de composants.
Sous CS3 vous devez passer par le menu Fenêtre. Sous CS4 et suivants un bouton vous y donne accès directement depuis le panneau propriétés :


Initialiser le composant en code nous donnerait donc (pour rouge) :

cp.selectedColor=0xFF0000;


Ce qui est d'utilité plus courante, c'est lire la couleur sélectionnée.

Pour appliquer à un clip une teinte unie telle que choisie via un un composant ColorPicker, il suffit donc de valoriser la propriété color d'un objet ColorTransform avec ce que renvoie la propriété selectedColor du composant :

// un Objet ColorTransform
var coul_c:ColorTransform= new ColorTransform();
//lire la couleur sélectionnée
coul_c.color=cp.selectedColor;
// appliquer la couleur
fleur.transform.colorTransform=coul_c;


L'événement CHANGE


Le plus souvent on utilise la couleur choisie aussitôt la sélection effectuée. Il s'agit donc d'écouter l'événement idoine. C'est l'événement CHANGE de la classe ColorPickerEvent.

// importation requise
import fl.events.ColorPickerEvent;
 
cp.addEventListener(ColorPickerEvent.CHANGE, appliqueModif);
function appliqueModif(e:ColorPickerEvent) {
 
	trace("Valeur hexa : "+e.target.hexValue);
	trace("Valeur  (uint) "+ e.color);
 
   var coul_c:ColorTransform= new ColorTransform();
   coul_c.color=e.target.selectedColor;
   fleur.transform.colorTransform=coul_c;
}


Notez au passage la propriété hexValue qui vous donne la valeur hexadécimale de la couleur sélectionnée du composant.

Ne confondez pas la propriété hexValue du composant et la propriété color de l'événement, qui elle, renvoie la couleur en uint

Autres méthodes et propriétés parfois utiles

Histoire de finir de faire le tour du propriétaire, sachez que vous pouvez modifier les dimensions du composant via la méthode setSize (héritée de UIComposant) qui admet deux paramètres : largeur, hauteur. A votre disposition aussi les width et height qui nous sont familiers

cp.setSize(cp.width+=10,cp.height+=10);



Vous pouvez afficher ou non le champ texte du composant qui donne la valeur hexadécimale de la couleur sélectionnée. C'est une propriété booléenne : showTextField.

// Le champ texte n'est pas affiché
cp.showTextField = false;


Enfin, sachez que vous pouvez afficher ou masquer la palette des couleur à l'aide des méthodes open et close.

// le composant est affiché ouvert avec une largeur de 100 et une hauteur de 50
cp.setSize(100,50);
cp.selectedColor=0xFF0000;
cp.open();



Une palette aux couleurs personnalisée

Par défaut ColorPicker propose 216 couleurs mais on peut faire ce qui nous chante (dans la limite de 1024 couleurs).
C'est la propriété colors qui permet de définir un choix de couleurs personnalisée.

Attention colors avec un s !
Ne confondez pas avec color - sans s - propriété de l'objet ColorTransform

colors renvoie et définit un tableau des couleurs affichées par le composant. Pour proposer seulement rouge vert et bleu on écrirait par exemple :

cp.colors=[0xFF0000,0x00FF00,0x0000FF];


Pour afficher cette palette ouverte :



var lesCouleurs:Array=[0xFF0000,0x00FF00,0x0000FF]
cp.colors=lesCouleurs;
cp.showTextField=false;
cp.setSize(20,50);
cp.open();

Pour ajouter une ou plusieurs couleurs à la palette existante utilisez tout bonnement la méthode push.

cp.colors.push(0xCCCCCC);
cp.colors=cp.colors.push(0xAAAAAA,0xCCCCCC,0xEEEEEE);


De toutes façons puisque colors renvoie un tableau, si vous savez manipuler un tableau, vous en ferez ce que vous voudrez ;)

Monsieur Plus

Si vous preniez goût à l'utilisation de ce composant, sachez qu'on peut intervenir sur sur son aspect (dimensions des cases de couleur et autre nombre de colonnes de la palette) via la méthode setStyle.
Vous en trouverez la liste à l'entrée Style.

L"extension Adobe Flash Plugin est nécessaire pour afficher ce contenu.

import fl.events.ColorPickerEvent;
import fl.controls.ColorPicker;
 
// un dictionnaire pour stocker les correspondances valeur/nom
var corres:Dictionary= new Dictionary();
corres[0xE67E30] = "Abricot";
corres[0xAD390E] = "Aquilain";
corres[0xAE642D] = "Baillet";
 
 
var cp:ColorPicker = new ColorPicker  ;
cp.x = cp.y = 10;
 
cp.setSize(30,50); // dimensions du bouton
cp.colors = [0xE67E30,0xAD390E,0xAE642D];// trois couleurs
cp.selectedColor = 0xE67E30;             // couleur de départ
cp.setStyle("swatchWidth", 30);          // largeur des nuanciers
cp.setStyle("swatchHeight", 50);         // hauteur des nuanciers      
 
 
cp.addEventListener(Event.OPEN, init);   // écrire la couleur d'init ds le chp texte
cp.addEventListener(ColorPickerEvent.ITEM_ROLL_OVER,majChamp); // afficher le nom de la couleur
 
addChild(cp);
 
// - - - - - Rappels - - - - - - - - - - - -
function majChamp(ce:ColorPickerEvent) {
	ce.target.textField.text = corres[ce.color];
}
 
function init(e:Event) {
// une fois seulement
	ColorPicker(e.target).textField.text = "Abricot";
// suprimer l'écouteur
	ColorPicker(e.target).removeEventListener(Event.OPEN, init);
}

A titre de démo et sans plus de détail… ;)

Coloriage, c'est parti !

Cette fois on y est, vous avez tout ce qu'il faut pour réaliser le coloriage proposé.

Construction graphique


Le “dessin” lui même est un bête clip composé de plusieurs occurrences de symboles que j'utilise comme les gommettes de mon enfance. Vous pouvez être plus courageux et vous déchirer d'un vrai beau dessin, la seule chose qui importe c'est que chaque élément coloriable soit un clip (dans l'idée de lui “appliquer une teinte” via colorTransform).


Vous l'avez constaté : le propre de la “teinte” - propriété color d'un objet ColorTransform - c'est de tout barbouiller d'une couche unie, plus de nuances ni de contours. Le moyen de contourner le problème pour, dans l'exemple qui nous occupe, conserver un liseré noir autour des pétales des fleurs c'est tout bonnement de tricher d'un ou plusieurs calque(s) dédié(s) qui ne porteront que des bordures et qui sont “par dessus” les objets colorisés.


Ne vous compliquez pas trop pour obtenir ce résultat :
• sélectionner l'ensemble des clips dont on veut conserver le contour,
• copier [cmd-C],
• coller en place sur le calque dédié [cmd-maj-V],
• tout sélectionner [cmd-A],
• séparer [cmd-B],
• sélectionner et virer les remplissages (pff… pas de raccourcis :(/;)),


Code


Le code, on est d'accord que c'est tout benêt dans le principe :
On écoute le clic (MouseEvent.CLICK) sur chaque clip à colorier et on lui applique la couleur choisie dans la palette.

EnooOOoorme soupir dans l'assistance : “bon sang de bon d'là ! Il faut donc nommer chacun des clips et leur ajouter un écouteur ? Mais c'est du Stakhanovisme !”

Non ! Ne dressez pas un piquet de grève tout de suite ;) Il y a bien plus malin.
Vous vous souvenez de la différence entre ''target'' et ''currentTarget'' ? :idea:

Ici, l'idée c'est d'écouter sur le clip contenant (je l'ai nommé tableau ds le code reproduit) et de traiter non pas currentTarget (le “tableau” lui même) mais target (chacun des symboles le composant).

tableau.addEventListener(MouseEvent.CLICK, qdClic);
 
function qdClic(me:MouseEvent):void {
	trace(me.currentTarget.name);
	trace(me.target.name);
	// ici ce n'est pas le clip tableau dont on modifie la couleur
	// mais les clips dont il est constitué
	// on écoute donc target et non currentTarget
	var coul:ColorTransform= new ColorTransform();
	coul.color = cp.selectedColor;
	me.target.transform.colorTransform = coul;
}


Tout irait bien si d'aucuns ne s'avisaient d'ajouter un joli cadre au symbole lui même - comme sur la démo d'intro quoi…
Et là, catastrophe… Quand on clique sur ce cadre, c'est tout le tableau qui est barbouillé de la couleur sélectionnée, on se retrouve avec un splendide rectangle uni O.o

Normal, aussi longtemps que le symbole n'était composé que d'autres symboles (le fond lui même est un symbole), target était immanquablement un enfant du “tableau”. Maintenant qu'il y a un dessin qui déborde du fond, quand on clique, target c'est le clip tableau, et du coup… Ça ne fait plus ce qu'on veut…

Nous voici poussés dans nos dernier retranchement c'est le moment de dégoupiller la phase de capture, et de profiter de l'exemple pour se mettre les idées aux clair.

tableau.addEventListener(MouseEvent.CLICK, qdClic,true);



Ouf ! On s'en est bien sortis, sur ce coup là. Ne reste plus qu'à régler le sort du bouton Effacer.

Effacer

Un bout de code vaudra mieux qu'un long discours :

btEfface.addEventListener(MouseEvent.CLICK,efface);
function efface(me:MouseEvent):void {
	//var sansCoul:ColorTransform= new ColorTransform();
	var max:int = tableau.numChildren;
	for (var i:int=0; i<max; i++) {
 
		//tableau.getChildAt(i).transform.colorTransform = sansCoul;
		// sur ce coup là, on peut faire l'économie d'une variable, le code est tout aussi lisible
		tableau.getChildAt(i).transform.colorTransform = new ColorTransform();
 
	}
}



ColorPicker pour Flex


Et voilà, c'en est fini du coloriage.
Si vous utilisez Flex vous y retrouverez ce (quasi) même composant, et Tannoy a traduit la doc pour nous _o_

Il ne reste plus qu'à vous dire à bientôt pour d'autres aventures ;)

Les sources

1) Précautions Oratoires d'Usage