Adobe as3_devguide.pdf - Manuel

- Revenir à l'accueil

 

 

ADOBE :

[TXT]

 ADOBEFLASHLITE1.Xgui..> 07-Feb-2012 11:27  229K  

[TXT]

 Adobe-Acrobat-Fusion..> 30-Dec-2013 17:49  1.2M  

[TXT]

 Adobe-Acrobat-Videos..> 30-Dec-2013 17:49  1.6M  

[TXT]

 Adobe-American-India..> 30-Dec-2013 17:48  1.2M  

[TXT]

 Adobe-Learn-Flash-Pr..> 30-Dec-2013 17:49  1.3M  

[TXT]

 Adobe-SpeedGrade-Vid..> 30-Dec-2013 17:51  1.3M  

[TXT]

 Adobe-at-IBC-2013-Vi..> 30-Dec-2013 17:51  1.3M  

[TXT]

 Adobedocumentation.htm  07-Feb-2012 11:28  6.9M  

[TXT]

 Dreamweaver-CC-Video..> 30-Dec-2013 17:50  1.2M  

[TXT]

 Dreamweaver-Interact..> 30-Dec-2013 17:50  1.2M  

[TXT]

 Dreamweaver-Place-et..> 30-Dec-2013 17:50  1.2M
DreamWeaver :

[TXT]

 Dreamweaver-CC-Video..> 30-Dec-2013 16:51  1.2M  

[TXT]

 Dreamweaver-Interact..> 30-Dec-2013 16:57  1.2M  

[TXT]

 Dreamweaver-Place-et..> 30-Dec-2013 17:01  1.2M  

Ordinateurs :

Miniature

Ask Ben Heck - Connect Raspberry Pi to Car Computer

Miniature

Ben's Portable Raspberry Pi Computer Trailer

Miniature

Ben's Raspberry Pi Portable Computer Trailer 2

Miniature

Ben Heck's Pocket Computer Trailer

Miniature

Ask Ben Heck - Atari Computer

Miniature

Ask Ben Heck - Using Computer Monitors for External Displays

Miniature

Raspberry Pi Partnership with BBC Computer Literacy Project - Answers from co-founder Eben Upton

Miniature

Installing RaspBMC on your Raspberry Pi with the Farnell element14 Accessory kit

Miniature

Raspberry Pi Served - Joey Hudy

Miniature

Happy Birthday Raspberry Pi

Miniature

Raspberry Pi board B product overview

Logiciels :

Miniature

Ask Ben Heck - Best Opensource or Free CAD Software

Miniature

Tektronix FPGAView™ software makes debugging of FPGAs faster than ever!

Miniature

Ask Ben Heck - Best Open-Source Schematic Capture and PCB Layout Software

Tutoriels :

Miniature

Ben Heck The Great Glue Gun Trailer Part 1

Miniature

the knode tutorial - element14

Miniature

Ben's Autodesk 123D Tutorial Trailer

Miniature

Ben's CadSoft EAGLE Tutorial Trailer

Miniature

Ben Heck's Soldering Tutorial Trailer

Miniature

Ben Heck's AVR Dev Board tutorial

Miniature

Ben Heck's Pinball Tutorial Trailer

Farnell Element 14 :

Miniature

Introducing element14 TV

Miniature

Ben Heck Time to Meet Your Maker Trailer

Miniature

Détecteur de composants

Miniature

Recherche intégrée

Miniature

Ben Builds an Accessibility Guitar Trailer Part 1

Miniature

Ben Builds an Accessibility Guitar - Part 2 Trailer

Miniature

PiFace Control and Display Introduction

Miniature

Flashmob Farnell

Miniature

Express Yourself in 3D with Cube 3D Printers from Newark element14

Miniature

Farnell YouTube Channel Move

Miniature

Farnell: Design with the best

Miniature

French Farnell Quest

Miniature

Altera - 3 Ways to Quickly Adapt to Changing Ethernet Protocols

Miniature

Cy-Net3 Network Module

Miniature

MC AT - Professional and Precision Series Thin Film Chip Resistors

Miniature

Solderless LED Connector

Miniature

PSA-T Series Spectrum Analyser: PSA1301T/ PSA2701T

Miniature

3-axis Universal Motion Controller For Stepper Motor Drivers: TMC429

Guide du développeur d’ACTIONSCRIPT® 3.0 Dernière mise à jour le 27/4/2013 Informations juridiques Informations juridiques Vous trouverez des informations juridiques à l’adresse http://help.adobe.com/fr_FR/legalnotices/index.html. iii Dernière mise à jour le 27/4/2013 Sommaire Chapitre 1 : Utilisation des dates et des heures Gestion des dates calendaires et des heures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Contrôle des intervalles temporels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Exemple de date et heure : horloge analogique simple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Chapitre 2 : Utilisation des chaînes Principes de base des chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Création de chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Propriété length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Utilisation de caractères dans des chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 Comparaison de chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Récupération des représentations de chaîne d’autres objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Concaténation de chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Recherche de sous-chaînes et de modèles dans des chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Conversion de la casse dans des chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Exemple de chaîne : ASCII Art . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Chapitre 3 : Utilisation de tableaux Principes de base des tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Tableaux indexés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Tableaux associatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Tableaux multidimensionnels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Clonage de tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Extension de la classe Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Exemple de tableau : PlayList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Chapitre 4 : Gestion des erreurs Principes de base de la gestion des erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Types d’erreurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Gestion des erreurs dans ActionScript 3.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Utilisation des versions de débogage des moteurs d’exécution Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Gestion des erreurs synchrones dans une application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Création de classes d’erreur personnalisées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 Réponse à des événements et à l’état d’erreur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Comparaison des classes Error . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Exemple de gestion des erreurs : application CustomErrors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Chapitre 5 : Utilisation d’expressions régulières Principes de base des expressions régulières . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 Syntaxe d’expression régulière . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 Méthodes d’utilisation d’expressions régulières avec des chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 Exemple d’expression régulière : analyseur Wiki . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 iv Sommaire Dernière mise à jour le 27/4/2013 Chapitre 6 : Utilisation de XML Principes de base de XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 Approche E4X concernant le traitement XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Objets XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 Objets XMLList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106 Initialisation de variables XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 Assemblage et transformation d’objets XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 Parcours de structures XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 Utilisation des espaces de noms XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 Conversion de type XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 Lecture de documents XML externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 Utilisation de XML dans un exemple ActionScript : chargement de données RSS depuis Internet . . . . . . . . . . . . . . . . . . . . . . . 118 Chapitre 7 : Utilisation de la fonctionnalité JSON native Présentation de l’API JSON . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Définition du comportement JSON personnalisé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 Chapitre 8 : Gestion des événements Principes de base de la gestion des événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 Variation de la gestion d’événements dans ActionScript 3.0 par rapport aux versions antérieures . . . . . . . . . . . . . . . . . . . . . . 131 Flux d’événements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 Objets événement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 Ecouteurs d’événement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 Exemple de gestion des événements : Alarm Clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145 Chapitre 9 : Utilisation de domaines d’application Chapitre 10 : Programmation de l’affichage Concepts fondamentaux de la programmation de l’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 Classes d’affichage de base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 Avantages de l’utilisation de la liste d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 Utilisation des objets d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 Manipulation des objets d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 Animation des objets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 Orientation de la scène . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Chargement dynamique du contenu d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Exemple d’objet d’affichage : SpriteArranger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 Chapitre 11 : Utilisation de la géométrie Principes de base de la géométrie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218 Utilisation des objets Point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 Utilisation des objets Rectangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Utilisation des objets Matrix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Exemple de géométrie : application d’une transformation de matrice à un objet d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . 226 Chapitre 12 : Utilisation de l’API de dessin Principes de base de l’API de dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 Classe Graphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 v Sommaire Dernière mise à jour le 27/4/2013 Dessin de lignes et de courbes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231 Dessin de formes à l’aide des méthodes intégrées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 Création de lignes et de remplissages en dégradé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235 Utilisation de la classe Math avec les méthodes de dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239 Animation avec l’API de dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240 Exemple d’utilisation de l’API de dessin : générateur algorithmique d’effets visuels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241 Utilisation avancée de l’API de dessin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 Chapitre 13 : Utilisation des images bitmap Principes de base de l’utilisation des images bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 Classes Bitmap et BitmapData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253 Manipulation des pixels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 Copie de données bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 Compression des données d’une image bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 Création de textures avec les fonctions de bruit aléatoire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 Défilement du contenu d’images bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 Utilisation du mipmapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 Exemple d’objet Bitmap : lune en rotation animée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 Décodage asynchrone des images bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273 Chapitre 14 : Filtrage des objets d’affichage Principes de base du filtrage des objets d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276 Création et application de filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 Filtres d’affichage disponibles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284 Exemple de filtrage des objets d’affichage : Filter Workbench . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302 Chapitre 15 : Utilisation des shaders de Pixel Bender Principes de base des shaders de Pixel Bender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310 Chargement ou intégration d’un shader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312 Accès aux métadonnées du shader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 Spécification des valeurs des entrées et des paramètres d’un shader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 Utilisation d’un shader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 320 Chapitre 16 : Utilisation des clips Principes de base des clips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333 Utilisation des objets MovieClip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Contrôle de la lecture d’un clip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334 Création d’objets MovieClip à l’aide d’ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 337 Chargement d’un fichier SWF externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 Exemple de clip : RuntimeAssetsExplorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342 Chapitre 17 : Utilisation des interpolations de mouvement Principes de base des interpolations de mouvement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 Copie de scripts d’interpolation de mouvement dans Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347 Incorporation de scripts d’interpolation de mouvement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348 Description de l’animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349 Ajout de filtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352 Association d’une interpolation de mouvement à ses objets d’affichage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 vi Sommaire Dernière mise à jour le 27/4/2013 Chapitre 18 : Utilisation de la cinématique inverse Principes de base de la cinématique inverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 355 Aperçu de l’animation de squelettes IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356 Obtention d’informations sur un squelette IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 Instanciation de l’objet IKMover et restriction du mouvement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 358 Mouvement d’un squelette IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359 Utilisation de ressorts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Utilisation d’événements IK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360 Chapitre 19 : Travail en trois dimensions (3D) Principes de base des objets d’affichage 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362 Présentation des objets d’affichage 3D dans les moteurs d’exécution de Flash Player et d’AIR . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Création et déplacement d’objets d’affichage 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 365 Projection d’objets 3D sur un affichage 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367 Exemple : Projection de perspective . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 369 Transformations 3D complexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372 Création d’effets 3D à l’aide de triangles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375 Chapitre 20 : Principes de base de l’utilisation du texte Chapitre 21 : Utilisation de la classe TextField Affichage du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385 Sélection et manipulation de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 389 Capture du texte saisi par l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391 Restriction de la saisie de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392 Mise en forme du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 393 Fonctions avancées d’affichage de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397 Utilisation du texte statique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 399 Exemple TextField : mise en forme du texte dans le style « article de journal » . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 401 Chapitre 22 : Utilisation de Flash Text Engine Création et affichage de texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410 Gestion des événements dans FTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415 Mise en forme du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418 Utilisation des polices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 422 Contrôle du texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 425 Exemple d’utilisation de Flash Text Engine : mise en forme d’un article de journal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431 Chapitre 23 : Utilisation de Text Layout Framework Présentation de Text Layout Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440 Utilisation de Text Layout Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441 Structuration du texte à l’aide de TLF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446 Formatage du texte à l’aide de TLF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450 Importation et exportation de texte à l’aide de TLF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451 Gestion des conteneurs de texte à l’aide de TLF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452 Activation de la sélection, de la modification et de l’annulation de texte à l’aide de TLF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453 Gestion des événements à l’aide de TLF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453 Positionnement des images dans le texte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 vii Sommaire Dernière mise à jour le 27/4/2013 Chapitre 24 : Utilisation du son Principes de base de l’utilisation du son . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455 Présentation de l’architecture audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456 Chargement de fichiers audio externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458 Utilisation des sons intégrés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460 Utilisation de fichiers audio de lecture en continu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462 Utilisation de données audio générées de façon dynamique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 463 Lecture de sons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465 Sécurité lors du chargement et de la lecture des sons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469 Contrôle du volume du son et de la balance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 470 Utilisation des métadonnées audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471 Accès aux données audio brutes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472 Capture de l’entrée de son . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476 Exemple d’objet Sound : Podcast Player . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 482 Chapitre 25 : Utilisation de la vidéo Principes de base de la vidéo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489 Présentation des formats vidéo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490 Présentation de la classe Video . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 Chargement de fichiers vidéo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 494 Contrôle de la lecture de la vidéo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495 Lecture de vidéos en mode plein écran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497 Lecture de fichiers vidéo en flux continu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 Présentation des points de repère . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 501 Ecriture de méthodes de rappel pour les métadonnées et les points de repère . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 502 Utilisation des points de repère et des métadonnées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 508 Gestion de l’activité de l’objet NetStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 518 Rubriques avancées relatives aux fichiers vidéo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 521 Exemple vidéo : Video Jukebox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 523 Présentation à accélération matérielle par le biais de la classe StageVideo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 528 Chapitre 26 : Utilisation de caméras Présentation de la classe Camera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 537 Affichage du contenu de la caméra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 Conception d’une application gérant une caméra locale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 538 Etablissement d’une connexion avec la caméra de l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 Vérification de la présence de caméras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 539 Détection de l’autorisation d’accéder à la caméra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 540 Optimisation de la qualité des vidéos de la caméra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 542 Gestion de l’état de la caméra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543 Chapitre 27 : Utilisation de la gestion des droits d’auteur numériques (DRM) Présentation du flux de travail associé au contenu protégé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 546 Membres et événements DRM de la classe NetStream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 553 Utilisation de la classe DRMStatusEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 554 Utilisation de la classe DRMAuthenticateEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 556 Utilisation de la classe DRMErrorEvent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 559 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 viii Sommaire Dernière mise à jour le 27/4/2013 Utilisation de la classe DRMManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 560 Utilisation de la classe DRMContentData . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 561 Mise à jour de Flash Player en vue de prendre en charge Adobe Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 562 Licences hors bande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563 Prise en charge de domaine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565 Lecture de contenu chiffré à l’aide de la prise en charge de domaine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 565 Aperçu de la licence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566 Diffusion de contenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566 Open Source Media Framework . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 567 Chapitre 28 : Ajout d’un contenu PDF dans AIR Détection des capacités PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 569 Chargement du contenu PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 570 Programmation du contenu PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 571 Limites connues pour du contenu PDF dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 572 Chapitre 29 : Principes de base de l’interaction utilisateur Capture des entrées utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 574 Gestion de la cible d’action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 575 Découverte des types de saisie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 576 Chapitre 30 : Saisie au clavier Capture de la saisie au clavier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578 Utilisation de la classe IME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 580 Claviers virtuels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585 Chapitre 31 : Entrées de souris Capture des entrées de souris . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593 Exemple d’entrée de souris : WordSearch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596 Chapitre 32 : Saisie tactile, multipoint et par mouvement Principes de base de la saisie tactile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601 Découverte de la prise en charge des actions tactiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603 Gestion des événements tactiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 604 Toucher-glisser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608 Gestion des événements de mouvement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 609 Résolution des problèmes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 613 Chapitre 33 : Opération de copier-coller Principes de base de l’opération de copier-coller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 616 Lecture en provenance et écriture à destination du Presse-papiers du système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617 Opération copier-coller HTML dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617 Formats de données Clipboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619 Chapitre 34 : Saisie via un accéléromètre Vérification de la prise en charge de l’accéléromètre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 626 Détection des changements de l’accéléromètre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 ix Sommaire Dernière mise à jour le 27/4/2013 Chapitre 35 : Opération glisser-déposer dans AIR Principes de base des opérations glisser-déposer dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 629 Prise en charge du mouvement de glissement vers l’extérieur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 631 Prise en charge du mouvement de glissement vers l’intérieur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 634 Opération glisser-déposer dans HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637 Glissement des données hors d’un élément HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 Glissement de données dans un élément HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 641 Exemple : Annulation du comportement de glissement vers l’intérieur HTML par défaut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 642 Gestion des dépôts de fichier dans un sandbox HTML hors application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 644 Dépôt de fichiers promis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 645 Chapitre 36 : Utilisation des menus Principes de base des menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 654 Création de menus natifs (AIR) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 661 A propos des menus contextuels dans un contenu HTML (AIR) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 663 Affichage de menus natifs en incrustation (AIR) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 664 Gestion des événements de menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 664 Exemple de menu natif : menu de fenêtre et d’application (AIR) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 666 Chapitre 37 : Icônes de la barre des tâches dans AIR A propos des icônes de la barre des tâches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 670 Icônes du Dock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 671 Icônes de la barre d’état système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 672 Icônes et boutons de la barre des tâches de la fenêtre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 674 Chapitre 38 : Utilisation du système de fichiers Utilisation de la classe FileReference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 676 Utilisation de l’interface de programmation du système de fichiers AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 691 Chapitre 39 : Stockage des données locales Objets partagés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 728 Stockage local chiffré . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 737 Chapitre 40 : Utilisation des bases de données SQL locales dans AIR A propos des bases de données SQL locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 741 Création et modification d’une base de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 746 Manipulation des données de bases de données SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 753 Utilisation des opérations de base de données synchrones et asynchrones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 782 Utilisation du chiffrement avec les bases de données SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 787 Stratégies d’utilisation des bases de données SQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 805 Chapitre 41 : Utilisation de tableaux d’octets Lecture et écriture d’un objet ByteArray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 808 Exemple ByteArray : lecture d’un fichier .zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 814 Chapitre 42 : Principes de base de la mise en réseau et de la communication Interfaces réseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 822 Changements de connectivité réseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 823 Enregistrements DNS (Domain Name System) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 826 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 x Sommaire Dernière mise à jour le 27/4/2013 Chapitre 43 : Sockets Sockets TCP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 828 Sockets UDP (AIR) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 839 Adresses IPv6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 841 Chapitre 44 : Communications HTTP Chargement de données externes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 843 Requêtes de service Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 852 Ouverture d’une URL dans une autre application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 860 Chapitre 45 : Communications avec d’autres occurrences de Flash Player et d’AIR A propos de la classe LocalConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 862 Envoi de messages entre deux applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 864 Connexion au contenu dans des domaines différents et aux applications AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 866 Chapitre 46 : Communication avec les processus natifs dans AIR Présentation des communications avec les processus natifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 869 Lancement et fermeture d’un processus natif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 870 Communications avec un processus natif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 871 Considérations liées à la sécurité qui affectent les communications avec le processus natif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 872 Chapitre 47 : Utilisation de l’API externe Principes de base de l’utilisation de l’API externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 874 Avantages de l’API externe et conditions requises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 877 Utilisation de la classe ExternalInterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 878 Exemple d’API externe : communications entre ActionScript et JavaScript dans un navigateur Web . . . . . . . . . . . . . . . . . . . . 882 Chapitre 48 : Validation des signatures XML dans AIR Bases de la validation des signatures XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 888 A propos des signatures XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 893 Implémentation de l’interface IURIDereferencer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 895 Chapitre 49 : Environnement du système client Principes de base de l’environnement du système client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 903 Utilisation de la classe System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 904 Utilisation de la classe Capabilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 905 Exemple d’utilisation de Capabilities : détection des capacités du système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 906 Chapitre 50 : Appel et fermeture d’une application AIR Appel d’une application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 910 Capture des arguments de ligne de commande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 912 Appel d’une application AIR lors de la connexion d’un utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 915 Appel d’une application AIR à partir du navigateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 916 Fermeture d’une application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 918 Chapitre 51 : Utilisation des informations sur le moteur d’exécution d’AIR et les systèmes d’exploitation Gestion des associations de fichiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 920 Lecture de la version du moteur d’exécution et du correctif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 xi Sommaire Dernière mise à jour le 27/4/2013 Détection des capacités d’AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 921 Suivi de la présence des utilisateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 922 Chapitre 52 : Utilisation des fenêtres natives AIR Principes de base des fenêtres natives dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 923 Création de fenêtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 931 Gestion des fenêtres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 940 Ecoute des événements d’une fenêtre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 951 Affichage des fenêtres en mode plein écran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 952 Chapitre 53 : Ecrans dans AIR Principes de base des écrans dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 954 Dénombrement des écrans . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 955 Chapitre 54 : Impression Principes de base de l’impression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 958 Impression d’une page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 959 Tâches des moteurs d’exécution de Flash et impression système . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 960 Définition de la taille, de l’échelle et de l’orientation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 963 Techniques d’impression avancées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 965 Exemple d’impression : impression de plusieurs pages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 967 Exemple d’impression : mise à l’échelle, recadrage et ajustement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 969 Exemple d’impression : options d’impression et de mise en page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 971 Chapitre 55 : Geolocation Détection des changements de géolocalisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 974 Chapitre 56 : Internationalisation des applications Principes de base de l’internationalisation des applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 978 Présentation du package flash.globalization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 979 Identification des paramètres régionaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 981 Formatage des nombres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 982 Formatage des valeurs en devise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 985 Formatage des dates et heures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 987 Tri et comparaison des chaînes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 989 Conversion de la casse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 990 Exemple : Internationalisation d’une application de suivi des stocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 991 Chapitre 57 : Localisation d’applications Choix d’un jeu de paramètres régionaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 996 Localisation de contenu Flex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 997 Localisation du contenu Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 997 Localisation d’applications AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 997 Localisation des dates, heures et devises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 998 Chapitre 58 : A propos de l’environnement HTML Présentation de l’environnement HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1000 AIR et WebKit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1003 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 xii Sommaire Dernière mise à jour le 27/4/2013 Chapitre 59 : Programmation HTML et JavaScript dans AIR A propos de la classe HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1019 Contournement des erreurs JavaScript liées à la sécurité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1021 Accès aux classes de l’API AIR à partir de JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1026 A propos des URL dans AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1027 Mise des objets ActionScript à disposition de JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1028 Accès au DOM HTML et aux objets JavaScript à partir d’ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1030 Intégration d’un contenu SWF en HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1031 Utilisation des bibliothèques ActionScript au sein d’une page HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1034 Conversion des objets Date et RegExp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1036 Manipulation d’une feuille de style HTML à partir d’ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1036 Programmation croisée du contenu dans des sandbox de sécurité distincts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1038 Chapitre 60 : Programmation du conteneur HTML d’AIR à l’aide de scripts Affichage des propriétés des objets HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1043 Défilement du contenu HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1046 Accès à l’historique de HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1047 Paramétrage de l’agent d’utilisateur employé lors du chargement du contenu HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1048 Paramétrage du codage des caractères à utiliser pour le contenu HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1048 Paramétrage des interfaces utilisateur de type navigateur pour un contenu HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1049 Création de sous-classes de la classe HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1060 Chapitre 61 : Gestion des événements HTML dans AIR Evénements HTMLLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1062 Gestion des événements DOM avec ActionScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1063 Réponse aux exceptions JavaScript non interceptées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1063 Gestion des événements d’exécution avec JavaScript . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1065 Chapitre 62 : Affichage de contenu HTML dans une application mobile Objets StageWebView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1068 Contenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1069 Evénements de navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1070 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1071 Cible d’action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1072 Capture d’image bitmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1074 Chapitre 63 : Utilisation de programmes de travail à des fins de simultanéité Présentation des programmes de travail et de la simultanéité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1076 Création et gestion de programmes de travail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1077 Communication entre programmes de travail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1080 Chapitre 64 : Sécurité Présentation de la sécurité sur la plate-forme Flash . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1085 Sandbox de sécurité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1087 Contrôles des autorisations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1091 Restriction des API de réseau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1100 Sécurité du mode plein écran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1102 Sécurité du mode interactif plein écran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1103 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 xiii Sommaire Dernière mise à jour le 27/4/2013 Chargement de contenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1104 Programmation croisée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1107 Accès aux médias chargés comme s’il s’agissait de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1111 Chargement des données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1113 Chargement de contenu incorporé à partir de fichiers SWF importés dans un domaine de sécurité . . . . . . . . . . . . . . . . . . . . 1117 Utilisation de contenus existants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1117 Définition des autorisations LocalConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1118 Contrôle de l’accès URL externe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1118 Objets partagés . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1120 Accès à la caméra, au microphone, au Presse-papiers, à la souris et au clavier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1122 Sécurité AIR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1122 Chapitre 65 : Utilisation des exemples de code ActionScript Types d’exemples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1145 Exécution d’exemples ActionScript 3.0 dans Flash Professional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1147 Exécution d’exemples ActionScript 3.0 dans Flash Builder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1148 Exécution d’exemples ActionScript 3.0 sur un périphérique mobile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1150 Chapitre 66 : Prise en charge de SQL dans les bases de données locales Syntaxe SQL prise en charge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1155 Prise en charge des types de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1177 Chapitre 67 : ID, arguments et messages d’erreur SQL détaillés Chapitre 68 : AGAL (Adobe Graphics Assembly Language) Pseudo-code binaire AGAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1188 1 Dernière mise à jour le 27/4/2013 Chapitre 1 : Utilisation des dates et des heures Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si la ponctualité ne fait pas tout, elle n’en est pas moins un facteur clé des applications logicielles. ActionScript 3.0 propose différentes méthodes de gestion des dates calendaires, des heures et des intervalles temporels. Deux classes principales assurent l’essentiel de la fonctionnalité temporelle : la classe Date et la nouvelle classe Timer du package flash.utils. Les dates et les heures constituent un type d’informations courant utilisé dans les programmes ActionScript. Par exemple, vous pouvez, entre autres, connaître la date du jour ou calculer combien de temps un utilisateur passe sur un écran particulier. Dans ActionScript, vous pouvez utiliser la classe Date pour représenter un moment unique dans le temps, y compris des informations de date et d’heure. Une occurrence de Date contient des valeurs pour les unités de date et d’heure individuelles (année, mois, date, jour de la semaine, heure, minutes, secondes, millisecondes et fuseau horaire, par exemple). Pour des utilisations plus avancées, ActionScript comprend également la classe Timer que vous pouvez utiliser pour effectuer des actions après un certain délai ou à des intervalles répétés. Voir aussi Date flash.utils.Timer Gestion des dates calendaires et des heures Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans ActionScript 3.0, toutes les fonctions de gestion des dates calendaires et des heures se concentrent autour de la classe de niveau supérieur Date. Cette classe contient des méthodes et des propriétés qui vous permettent de manier les dates et les heures soit selon le modèle universel coordonné (UTC, Universal Time Coordinated), soit selon le fuseau horaire considéré. L’UTC est une définition normalisée du temps qui correspond essentiellement à l’heure du méridien de Greenwich (GMT, Greenwich Mean Time). Création d’objets Date Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Date compte l’une des méthodes constructeur les plus polyvalentes de toutes les classes de base. Vous pouvez l’invoquer de quatre manières différentes. Primo, si aucun paramètre n’est fourni, le constructeur Date() renvoie un objet Date contenant la date et l’heure locale actuelle de votre fuseau horaire. Exemple : var now:Date = new Date(); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 2 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 Secundo, si un paramètre numérique unique est fourni, le constructeur Date() le considère comme le nombre de millisecondes écoulées depuis le 1er janvier 1970 et renvoie l’objet Date correspondant. Notez que la valeur en millisecondes que vous transmettez est considérée comme le nombre de millisecondes depuis le 1er janvier 1970 en temps UTC. Toutefois, l’objet Date affiche des valeurs dans votre fuseau horaire local, sauf si vous utilisez des méthodes UTC uniquement pour les extraire et les afficher. Si vous créez un nouvel objet Date à l’aide du paramètre en millisecondes, veillez à tenir compte du décalage horaire entre votre fuseau local et le temps UTC. Les instructions ci-après créent un objet Date défini à minuit le 1er janvier 1970 en temps UTC : var millisecondsPerDay:int = 1000 * 60 * 60 * 24; // gets a Date one day after the start date of 1/1/1970 var startTime:Date = new Date(millisecondsPerDay); Tertio, vous pouvez transmettre plusieurs paramètres numériques au constructeur Date(). Celui-ci les traite respectivement comme la date, le mois, le jour, les heures, les minutes, les secondes et les millisecondes, et renvoie un objet Date correspondant. Les paramètres indiqués sont considérés comme correspondant à l’heure locale plutôt qu’au temps UTC. Les instructions suivantes établissent un objet Date défini à minuit le 1er janvier 2000, dans le fuseau horaire local : var millenium:Date = new Date(2000, 0, 1, 0, 0, 0, 0); Quarto, vous pouvez transmettre un paramètre numérique unique au constructeur Date(). Celui-ci essaiera d’analyser cette chaîne en composants de date et heure, et de renvoyer un objet Date correspondant. Si vous choisissez cette approche, il est recommandé d’inclure le constructeur Date() dans un bloc try..catch afin d’intercepter toute erreur d’analyse. Le constructeur Date() gère plusieurs formats de chaîne (dont la liste figure dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash). L’instruction suivante initialise un nouvel objet Date à l’aide d’une valeur chaîne : var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM"); Si le constructeur Date() ne peut analyser le paramètre chaîne, il ne déclenche pas d’exception. Cependant, l’objet Date résultant contiendra une valeur date incorrecte. Obtention des valeurs d’unités temporelles Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez extraire les valeurs de plusieurs unités temporelles au sein de l’objet Date grâce à des propriétés ou des méthodes de la classe Date. Chacune des propriétés suivantes fournit la valeur d’une unité temporelle de l’objet Date : • La propriété fullYear • La propriété month au format numérique : de 0 pour janvier à 11 pour décembre • La propriété date, qui correspond au numéro calendaire du jour du mois, de 1 à 31 • La propriété day, qui correspond au jour de la semaine au format numérique, 0 représentant dimanche • La propriété hours, de 0 à 23 • La propriété minutes • La propriété seconds • La propriété milliseconds La classe Date offre en fait plusieurs manières d’obtenir ces valeurs. Vous pouvez par exemple obtenir la valeur month de l’objet Date de quatre manières : • La propriété month GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 3 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 • La méthode getMonth() • La propriété monthUTC • La méthode getMonthUTC() Ces quatre solutions sont d’une efficacité équivalente, vous pouvez donc adopter celle qui convient le mieux à votre application. Les propriétés répertoriées ci-dessus représentent toutes des composants de la valeur date totale. Par exemple, la propriété milliseconds ne sera jamais supérieure à 999, puisque si elle atteint 1000, la valeur seconds augmente de 1, la propriété milliseconds se remet à zéro. Si vous voulez obtenir la valeur de l’objet Date en millisecondes depuis le 1er janvier 1970 (UTC), vous pouvez utiliser la méthode getTime(). La méthode setTime(), quant à elle, vous permet de modifier la valeur d’un objet Date existant en millisecondes depuis le 1er janvier 1970 (UTC). Opérations arithmétiques sur la date et l’heure Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Date permet d’additionner et de soustraire des dates et heures. Les valeurs Date sont conservées en interne sous forme de millisecondes. Il est donc nécessaire de convertir les autres valeurs en millisecondes avant de les ajouter ou de les soustraire aux objets Date. Si votre application doit effectuer de nombreuses opérations arithmétiques sur les dates et heures, il peut s’avérer utile de créer des constantes qui conservent les valeurs d’unités temporelles courantes en millisecondes, comme illustré ciaprès : public static const millisecondsPerMinute:int = 1000 * 60; public static const millisecondsPerHour:int = 1000 * 60 * 60; public static const millisecondsPerDay:int = 1000 * 60 * 60 * 24; Il devient alors simple d’effectuer des opérations arithmétiques à l’aide des unités temporelles standard. Le code ciaprès décale la valeur date d’une heure par rapport à l’heure actuelle à l’aide des méthodes getTime() et setTime() : var oneHourFromNow:Date = new Date(); oneHourFromNow.setTime(oneHourFromNow.getTime() + millisecondsPerHour); Une autre manière de définir une valeur date consiste à créer un objet Date à l’aide d’un seul paramètre en millisecondes. Par exemple, le code suivant ajoute 30 jours à une date pour en calculer une autre : // sets the invoice date to today's date var invoiceDate:Date = new Date(); // adds 30 days to get the due date var dueDate:Date = new Date(invoiceDate.getTime() + (30 * millisecondsPerDay)); La constante millisecondsPerDay est ensuite multipliée par 30 pour représenter la période de 30 jours et le résultat est ajouté à la valeur invoiceDate afin de définir la valeur dueDate. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 4 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 Conversion entre plusieurs fuseaux horaires Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les opérations arithmétiques sur les dates et heures sont particulièrement pratiques lorsque vous devez convertir des dates d’un fuseau horaire à un autre. Tel est le rôle de la méthode getTimezoneOffset(), qui renvoie la valeur (en minutes) de décalage entre le fuseau horaire de l’objet Date et le temps UTC. La valeur renvoyée s’exprime en minutes parce que tous les fuseaux horaires ne correspondent pas à une heure ; certains sont décalés d’une demi-heure par rapport aux fuseaux voisins. L’exemple suivant utilise le décalage de fuseau horaire pour convertir une date à partir de l’heure locale en temps UTC. La conversion s’effectue tout d’abord par calcul de la valeur du fuseau horaire en millisecondes, puis par ajustement de la valeur Date selon ce montant : // creates a Date in local time var nextDay:Date = new Date("Mon May 1 2006 11:30:00 AM"); // converts the Date to UTC by adding or subtracting the time zone offset var offsetMilliseconds:Number = nextDay.getTimezoneOffset() * 60 * 1000; nextDay.setTime(nextDay.getTime() + offsetMilliseconds); Contrôle des intervalles temporels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous développez des applications à l’aide d’Adobe Flash CS4 Professional, vous avez accès au scénario, qui fournit une progression constante, image par image, au sein de votre application. Toutefois, dans un projet purement ActionScript, vous devez compter sur d’autres mécanismes temporels. Boucles ou minuteurs ? Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans certains langages de programmation, vous devez mettre au point des motifs temporels à l’aide d’instructions en boucle telles que for ou do..while. Les instructions en boucle s’exécutent en général aussi vite que la machine locale le permet, ce qui signifie que l’application sera plus rapide sur certaines machines que sur d’autres. Si votre application doit bénéficier d’un intervalle temporel cohérent, vous devez l’associer à un calendrier ou une horloge réels. Bien des applications, telles que les jeux, les animations, les contrôleurs en temps réel, nécessitent des mécanismes de décompte temporel qui soient cohérents d’une machine à l’autre. La classe Timer d’ActionScript 3.0 offre une solution performante dans ce domaine. Grâce au modèle d’événements ActionScript 3.0, la classe Timer distribue des événements Timer dès qu’un intervalle spécifié est atteint. La classe Timer Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour la gestion des fonctions temporelles dans ActionScript 3.0, il est recommandé d’utiliser la classe Timer (flash.utils.Timer), qui permet de distribuer des événements dès qu’un intervalle est atteint. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 5 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 Pour lancer un minuteur, vous devez d’abord créer une occurrence de la classe Timer et lui indiquer à quelle fréquence elle doit générer un événement Timer et combien de fois elle doit le faire avant de s’arrêter. Par exemple, le code suivant crée une occurrence de Timer qui distribue un événement toutes les secondes pendant 60 secondes : var oneMinuteTimer:Timer = new Timer(1000, 60); L’objet Timer distribue un objet TimerEvent chaque fois que l’intervalle donné est atteint. Le type d’événement de l’objet TimerEvent est timer (défini par la constante TimerEvent.TIMER). Un objet TimerEvent contient les mêmes propriétés que l’objet standard Event. Si l’occurrence de Timer prévoit un nombre fixe d’intervalles, elle distribue également un événement timerComplete (défini par la constante TimerEvent.TIMER_COMPLETE) lorsqu’elle atteint l’intervalle final. Voici un court exemple d’application illustrant la classe Timer en action : package { import flash.display.Sprite; import flash.events.TimerEvent; import flash.utils.Timer; public class ShortTimer extends Sprite { public function ShortTimer() { // creates a new five-second Timer var minuteTimer:Timer = new Timer(1000, 5); // designates listeners for the interval and completion events minuteTimer.addEventListener(TimerEvent.TIMER, onTick); minuteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete); // starts the timer ticking minuteTimer.start(); } public function onTick(event:TimerEvent):void { // displays the tick count so far // The target of this event is the Timer instance itself. trace("tick " + event.target.currentCount); } public function onTimerComplete(event:TimerEvent):void { trace("Time's Up!"); } } } Lorsque la classe ShortTimer est créée, elle génère une occurrence de Timer qui marque chaque seconde pendant cinq secondes. Elle ajoute alors deux écouteurs au minuteur : un qui écoute chaque décompte et un qui écoute l’événement timerComplete. Elle lance ensuite le décompte du minuteur et à partir de là, la méthode onTick() s’exécute toutes les secondes. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 6 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 La méthode onTick() affiche simplement le nombre actuel de tics. Après cinq secondes, la méthode onTimerComplete() s’exécute et vous avertit que le temps est écoulé. Si vous exécutez cet exemple, vous devriez voir les lignes suivantes s’afficher dans votre console ou fenêtre de suivi à raison d’une ligne par seconde : tick 1 tick 2 tick 3 tick 4 tick 5 Time's Up! Fonctions temporelles du package flash.utils Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 3.0 contient un certain nombre de fonctions temporelles similaires à celles qui étaient disponibles dans ActionScript 2.0. Ces fonctions sont fournies au niveau du package dans le package flash.utils et elles fonctionnent de la même manière que dans ActionScript 2.0. Ces fonctions demeurent dans ActionScript 3.0 afin d’assurer la compatibilité avec les versions antérieures. Adobe ne recommande pas leur utilisation dans les nouvelles applications ActionScript 3.0. Il est en général plus simple et plus efficace d’utiliser la classe Timer. Exemple de date et heure : horloge analogique simple Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un exemple d’horloge analogique simple illustre ces deux concepts de date et heure : • Obtention de la date et de l’heure actuelle et extraction des valeurs heures, minutes et secondes • Utilisation d’une horloge pour fixer le rythme d’une application Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application SimpleClock se trouvent dans le dossier Samples/SimpleClock. L’application se compose des fichiers suivants : Fonction Description clearInterval(id:uint):void Annule un appel de setInterval() spécifié. clearTimeout(id:uint):void Annule un appel de setTimeout() spécifié. getTimer():int Renvoie le nombre de millisecondes qui se sont écoulées depuis l’initialisation d’Adobe® Flash® Player ou d’Adobe® AIR™. setInterval(closure:Function, delay:Number, ... arguments):uint Exécute une fonction à fréquence définie (intervalle exprimé en millisecondes). setTimeout(closure:Function, delay:Number, ... arguments):uint Exécute une fonction spécifiée après un délai spécifié (en millisecondes). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 7 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 Définition de la classe SimpleClock Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si l’exemple d’horloge est simple, il est toujours judicieux de bien organiser les applications de manière à faciliter leur extension future. Dans ce but, l’application SimpleClock utilise la classe SimpleClock pour gérer les tâches de démarrage et de mesure temporelle. Elle se sert ensuite d’une autre classe, AnalogClockFace, pour l’affichage réel de l’heure. Voici le code qui définit et initialise la classe SimpleClock (vous remarquerez que dans la version Flash, SimpleClock étend la classe Sprite à la place) : public class SimpleClock extends UIComponent { /** * The time display component. */ private var face:AnalogClockFace; /** * The Timer that acts like a heartbeat for the application. */ private var ticker:Timer; Cette classe possède deux propriétés importantes : • La propriété face, qui correspond à une occurrence de la classe AnalogClockFace • La propriété ticker, qui est une occurrence de la classe Timer La classe SimpleClock utilise un constructeur par défaut. La méthode initClock() se charge de la véritable configuration, en créant le cadran et en lançant le décompte de l’occurrence de Timer. Création du cadran Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les lignes suivantes du code SimpleClock créent le cadran utilisé pour afficher l’heure : Fichier Description SimpleClockApp.mxml ou SimpleClockApp.fla Fichier d’application principal dans Flash (FLA) ou Flex (MXML). com/example/programmingas3/simpleclock/SimpleClock.as Fichier d’application principal. com/example/programmingas3/simpleclock/AnalogClockFace.as Dessine un cadran d’horloge rond et les aiguilles des heures, des minutes et des secondes en fonction de l’heure. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 8 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 /** * Sets up a SimpleClock instance. */ public function initClock(faceSize:Number = 200) { // creates the clock face and adds it to the display list face = new AnalogClockFace(Math.max(20, faceSize)); face.init(); addChild(face); // draws the initial clock display face.draw(); La taille de l’horloge peut être transmise à la méthode initClock(). Si aucune valeur faceSize n’est transmise, la taille par défaut de 200 pixels est utilisée. L’application initialise ensuite l’horloge et l’ajoute à la liste d’affichage à l’aide de la méthode addChild() héritée de la classe DisplayObjectContainer. Elle appelle enfin la méthode AnalogClockFace.draw() pour afficher une fois le cadran, qui indique l’heure actuelle. Lancement du minuteur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Une fois le cadran créé, la méthode initClock() définit le minuteur : // creates a Timer that fires an event once per second ticker = new Timer(1000); // designates the onTick() method to handle Timer events ticker.addEventListener(TimerEvent.TIMER, onTick); // starts the clock ticking ticker.start(); Cette méthode commence par instancier une occurrence de Timer qui va distribuer un événement par seconde (toutes les 1 000 millisecondes). Comme le constructeur Timer() ne reçoit pas de second paramètre repeatCount, l’horloge se reproduit indéfiniment. La méthode SimpleClock.onTick() s’exécute une fois par seconde après réception de l’événement timer : public function onTick(event:TimerEvent):void { // updates the clock display face.draw(); } La méthode AnalogClockFace.draw() dessine simplement le cadran de l’horloge et des aiguilles. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 9 Utilisation des dates et des heures Dernière mise à jour le 27/4/2013 Affichage de l’heure actuelle Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La plupart du code de la classe AnalogClockFace implique la définition des éléments d’affichage du cadran. Lors de son initialisation, AnalogClockFace dessine un contour circulaire, place des libellés numériques pour chaque heure, puis crée trois objets Shape, un pour l’aiguille des heures, un pour celle des minutes et un pour l’aiguille des secondes de l’horloge. Lorsque l’application SimpleClock s’exécute, elle appelle la méthode AnalogClockFace.draw() toutes les secondes, comme suit : /** * Called by the parent container when the display is being drawn. */ public override function draw():void { // stores the current date and time in an instance variable currentTime = new Date(); showTime(currentTime); } Cette méthode enregistre l’heure actuelle dans une variable, pour que l’heure ne puisse changer pendant le dessin des aiguilles de l’horloge. Elle appelle ensuite la méthode showTime() pour afficher les aiguilles, comme illustré ci-après : /** * Displays the given Date/Time in that good old analog clock style. */ public function showTime(time:Date):void { // gets the time values var seconds:uint = time.getSeconds(); var minutes:uint = time.getMinutes(); var hours:uint = time.getHours(); // multiplies by 6 to get degrees this.secondHand.rotation = 180 + (seconds * 6); this.minuteHand.rotation = 180 + (minutes * 6); // Multiply by 30 to get basic degrees, then // add up to 29.5 degrees (59 * 0.5) // to account for the minutes. this.hourHand.rotation = 180 + (hours * 30) + (minutes * 0.5); } Tout d’abord, cette méthode extrait les valeurs des heures, des minutes et des secondes pour l’heure actuelle. Elle utilise ensuite ces valeurs pour calculer l’angle de chaque aiguille. Comme l’aiguille des secondes effectue une rotation complète en 60 secondes, elle tourne de 6 degrés par seconde (360/60). L’aiguille des minutes pivote selon le même angle chaque minute. L’aiguille des heures se met à jour toutes les minutes également et doit donc progresser à chaque minute. Elle tourne de 30 degrés toutes les heures (360/12), mais pivote également d’un demi-degré toutes les minutes (30 degrés divisés par 60 minutes). 10 Dernière mise à jour le 27/4/2013 Chapitre 2 : Utilisation des chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe String contient des méthodes qui vous permettent de manipuler des chaînes de texte. Les chaînes s’utilisent avec de nombreux objets. Les méthodes décrites ci-après permettent de manipuler les chaînes utilisées dans des objets tels que TextField, StaticText, XML, ContextMenu et FileReference. Les chaînes sont des séries de caractères. ActionScript 3.0 prend en charge les caractères ASCII et Unicode. Voir aussi String RegExp parseFloat() parseInt() Principes de base des chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour les programmeurs, une « chaîne » est un texte, une suite de lettres, chiffres ou autres caractères qui se suivent et forment une unité représentée par une valeur. Par exemple, la ligne de code suivante crée une variable ayant le type de données String (chaîne) et affecte une valeur de chaîne littérale à cette variable : var albumName:String = "Three for the money"; Comme le montre cet exemple, ActionScript permet de délimiter une valeur chaîne en enfermant du texte entre des guillemets droits doubles ou simples. Voici d’autres exemples de chaînes : "Hello" "555-7649" "http://www.adobe.com/" Lorsque vous manipulez un fragment de texte en ActionScript, vous utilisez une valeur chaîne. La classe String d’ActionScript est le type de données qui permet de travailler avec du texte. Des occurrences de chaînes sont fréquemment utilisées pour des propriétés, des paramètres de méthodes, etc., dans de nombreuses autres classes en ActionScript. Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs aux chaînes : ASCII Système de codage permettant de représenter du texte sous forme de caractères et symboles dans les programmes informatiques. Le système ASCII gère les 26 lettres de l’alphabet latin, plus un nombre limité de caractères supplémentaires. Caractère Unité de base d’un texte (lettre ou symbole). Concaténation Ajout bout à bout de plusieurs valeurs de chaîne pour en créer une nouvelle. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 11 Utilisation des chaînes Dernière mise à jour le 27/4/2013 Chaîne vide Chaîne qui ne contient rien: ni texte, ni espace, ni autre caractère, représentée par "". Une chaîne vide n’est pas la même chose qu’une variable ayant une valeur nulle (null) : celle-ci est une variable à laquelle aucune occurrence de l’objet String n’est affectée, alors qu’une chaîne vide est une occurrence dont la valeur ne contient aucun caractère. String Valeur textuelle (séquence de caractères). Littéral (ou « littéral de chaîne ») Valeur chaîne écrite explicitement en code, sous forme de valeur texte encadrée par des guillemets droits simples ou doubles. Sous-chaîne Définit une chaîne qui fait partie d’une autre chaîne. Unicode Système standardisé de codage permettant de représenter du texte sous forme de caractères et symboles dans les programmes informatiques. Le système Unicode permet d’utiliser la totalité des caractères de toutes les langues écrites existantes. Création de chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe String permet de représenter des données de chaîne (texte) en ActionScript 3.0. Les chaînes ActionScript prennent en charge les caractères ASCII et Unicode. La meilleure façon de créer une chaîne est d’utiliser un littéral de chaîne. Pour déclarer un littéral de chaîne, utilisez les guillemets droits doubles (") ou les guillemets droits simples ('). Par exemple, les deux chaînes suivantes sont équivalentes : var str1:String = "hello"; var str2:String = 'hello'; Vous pouvez également déclarer une chaîne à l’aide de l’opérateur new, comme suit : var str1:String = new String("hello"); var str2:String = new String(str1); var str3:String = new String(); // str3 == "" Les deux chaînes suivantes sont équivalentes : var str1:String = "hello"; var str2:String = new String("hello"); Pour utiliser des guillemets droits simples (') dans un littéral de chaîne délimité par des guillemets droits simples ('), utilisez le caractère d’échappement (\). De même, pour utiliser des guillemets droits doubles ('') dans un littéral de chaîne délimité par des guillemets droits doubles (''), utilisez le caractère d’échappement (\). Les deux chaînes suivantes sont équivalentes : var str1:String = "That's \"A-OK\""; var str2:String = 'That\'s "A-OK"'; Vous pouvez utiliser des guillemets simples ou des guillemets doubles en fonction de ceux qui existent dans un littéral de chaîne, comme dans l’exemple suivant : var str1:String = "ActionScript 3.0"; var str2:String = 'banana'; Rappelons qu’ActionScript fait la distinction entre les guillemets droits simples (') et les guillemets simples gauches ou droits (' ou ' ). Il en est de même pour les guillemets doubles. Utilisez des guillemets droits pour délimiter des littéraux de chaîne. Lorsque vous collez du texte dans ActionScript depuis une autre source, utilisez les caractères corrects. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 12 Utilisation des chaînes Dernière mise à jour le 27/4/2013 Comme indiqué dans le tableau suivant, vous pouvez utiliser le caractère d’échappement (\) pour définir d’autres caractères dans des littéraux de chaîne : Propriété length Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Chaque chaîne possède une propriété length correspondant au nombre de caractères qu’elle contient: var str:String = "Adobe"; trace(str.length); // output: 5 Une chaîne vide et une chaîne null ont toutes deux une longueur de 0, comme l’indique l’exemple suivant : var str1:String = new String(); trace(str1.length); // output: 0 str2:String = ''; trace(str2.length); // output: 0 Utilisation de caractères dans des chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Chaque caractère d’une chaîne possède une position d’index dans la chaîne (un entier). La position d’index du premier caractère est 0. Par exemple, dans la chaîne suivante, le caractère y occupe la position 0 et le caractère w occupe la position 5 : "yellow" Vous pouvez examiner des caractères individuels à différentes positions d’une chaîne à l’aide des méthodes charAt() et charCodeAt(), comme dans l’exemple suivant : Séquence d’échappement Caractère \b Retour arrière \f Changement de page \n Nouvelle ligne \r Retour chariot \t Tabulation \unnnn Caractère Unicode dont le code de caractère est spécifié par le nombre hexadécimal nnnn ; par exemple, \u263a est le caractère smiley. \\xnn Caractère ASCII dont le code est spécifié par le nombre hexadécimal nn. \' Guillemet droit simple \" Guillemet droit double \\ Barre oblique inverse GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 13 Utilisation des chaînes Dernière mise à jour le 27/4/2013 var str:String = "hello world!"; for (var i:int = 0; i < str.length; i++) { trace(str.charAt(i), "-", str.charCodeAt(i)); } Lorsque vous exécutez ce code, vous obtenez le résultat suivant : h - 104 e - 101 l - 108 l - 108 o - 111 - 32 w - 119 o - 111 r - 114 l - 108 d - 100 ! - 33 Vous pouvez également utiliser des codes de caractère pour définir une chaîne à l’aide de la méthode fromCharCode(), comme l’indique l’exemple suivant : var myStr:String = String.fromCharCode(104,101,108,108,111,32,119,111,114,108,100,33); // Sets myStr to "hello world!" Comparaison de chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser les opérateurs suivants pour comparer des chaînes : <, <=, !=, ==, => et >. Vous pouvez utiliser ces opérateurs avec des instructions conditionnelles (if et while, par exemple) comme l’indique l’exemple suivant : var str1:String = "Apple"; var str2:String = "apple"; if (str1 < str2) { trace("A < a, B < b, C < c, ..."); } Lorsque vous utilisez ces opérateurs avec des chaînes, ActionScript considère la valeur du code de chaque caractère dans la chaîne, en comparant les caractères de gauche à droite, comme indiqué ci-dessous : trace("A" < "B"); // true trace("A" < "a"); // true trace("Ab" < "az"); // true trace("abc" < "abza"); // true Utilisez les opérateurs == et != pour comparer des chaînes entre elles et pour comparer des chaînes avec d’autres types d’objets, comme l’indique l’exemple suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 14 Utilisation des chaînes Dernière mise à jour le 27/4/2013 var str1:String = "1"; var str1b:String = "1"; var str2:String = "2"; trace(str1 == str1b); // true trace(str1 == str2); // false var total:uint = 1; trace(str1 == total); // true Récupération des représentations de chaîne d’autres objets Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez obtenir une représentation de chaîne de n’importe quel type d’objet. Tous les objets disposent en effet d’une méthode toString() : var n:Number = 99.47; var str:String = n.toString(); // str == "99.47" Lorsque vous utilisez l’opérateur de concaténation + avec une combinaison d’objet String et d’objets qui ne sont pas des chaînes, vous n’avez pas besoin d’utiliser la méthode toString(). Pour plus d’informations sur la concaténation, voir la section suivante. La fonction globale String() renvoie la même valeur pour un objet donné que la valeur renvoyée par l’objet appelant la méthode toString(). Concaténation de chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La concaténation de chaînes consiste à prendre deux chaînes et à les combiner en une seule chaîne de façon séquentielle. Par exemple, vous pouvez utiliser l’opérateur + pour concaténer deux chaînes : var str1:String = "green"; var str2:String = "ish"; var str3:String = str1 + str2; // str3 == "greenish" Vous pouvez également utiliser l’opérateur += pour obtenir le même résultat, comme dans l’exemple suivant : var str:String = "green"; str += "ish"; // str == "greenish" En outre, la classe String comprend la méthode concat(), utilisable comme suit : var str1:String = "Bonjour"; var str2:String = "from"; var str3:String = "Paris"; var str4:String = str1.concat(" ", str2, " ", str3); // str4 == "Bonjour from Paris" Si vous utilisez l’opérateur + (ou l’opérateur +=) avec un objet String et un objet qui n’est pas une chaîne, ActionScript convertit automatiquement ce dernier en un objet String afin d’évaluer l’expression, comme indiqué dans l’exemple : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 15 Utilisation des chaînes Dernière mise à jour le 27/4/2013 var str:String = "Area = "; var area:Number = Math.PI * Math.pow(3, 2); str = str + area; // str == "Area = 28.274333882308138" Néanmoins, vous pouvez utiliser des parenthèses pour le regroupement afin de fournir un contexte à l’opérateur +, comme indiqué dans l’exemple suivant : trace("Total: $" + 4.55 + 1.45); // output: Total: $4.551.45 trace("Total: $" + (4.55 + 1.45)); // output: Total: $6 Recherche de sous-chaînes et de modèles dans des chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les sous-chaînes sont des caractères consécutifs à l’intérieur d’une chaîne. La chaîne "abc", par exemple, contient les sous-chaînes suivantes : "", "a", "ab", "abc", "b", "bc", "c". Vous pouvez utiliser des méthodes ActionScript pour localiser les sous-chaînes d’une chaîne. Les modèles sont définis en ActionScript par des chaînes ou par des expressions régulières. Par exemple, l’expression régulière suivante définit un modèle spécifique, les lettres A, B, et C suivies d’un chiffre (les barres de fraction sont des délimiteurs d’expression régulière) : /ABC\d/ ActionScript comporte des méthodes servant à rechercher des modèles dans des chaînes et à remplacer les correspondances trouvées par des sous-chaînes de substitution. Ces méthodes sont décrites dans les sections suivantes. Les expressions régulières peuvent définir des modèles compliqués. Pour plus d’informations, voir « Utilisation d’expressions régulières » à la page 78. Recherche d’une sous-chaîne par la position d’un caractère Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les méthodes substr() et substring() sont similaires. Elles renvoient toutes les deux une sous-chaîne d’une chaîne. Elles prennent deux paramètres. Dans les deux méthodes, le premier paramètre est la position du caractère initial dans la chaîne concernée. Toutefois, dans la méthode substr(), le deuxième paramètre est la longueur de la sous-chaîne à renvoyer, alors que dans la méthode substring(), le deuxième paramètre est la position du caractère final de la souschaîne (qui ne figure pas dans la chaîne renvoyée). Cet exemple illustre la différence entre ces deux méthodes : var str:String = "Hello from Paris, Texas!!!"; trace(str.substr(11,15)); // output: Paris, Texas!!! trace(str.substring(11,15)); // output: Pari La méthode slice() fonctionne de la même façon que la méthode substring(). Lorsque deux nombres entiers non négatifs sont passés en paramètres, son fonctionnement est identique. Néanmoins, la méthode slice() peut recevoir des entiers négatifs comme paramètres. Dans ce cas, la position des caractères est comptée à partir de la fin de la chaîne, comme dans l’exemple suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 16 Utilisation des chaînes Dernière mise à jour le 27/4/2013 var str:String = "Hello from Paris, Texas!!!"; trace(str.slice(11,15)); // output: Pari trace(str.slice(-3,-1)); // output: !! trace(str.slice(-3,26)); // output: !!! trace(str.slice(-3,str.length)); // output: !!! trace(str.slice(-8,-3)); // output: Texas Vous pouvez associer des entiers positifs et négatifs comme paramètres de la méthode slice(). Recherche de la position des caractères d’une sous-chaîne correspondante Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser les méthodes indexOf() et lastIndexOf() pour localiser des sous-chaînes correspondantes au sein d’une chaîne, comme dans l’exemple suivant : var str:String = "The moon, the stars, the sea, the land"; trace(str.indexOf("the")); // output: 10 La méthode indexOf() est sensible à la casse. Vous pouvez spécifier un deuxième paramètre pour indiquer la position de l’index dans la chaîne à partir de laquelle commencer la recherche, comme suit : var str:String = "The moon, the stars, the sea, the land" trace(str.indexOf("the", 11)); // output: 21 La méthode lastIndexOf() trouve la dernière occurrence d’une sous-chaîne dans la chaîne : var str:String = "The moon, the stars, the sea, the land" trace(str.lastIndexOf("the")); // output: 30 Si vous incluez un deuxième paramètre avec la méthode lastIndexOf(), la recherche est effectuée à l’envers à partir de cette position d’index dans la chaîne (de droite à gauche) : var str:String = "The moon, the stars, the sea, the land" trace(str.lastIndexOf("the", 29)); // output: 21 Création d’un tableau de sous-chaînes segmenté par un délimiteur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser la méthode split() pour créer un tableau de sous-chaînes divisé en fonction d’un caractère délimiteur. Par exemple, vous pouvez segmenter une chaîne séparée par des virgules ou des tabulations en plusieurs chaînes. L’exemple suivant indique comment diviser un tableau en sous-chaînes avec le caractère esperluette (&) comme délimiteur : var queryStr:String = "first=joe&last=cheng&title=manager&StartDate=3/6/65"; var params:Array = queryStr.split("&", 2); // params == ["first=joe","last=cheng"] Le deuxième paramètre de la méthode split() (qui est facultatif) définit la taille maximale du tableau renvoyé. Vous pouvez également utiliser une expression régulière comme caractère délimiteur : var str:String = "Give me\t5." var a:Array = str.split(/\s+/); // a == ["Give","me","5."] GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 17 Utilisation des chaînes Dernière mise à jour le 27/4/2013 Pour plus d’informations, voir « Utilisation d’expressions régulières » à la page 78 et le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Recherche de modèles dans des chaînes et remplacement de sous-chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe String comprend les méthodes suivantes pour utiliser des modèles dans des chaînes : • Utilisez les méthodes match() et search() pour localiser des sous-chaînes qui correspondent à un modèle. • Utilisez la méthode replace() pour rechercher des sous-chaînes qui correspondent à un modèle et les remplacer par une sous-chaîne spécifiée. Ces méthodes sont décrites dans les sections suivantes. Vous pouvez utiliser des chaînes ou des expressions régulières pour définir des modèles utilisés dans ces méthodes. Pour plus d’informations sur les expressions régulières, voir « Utilisation d’expressions régulières » à la page 78. Recherche de sous-chaînes correspondantes La méthode search() renvoie la position de l’index de la première sous-chaîne qui correspond à un modèle donné, comme illustré dans cet exemple : var str:String = "The more the merrier."; // (This search is case-sensitive.) trace(str.search("the")); // output: 9 Vous pouvez également utiliser des expressions régulières pour définir le modèle pour lequel établir une correspondance, comme illustré dans cet exemple : var pattern:RegExp = /the/i; var str:String = "The more the merrier."; trace(str.search(pattern)); // 0 Le résultat de la méthode trace() est 0, car le premier caractère dans la chaîne est la position de l’index 0. L’indicateur i est défini dans l’expression régulière. Par conséquent, la recherche n’est pas sensible à la casse. La méthode search() trouve une seule correspondance et renvoie sa position d’index de début, même si l’indicateur g (global) est défini dans l’expression régulière. L’exemple suivant présente une expression régulière plus compliquée qui correspond à une chaîne dans des guillemets doubles : var pattern:RegExp = /"[^"]*"/; var str:String = "The \"more\" the merrier."; trace(str.search(pattern)); // output: 4 str = "The \"more the merrier."; trace(str.search(pattern)); // output: -1 // (Indicates no match, since there is no closing double quotation mark.) La méthode match() fonctionne de façon similaire. Elle recherche une sous-chaîne correspondante. Néanmoins, lorsque vous utilisez l’indicateur global dans un modèle d’expression régulière (comme dans l’exemple suivant), match() renvoie un tableau de sous-chaînes correspondantes : var str:String = "bob@example.com, omar@example.org"; var pattern:RegExp = /\w*@\w*\.[org|com]+/g; var results:Array = str.match(pattern); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 18 Utilisation des chaînes Dernière mise à jour le 27/4/2013 Le tableau results est défini comme suit : ["bob@example.com","omar@example.org"] Pour plus d’informations sur les expressions régulières, voir « Utilisation d’expressions régulières » à la page 78. Remplacement de sous-chaînes mises en correspondance Vous pouvez utiliser la méthode replace() pour rechercher un modèle spécifié dans une chaîne et remplacer les correspondances par la chaîne de remplacement spécifiée, comme illustré dans l’exemple suivant : var str:String = "She sells seashells by the seashore."; var pattern:RegExp = /sh/gi; trace(str.replace(pattern, "sch")); //sche sells seaschells by the seaschore. Dans cet exemple, les chaînes mises en correspondance ne sont pas sensibles à la casse car l’indicateur i (ignoreCase) est défini dans l’expression régulière, et plusieurs correspondances sont remplacées car l’indicateur g (global) est défini. Pour plus d’informations, voir « Utilisation d’expressions régulières » à la page 78. Vous pouvez inclure les codes de remplacement $ suivants dans la chaîne de remplacement. Le texte de remplacement indiqué dans le tableau suivant est inséré à la place du code de remplacement $ : L’exemple suivant illustre l’utilisation des codes de remplacement $2 et $1, qui représentent le premier et le deuxième groupes capturés correspondants : var str:String = "flip-flop"; var pattern:RegExp = /(\w+)-(\w+)/g; trace(str.replace(pattern, "$2-$1")); // flop-flip Vous pouvez également utiliser une fonction comme deuxième paramètre de la méthode replace(). Le texte correspondant est remplacé par la valeur renvoyée de la fonction. Code $ Texte de remplacement $$ $ $& Sous-chaîne correspondante. $` Partie de la chaîne qui précède la sous-chaîne correspondante. Ce code utilise les guillemets simples droits gauches (`) et non les guillemets simples droits (') ni les guillemets simples anglais gauches (' ). $' Partie de la chaîne qui suit la sous-chaîne correspondante. Ce code utilise les guillemets simples droits (' ). $n nième groupe entre parenthèses correspondant capturé, où n est un chiffre compris entre 1 et 9 et $n n’est pas suivi d’une décimale. $nn nnième groupe entre parenthèses correspondant capturé, où nn est un nombre décimal à deux chiffres compris entre 01 et 99. Si la nnième capture n’est pas définie, le texte de remplacement est une chaîne vide. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 19 Utilisation des chaînes Dernière mise à jour le 27/4/2013 var str:String = "Now only $9.95!"; var price:RegExp = /\$([\d,]+.\d+)+/i; trace(str.replace(price, usdToEuro)); function usdToEuro(matchedSubstring:String, capturedMatch1:String, index:int, str:String):String { var usd:String = capturedMatch1; usd = usd.replace(",", ""); var exchangeRate:Number = 0.853690; var euro:Number = parseFloat(usd) * exchangeRate; const euroSymbol:String = String.fromCharCode(8364); return euro.toFixed(2) + " " + euroSymbol; } Lorsque vous utilisez une fonction comme deuxième paramètre de la méthode replace(), les arguments suivants sont transmis à la fonction : • La partie correspondante de la chaîne. • Tout groupe entre parenthèses capturé correspondant. Le nombre d’arguments transmis de cette façon varie selon le nombre de correspondances entre parenthèses. Pour déterminer le nombre de correspondances entre parenthèses, vérifiez arguments.length - 3 dans le code de la fonction. • La position d’index dans la chaîne où débute la correspondance. • La chaîne complète. Conversion de la casse dans des chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Comme illustré dans l’exemple suivant, les méthodes toLowerCase() et toUpperCase() convertissent les caractères alphabétiques de la chaîne en minuscule et en majuscule, respectivement : var str:String = "Dr. Bob Roberts, #9." trace(str.toLowerCase()); // dr. bob roberts, #9. trace(str.toUpperCase()); // DR. BOB ROBERTS, #9. Une fois que ces méthodes sont exécutées, la chaîne source reste inchangée. Pour transformer la chaîne source, utilisez le code suivant : str = str.toUpperCase(); Ces méthodes fonctionnent avec des caractères étendus, pas simplement a–z et A–Z : var str:String = "José Barça"; trace(str.toUpperCase(), str.toLowerCase()); // JOSÉ BARÇA josé barça GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 20 Utilisation des chaînes Dernière mise à jour le 27/4/2013 Exemple de chaîne : ASCII Art Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Cet exemple ASCII Art représente différentes façons d’utiliser la classe String en ActionScript 3.0, notamment : • La méthode split() de la classe String est utilisée pour extraire des valeurs d’une chaîne séparée par des caractères (informations d’image dans un fichier de texte séparé par des tabulations). • Plusieurs techniques de manipulation de chaînes, y compris split(), la concaténation et l’extraction d’une partie de la chaîne à l’aide de substring() et de substr(), sont utilisées pour mettre la première lettre de chaque mot dans les titres d’image en majuscule. • La méthode getCharAt() est utilisée pour obtenir un seul caractère à partir d’une chaîne (pour déterminer le caractère ASCII correspondant à une valeur bitmap d’échelle de gris). • La concaténation de chaîne est utilisée pour construire la représentation ASCII art d’une image, un caractère à la fois. Le terme ASCII art fait référence à des représentations textuelles d’une image dans lesquelles une grille de polices de caractères à espacement constant (caractères Courier New, par exemple) trace l’image. L’image suivante est un exemple d’ASCII art produit par l’application : La version ASCII art du graphique est illustrée à droite. Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers de l’application ASCIIArt se trouvent dans le dossier Samples/AsciiArt. L’application se compose des fichiers suivants : Fichier Description AsciiArtApp.mxml ou AsciiArtApp.fla Fichier d’application principal en FLA pour Flash ou en MXML pour Flex com/example/programmingas3/asciiArt/AsciiArtBuilder.as La classe qui fournit la fonctionnalité principale de l’application, notamment l’extraction de métadonnées d’image d’un fichier de texte, le chargement des images et la gestion du processus de conversion d’image en texte. com/example/programmingas3/asciiArt/BitmapToAsciiConverter.as Une classe qui fournit la méthode parseBitmapData() pour convertir des données d’image dans une version String. com/example/programmingas3/asciiArt/Image.as Une classe qui représente une image bitmap chargée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 21 Utilisation des chaînes Dernière mise à jour le 27/4/2013 Extraction de valeurs séparées par des tabulations Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Cet exemple utilise le stockage séparé de données d’application par rapport à l’application ; de cette façon, si les données changent (par exemple, si une autre image est ajoutée ou que le titre d’une image change), il est inutile de recréer le fichier SWF. Dans ce cas, les métadonnées d’image, y compris le titre de l’image, l’URL du fichier d’image réel et certaines valeurs utilisées pour manipuler l’image, sont stockés dans un fichier de texte (le fichier txt/ImageData.txt dans le projet). Le contenu du fichier de texte est le suivant : FILENAMETITLEWHITE_THRESHHOLDBLACK_THRESHHOLD FruitBasket.jpgPear, apple, orange, and bananad810 Banana.jpgA picture of a bananaC820 Orange.jpgorangeFF20 Apple.jpgpicture of an apple6E10 Le fichier utilise un format séparé par des tabulations spécifique. La première ligne est une ligne d’en-tête. Les lignes restantes contiennent les données suivantes pour chaque bitmap à charger : • Le nom de fichier du bitmap. • Le nom d’affichage du bitmap. • Les valeurs de seuil du blanc et les valeurs de seuil du noir pour les bitmaps. Il s’agit de valeurs hexadécimales audessus et en dessous desquelles un pixel doit être considéré comme totalement blanc ou totalement noir. Dès que l’application démarre, la classe AsciiArtBuilder se charge et analyse le contenu du fichier de texte afin de créer la « pile » d’images qu’elle chargera. Pour cela, elle utilise le code suivant de la méthode parseImageInfo() de la classe AsciiArtBuilder : com/example/programmingas3/asciiArt/ImageInfo.as Une classe représentant des métadonnées pour une image ASCII art (titre, URL de fichier image, etc.). image/ Un dossier contenant des images utilisées par l’application. txt/ImageData.txt Un fichier de texte séparé par des tabulations et contenant des informations sur les images à charger par l’application. Fichier Description GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 22 Utilisation des chaînes Dernière mise à jour le 27/4/2013 var lines:Array = _imageInfoLoader.data.split("\n"); var numLines:uint = lines.length; for (var i:uint = 1; i < numLines; i++) { var imageInfoRaw:String = lines[i]; ... if (imageInfoRaw.length > 0) { // Create a new image info record and add it to the array of image info. var imageInfo:ImageInfo = new ImageInfo(); // Split the current line into values (separated by tab (\t) // characters) and extract the individual properties: var imageProperties:Array = imageInfoRaw.split("\t"); imageInfo.fileName = imageProperties[0]; imageInfo.title = normalizeTitle(imageProperties[1]); imageInfo.whiteThreshold = parseInt(imageProperties[2], 16); imageInfo.blackThreshold = parseInt(imageProperties[3], 16); result.push(imageInfo); } } Le contenu entier du fichier de texte se trouve dans une seule occurrence de String, la propriété _imageInfoLoader.data. Vous pouvez utiliser la méthode split() avec le caractère de nouvelle ligne ("\n") comme paramètre pour diviser l’occurrence de String en un tableau (lines) dont les éléments sont les lignes individuelles du fichier de texte. Le code utilise ensuite une boucle pour travailler avec chacune des lignes (excepté la première car elle contient uniquement des en-têtes). A l’intérieur de la boucle, la méthode split() est de nouveau utilisée pour diviser le contenu de la ligne en un ensemble de valeurs (l’objet Array appelé imageProperties). Le paramètre utilisé avec la méthode split() dans ce cas est le caractère de tabulation ("\t") car les valeurs dans chaque ligne sont délimitées par des tabulations. Utilisation de méthodes String pour normaliser des titres d’image Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans cette application, tous les titres d’image sont affichés à l’aide d’un format standard, avec la première lettre de chaque mot en majuscule (excepté quelques mots qui ne sont généralement pas en majuscule dans des titres anglais). Au lieu de considérer que le fichier de texte contient des titres formatés correctement, l’application formate les titres lors de leur extraction du fichier de texte. Dans la liste de code précédente, lors de l’extraction de valeurs de métadonnées d’image individuelles, la ligne de code suivante est utilisée : imageInfo.title = normalizeTitle(imageProperties[1]); Dans ce code, le titre de l’image issu du fichier de texte est transmis au moyen de la méthode normalizeTitle() avant d’être stocké dans l’objet ImageInfo : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 23 Utilisation des chaînes Dernière mise à jour le 27/4/2013 private function normalizeTitle(title:String):String { var words:Array = title.split(" "); var len:uint = words.length; for (var i:uint; i < len; i++) { words[i] = capitalizeFirstLetter(words[i]); } return words.join(" "); } Cette méthode utilise la méthode split() pour diviser le titre en mots individuels (séparés par le caractère d’espacement), transmet chaque mot au moyen de la méthode capitalizeFirstLetter() puis utilise la méthode join() de la classe Array pour combiner de nouveau les mots en une chaîne unique. Comme son nom l’indique, la méthode capitalizeFirstLetter() met la première lettre de chaque mot en majuscule : /** * Capitalizes the first letter of a single word, unless it's one of * a set of words that are normally not capitalized in English. */ private function capitalizeFirstLetter(word:String):String { switch (word) { case "and": case "the": case "in": case "an": case "or": case "at": case "of": case "a": // Don't do anything to these words. break; default: // For any other word, capitalize the first character. var firstLetter:String = word.substr(0, 1); firstLetter = firstLetter.toUpperCase(); var otherLetters:String = word.substring(1); word = firstLetter + otherLetters; } return word; } En anglais, le premier caractère des mots suivants utilisés dans un titre n’est pas mis en majuscule : “and,” “the,” “in,” “an,” “or,” “at,” “of,” ou “a.” (il s’agit d’une version simplifiée des règles). Pour exécuter cette logique, le code utilise d’abord une instruction switch pour vérifier si le mot est l’un des mots ne devant pas être en majuscule. Si c’est le cas, le code sort de l’instruction switch. Si le mot doit être en majuscule, la procédure comprend plusieurs étapes : 1 La première lettre du mot est extraite à l’aide de substr(0, 1), qui extraie une sous-chaîne commençant par le caractère au niveau de l’index 0 (la première lettre de la chaîne, comme indiqué par le premier paramètre 0). La sous-chaîne contiendra un caractère (indiqué par le deuxième paramètre 1). 2 Ce caractère est mis en majuscule à l’aide de la méthode toUpperCase(). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 24 Utilisation des chaînes Dernière mise à jour le 27/4/2013 3 Les caractères restants du mot d’origine sont extraits à l’aide de substring(1), qui extraie une sous-chaîne commençant à l’index 1 (la deuxième lettre) jusqu’à la fin de la chaîne (indiqué en omettant le deuxième paramètre de la méthode substring()). 4 Le dernier mot est créé en combinant la première lettre mise en majuscule et les lettres restantes en utilisant la concaténation de chaîne : firstLetter + otherLetters Génération du texte ASCII art Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe BitmapToAsciiConverter permet de convertir une image bitmap en sa représentation de texte ASCII. Cette procédure est effectuée par la méthode parseBitmapData(), partiellement représentée ici : var result:String = ""; // Loop through the rows of pixels top to bottom: for (var y:uint = 0; y < _data.height; y += verticalResolution) { // Within each row, loop through pixels left to right: for (var x:uint = 0; x < _data.width; x += horizontalResolution) { ... // Convert the gray value in the 0-255 range to a value // in the 0-64 range (since that's the number of "shades of // gray" in the set of available characters): index = Math.floor(grayVal / 4); result += palette.charAt(index); } result += "\n"; } return result; Ce code définit d’abord une occurrence de String appelée result qui sera utilisée pour créer la version ASCII art de l’image bitmap. Il effectue ensuite une boucle sur les pixels de l’image bitmap source. Il utilise plusieurs techniques de manipulation des couleurs (non décrites ici) pour convertir le rouge, le vert et le bleu d’un pixel en une valeur d’échelle de gris (un nombre entre 0 et 255). Le code divise ensuite cette valeur par 4 (comme indiqué) pour la convertir en une valeur dans l’échelle 0-63, qui est stockée dans la variable index (l’échelle 0-63 est utilisée car la palette des caractères ASCII disponibles utilisée par cette application contient 64 valeurs). La palette des caractères est définie en tant qu’occurrence de String dans la classe BitmapToAsciiConverter : // The characters are in order from darkest to lightest, so that their // position (index) in the string corresponds to a relative color value // (0 = black). private static const palette:String = "@#$%&8BMW*mwqpdbkhaoQ0OZXYUJCLtfjzxnuvcr[]{}1()|/?Il!i><+_~-;,. "; Etant donné que la variable index définit le caractère ASCII de la palette qui correspond au pixel actuel dans l’image bitmap, ce caractère est récupéré de la palette String à l’aide de la méthode charAt(). Il est ensuite ajouté à l’occurrence de String result au moyen de l’opérateur d’affectation de concaténation (+=). En outre, à la fin de chaque ligne de pixels, un caractère de nouvelle ligne est concaténé à la fin de l’occurrence de String result afin que la ligne à renvoyer crée une ligne de pixels de caractères. 25 Dernière mise à jour le 27/4/2013 Chapitre 3 : Utilisation de tableaux Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les tableaux vous permettent de stocker plusieurs valeurs dans une seule structure de données. Vous pouvez utiliser des tableaux indexés simples qui stockent des valeurs à l’aide d’index d’entiers ordinaux fixes ou des tableaux associatifs complexes qui stockent des valeurs à l’aide de clés arbitraires. Les tableaux peuvent également être multidimensionnels et contenir des éléments étant eux-mêmes des tableaux. Pour finir, vous pouvez utiliser un vecteur pour les tableaux dont les éléments sont tous des occurrences du même type de données. Voir aussi Array Vecteur Principes de base des tableaux Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous aurez souvent besoin en programmation d’utiliser un ensemble d’éléments plutôt qu’un seul objet; par exemple, dans une application de lecteur de musique, vous pouvez avoir une liste de morceaux en attente de lecture. Vous ne souhaitez pas créer une variable séparée pour chaque morceau de cette liste. Il serait préférable de rassembler tous les objets Song et de les utiliser sous forme de groupe. Un tableau est un élément de programmation qui agit comme conteneur pour un ensemble d’éléments (une liste de morceaux, par exemple). La plupart du temps, tous les éléments d’un tableau sont des occurrences de la même classe, mais ceci n’est pas obligatoire dans ActionScript. Les éléments individuels d’un tableau sont les éléments du tableau. Un tableau peut être comparé à un tiroir classeur pour des variables. Les variables peuvent être ajoutées en tant qu’éléments au tableau, comme vous placez un dossier dans le tiroir classeur. Vous pouvez utiliser le tableau comme une variable unique, comme si vous transportiez le tiroir entier à un autre endroit. Vous pouvez utiliser les variables en tant que groupe, comme si vous recherchiez des informations dans les dossiers en les parcourant l’un après l’autre. Vous pouvez y accéder individuellement, comme si vous ouvriez le tiroir et sélectionniez un seul dossier. Par exemple, imaginez que vous créez une application de lecteur de musique dans laquelle un utilisateur peut sélectionner plusieurs morceaux et les ajouter à une liste de lecture. Dans votre code ActionScript, vous avez une méthode appelée addSongsToPlaylist() qui accepte un seul tableau comme paramètre. Peu importe le nombre de morceaux à ajouter à la liste (quelques-uns, un grand nombre, ou même un seul), vous devez appeler la méthode addSongsToPlaylist() une seule fois, en lui transmettant le tableau qui contient les objets Song. Dans la méthode addSongsToPlaylist(), vous pouvez utiliser une boucle pour parcourir les éléments (morceaux) du tableau un par un et les ajouter à la liste de lecture. Le type de tableau ActionScript le plus courant est le tableau indexé. Dans un tableau indexé, chaque élément est stocké dans un emplacement numéroté appelé index. On accède à des éléments à l’aide du numéro, comme une adresse. Les tableaux indexés répondent à la plupart des besoins en programmation. La classe Array est une classe courante utilisée pour représenter un tableau indexé. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 26 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Un tableau indexé est souvent utilisé pour stocker plusieurs éléments du même type, des objets qui sont des occurrences de la même classe. La classe Array ne dispose pas de moyens pour restreindre le type d’éléments qu’elle contient. La classe Vector est un type de tableau indexé dans lequel tous les éléments d’un tableau unique sont du même type. L’utilisation d’une occurrence de Vector à la place d’une occurrence de Array peut également déboucher sur une amélioration des performances entre autres. la classe Vector est prise en charge à partir de Flash Player 10 et Adobe AIR 1.5. Une utilisation spéciale d’un tableau indexé est un tableau multidimensionnel. Un tableau multidimensionnel est un tableau indexé dont les éléments sont des tableaux indexés, qui contiennent à leur tour d’autres éléments. Le tableau associatif est un autre type de tableau. Il utilise une chaîne key au lieu d’un index numérique pour identifier des éléments individuels. Enfin, ActionScript 3.0 comprend également une classe Dictionary qui représente un dictionnaire. Un dictionnaire est un tableau qui vous permet d’utiliser tout type d’objet comme clé afin de distinguer les éléments entre eux. Concepts importants et terminologie La liste de référence suivante contient des termes importants utilisés dans le cadre de la programmation de routines qui gèrent des tableaux et des vecteurs : Array Objet qui sert de conteneur pour regrouper plusieurs objets. Opérateur ([]) d’accès au tableau Paire de crochets entourant un index ou une clé qui identifie de façon unique un élément du tableau. Cette syntaxe est utilisée après le nom d’une variable de tableau pour spécifier un seul élément du tableau plutôt qu’un tableau entier. Tableau associatif Tableau qui utilise des clés de chaîne pour identifier des éléments individuels. Type de base Type de données des objets qu’une occurrence de Vector est autorisée à stocker. Dictionnaire Tableau dont les éléments sont constitués de paires d’objets appelées clé et valeur. La clé est utilisée à la place d’un index numérique pour identifier un seul élément. Elément Elément unique dans un tableau. Index Adresse numérique utilisée pour identifier un élément unique dans un tableau indexé. Tableau indexé Type de tableau standard qui stocke chaque élément dans une position numérotée et utilise le numéro (index) pour identifier des éléments individuels. Clé Chaîne ou objet utilisé pour identifier un seul élément dans un tableau associatif ou un dictionnaire. Tableau multidimensionnel Tableau contenant des éléments qui sont des tableaux plutôt que des valeurs uniques. T Convention standard utilisée dans la présente documentation pour représenter le type de base d’une occurrence de Vector, quel qu’il soit. La convention T est utilisée pour représenter un nom de classe, comme cela est indiqué dans la description du paramètre Type. (« T » correspond à « type », comme dans « type de données ».) Paramètre Type Syntaxe utilisée avec le nom de classe Vector pour spécifier le type de base de Vector (le type de données des objets qu’il stocke). La syntaxe consiste en un point (.), puis le nom du type de données entouré de parenthèses en chevron (<>). L’ensemble ressemble à ceci : Vector. Dans la présente documentation, la classe spécifiée dans le paramètre Type est représenté de façon générique par T. Vecteur Type de tableau dont les éléments sont tous des occurrences du même type de données. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 27 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Tableaux indexés Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les tableaux indexés stockent une série d’une ou de plusieurs valeurs organisées de façon à ce que vous puissiez accéder à chaque valeur à l’aide d’une valeur d’entier non signé. Le premier index correspond toujours au nombre 0. L’index est ensuite incrémenté d’une unité pour chaque élément ajouté consécutivement au tableau. Dans ActionScript 3.0, deux classes sont utilisées comme tableaux indexés : la classe Array et la classe Vector. Les tableaux indexés utilisent un entier 32 bits non signé pour le numéro d’index. La taille maximale d’un tableau indexé est 232 - 1 ou 4 294 967 295. Si vous tentez de créer un tableau plus grand que la taille maximale, une erreur d’exécution se produit. Pour accéder à un élément particulier d’un tableau indexé, vous pouvez utiliser l’opérateur ([]) d’accès au tableau pour spécifier la position de l’index de l’élément visé. Par exemple, le code suivant représente le premier élément (l’élément à l’index 0) dans un tableau indexé appelé songTitles : songTitles[0] La combinaison du nom de la variable du tableau suivi de l’index entre crochets fonctionne comme un identifiant unique. En d’autres termes, elle peut être utilisée tout comme un nom de variable. Vous pouvez affecter une valeur à un élément du tableau indexé en utilisant le nom et l’index du côté gauche d’une instruction d’affectation : songTitles[1] = "Symphony No. 5 in D minor"; Dans la même veine, vous pouvez récupérer une valeur à un élément du tableau indexé en utilisant le nom et l’index du côté droit d’une instruction d’affectation : var nextSong:String = songTitles[2]; Vous pouvez aussi utiliser une variable entre crochets plutôt que de fournir une valeur explicite. Elle doit contenir une valeur entière non-négative telle qu’un uint, un int positif ou une occurrence de Number d’entier positif. Cette technique est utilisée couramment pour passer en boucle sur les éléments dans un tableau indexé et effectuer une opération sur un ou tous les éléments. Le code ci-dessous décrit cette technique. Le code utilise une boucle pour accéder à chaque valeur dans un objet Array appelé oddNumbers. Il utilise l’instruction trace() pour imprimer chaque valeur sous la forme “oddNumber[index] = value” : var oddNumbers:Array = [1, 3, 5, 7, 9, 11]; var len:uint = oddNumbers.length; for (var i:uint = 0; i < len; i++) { trace("oddNumbers[" + i.toString() + "] = " + oddNumbers[i].toString()); } Classe Array La classe Array est le premier type de tableau indexé. Une occurrence de Array peut comporter une valeur de n’importe quel type de données. Le même objet Array peut comporter des objets qui sont de types de données différents. Par exemple, une occurrence de Array unique peut avoir une valeur String en index 0, une occurrence de Number en index 1 et un objet XML en index 2. Classe Vector La classe Vector est un autre type de tableau indexé qui est disponible dans ActionScript 3.0. Une occurrence de Vector est un tableau typé, ce qui signifie que tous les éléments d’une occurrence de Vector ont toujours le même type de données. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 28 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Remarque : la classe Vector est prise en charge à partir de Flash Player 10 et Adobe AIR 1.5. Lorsque vous déclarez une variable Vector ou que vous instanciez un objet Vector, vous spécifiez explicitement le type de données des objets que le vecteur peut contenir. Le type de données spécifié est connu sous le nom de type de base du vecteur. Lors de l’exécution et de la compilation (en mode strict), tout code qui fixe la valeur d’un élément Vector ou récupère une valeur d’un élément Vector est contrôlé. Si le type de données de l’objet que l’on tente d’ajouter ou de récupérer ne correspond pas au type de base du vecteur, une erreur se produit. Outre la restriction concernant le type de données, la classe Vector possède d’autres restrictions qui la distinguent de la classe Array : • Un vecteur est un tableau dense. Un objet Array peut comporter des valeurs dans les index 0 et 7 même si elle n’en a pas dans les positions 1 à 6. Cependant, un vecteur doit comporter une valeur (ou null) dans chaque index. • Un vecteur peut facultativement avoir une longueur fixe. Ceci signifie que le nombre d’éléments du vecteur est immuable. • L’accès aux éléments d’un vecteur est défini par ses limites. Vous ne pouvez jamais lire une valeur d’un index supérieur à celui de l’élément final (longueur - 1). Vous ne pouvez jamais définir une valeur avec un index supérieur à l’index final actuel. En d’autres termes, vous pouvez définir une valeur uniquement à l’index existant ou à une [longueur] d’index. En raison de ses restrictions, un vecteur présente trois avantages principaux par rapport à une occurrence d’Array dont les éléments sont tous des occurrences d’une classe unique : • Performance : l’accès à l’élément de tableau et son itération sont beaucoup plus rapides lorsque vous utilisez une occurrence de Vector que lorsque vous utilisez une occurrence d’Array. • Sécurité des types : en mode strict, le compilateur peut identifier les erreurs de type de données. Parmi ces erreurs, il y a l’affectation d’une valeur du type de données incorrect à un vecteur ou l’attente d’un type de données incompatible lors de la lecture d’une valeur à partir du vecteur. A l’exécution, les types de données sont également contrôlés lors de l’ajout de données à un objet Vector ou la lecture de données qui en provient. Notez cependant que lorsque vous utilisez la méthode push() ou unshift() pour ajouter des valeurs à un vecteur, les types de données des arguments ne sont pas vérifiés au moment de la compilation. Lorsque vous utilisez ces méthodes, les valeurs sont toujours contrôlées à l’exécution. • Fiabilité : le contrôle de gamme à l’exécution (ou contrôle de longueur fixe) assure une fiabilité nettement supérieure à celle des objets Array. A part les contraintes et les avantages supplémentaires, la classe Vector est très proche de la classe Array. Les propriétés et les méthodes d’un objet Vector sont similaires, voire dans certains cas identiques, aux propriétés et aux méthodes d’un objet Array. Au lieu d’utiliser un objet Array dont tous les éléments possèdent le même type de données, il est généralement préférable de faire appel à une occurrence de l’objet Vector. Création de tableaux Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser plusieurs techniques pour créer une occurrence de Array ou une occurrence de Vector. Cependant, les techniques de création de chaque type de tableau sont quelque peu différentes. Création d’une occurrence de Array Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous créez un objet Array par l’appel au constructeur Array( ou par l’utilisation d’une syntaxe de littéral de tableau. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 29 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Vous pouvez utiliser la fonction de constructeur Array() de trois façons différentes. Premièrement, si vous appelez le constructeur sans arguments, vous obtenez un tableau vide. Vous pouvez utiliser la propriété length de la classe Array pour vérifier que le tableau ne contient aucun élément. Par exemple, le code suivant appelle le constructeur Array() sans arguments : var names:Array = new Array(); trace(names.length); // output: 0 Deuxièmement, si vous utilisez un nombre comme unique paramètre pour le constructeur Array(), un tableau de cette longueur est créé, avec chaque valeur d’élément définie sur undefined. L’argument doit être un entier non signé compris entre les valeurs 0 et 4 294 967 295. Par exemple, le code suivant appelle le constructeur Array() avec un seul argument numérique : var names:Array = new Array(3); trace(names.length); // output: 3 trace(names[0]); // output: undefined trace(names[1]); // output: undefined trace(names[2]); // output: undefined Troisièmement, si vous appelez le constructeur et transmettez une liste d’éléments comme paramètres, un tableau est créé avec des éléments correspondant à chacun des paramètres. Le code suivant transmet trois arguments au constructeur Array() : var names:Array = new Array("John", "Jane", "David"); trace(names.length); // output: 3 trace(names[0]); // output: John trace(names[1]); // output: Jane trace(names[2]); // output: David Vous pouvez aussi créer des tableaux avec des littéraux de tableau. Un littéral de tableau peut être affecté directement à une variable de tableau, comme illustré dans l’exemple suivant : var names:Array = ["John", "Jane", "David"]; Création d’une occurrence de Vector Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous créez une occurrence de Vector par l’appel du constructeur Vector.(). Vous pouvez aussi créer un vecteur par l’appel à la fonction globale Vector.(). Cette fonction convertit un objet spécifié en une occurrence de Vector. Dans Flash Professional CS5 et les versions ultérieures, Flash Builder 4 et les versions ultérieures et Flex 4 et les versions ultérieures, vous pouvez également créer une occurrence de Vector à l’aide de la syntaxe de littéral correspondante. Toutes les fois que vous déclarez une variable Vector (ou de la même façon, un paramètre de la méthode Vector ou un type de renvoi de la méthode Vector), vous spécifiez le type de base de la variable Vector. Vous spécifiez également le type de base lorsque vous créez une occurrence de Vector par l’appel au constructeur Vector.(). Autrement dit, toutes les fois que vous utilisez le terme Vector dans ActionScript, il est accompagné d’un type de base. Vous spécifiez le type de base du vecteur à l’aide de la syntaxe de paramètres de type. Le paramètre de type suit immédiatement le mot Vector dans le code. Il est formé d’un point (.), puis du nom de classe de base entouré de parenthèses en chevron (<>), comme l’indique cet exemple : var v:Vector.; v = new Vector.(); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 30 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Dans la première ligne de cet exemple, la variable v est déclarée comme une occurrence de Vector.. En d’autres termes, il représente un tableau indexé qui ne peut comporter que des occurrences de String. La deuxième ligne appelle le constructeur Vector() pour créer une occurrence du même type Vector, c’est-à-dire un vecteur dont les éléments sont tous des objets String. Il affecte cet objet à v. Utilisation du constructeur Vector.() Si vous utilisez le constructeur Vector.() sans arguments, il crée une occurrence de Vector vide. Vous pouvez contrôler qu’un vecteur est vide en vérifiant sa propriété length. Par exemple, le code ci-dessus appelle le constructeur Vector.() sans arguments : var names:Vector. = new Vector.(); trace(names.length); // output: 0 Si vous savez d’avance de combien d’éléments un vecteur a besoin initialement, vous pouvez prédéfinir ce nombre dans le vecteur. Pour créer un vecteur avec un certain nombre d’éléments, transmettez le nombre d’éléments comme premier paramètre (le paramètre length). Comme les éléments du vecteur ne peuvent pas être vides, ils sont remplis d’occurrences du type de base. Si ce type est un type de référence qui autorise les valeurs null, les éléments contiennent tous null. Autrement, ils contiennent tous la valeur par défaut pour la classe. Par exemple, une variable uint ne peut pas être null. Par conséquent, dans le code ci-dessous, le vecteur appelé ages est créé avec sept éléments, chacun contenant la valeur 0. var ages:Vector. = new Vector.(7); trace(ages); // output: 0,0,0,0,0,0,0 Enfin, à l’aide du constructeur Vector.(), vous pouvez également créer un vecteur de longueur fixe en transmettant true comme deuxième paramètre (le paramètre fixed). Dans ce cas, le vecteur est créé avec le nombre spécifié d’éléments et celui-ci ne peut pas être modifié. Notez cependant que vous pouvez quand même changer les valeurs des éléments d’un vecteur de longueur fixe. Utilisation du constructeur de syntaxe de littéral Vector Dans Flash Professional CS5 et les versions ultérieures, Flash Builder 4 et les versions ultérieures et Flex 4 et les versions ultérieures, vous pouvez transmettre une liste de valeurs au constructeur Vector() pour stipuler les valeurs initiales du vecteur : // var v:Vector. = new [E0, ..., En-1 ,]; // For example: var v:Vector. = new [0,1,2,]; Cette syntaxe possède les caractéristiques suivantes : • La virgule de fin de ligne est facultative. • La syntaxe ne gère pas la présence d’éléments vides dans le tableau. Une instruction telle que var v:Vector. = new [0,,2,] renvoie une erreur de compilation. • Il est impossible de stipuler la longueur par défaut de l’occurrence de Vector. La longueur correspond au nombre d’éléments qui composent la liste d’initialisation. • Il est impossible de spécifier si l’occurrence de Vector possède une longueur fixe. Utilisez à cet effet la propriété fixed. • Il risque de se produire des pertes de données ou des erreurs si les éléments transmis en tant que valeurs ne correspondent pas au type indiqué. Exemple : var v:Vector. = new [4.2]; // compiler error when running in strict mode trace(v[0]); //returns 4 when not running in strict mode GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 31 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Utilisation du constructeur Vector. () Outre le constructeur Vector.() et le constructeur de syntaxe de littéral Vector, vous disposez également de la fonction globale Vector. () pour créer un objet Vector. La fonction globale Vector.() est une fonction de conversion. Lorsque vous appelez la fonction globale Vector.(), vous spécifiez le type de base du vecteur que la méthode renvoie. Vous transmettez un tableau indexé unique (occurrence de Array ou Vector) comme argument. La méthode renvoie alors un vecteur avec le type de base spécifié, contenant les valeurs dans l’argument du tableau source. Le code ci-dessous montre la syntaxe nécessaire pour appeler la fonction globale Vector.(). var friends:Vector. = Vector.(["Bob", "Larry", "Sarah"]); La fonction globale Vector.() exécute une conversion de type de base sur deux niveaux. D’abord, lorsqu’une occurrence de Array est transmise à la fonction, une occurrence de Vector est renvoyée. Ensuite, que le tableau source soit une occurrence de Array ou Vector, la fonction tente de convertir les éléments du tableau source en valeurs du type de base. La conversion utilise des règles standard de conversion des types de données ActionScript. Par exemple, le code suivant convertit les valeurs String du tableau source en nombres entiers dans le vecteur résultant. La partie décimale de la première ("1.5") est tronquée et la troisième valeur non numérique ("Waffles") est convertie en 0 dans le résultat : var numbers:Vector. = Vector.(["1.5", "17", "Waffles"]); trace(numbers); // output: 1,17,0 S’il n’est pas possible de convertir un élément source quelconque, une erreur se produit. Lorsque le code appelle la fonction globale Vector.(), si un élément du tableau source est une occurrence d’une sous-classe du type de base spécifié, l’élément est ajouté au vecteur résultant (aucune erreur ne se produit). L’utilisation de la fonction globale Vector.() est en fait le seul moyen de convertir un vecteur avec un type de base T en un vecteur avec un type de base qui est une superclasse de T. Insertion d’éléments de tableau Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’opérateur ([]) d’accès au tableau constitue le moyen le plus élémentaire d’ajouter un élément à un tableau indexé. Pour définir la valeur d’un élément de tableau indexé, utilisez le nom d’objet Array ou Vector et le numéro d’index du côté gauche d’une instruction d’affectation. songTitles[5] = "Happy Birthday"; Si un élément ne se trouve pas déjà à cette position d’index du tableau ou du vecteur, l’index est créé et la valeur y est stockée. Si une valeur existe à cet index, la nouvelle valeur remplace l’ancienne. Un objet Array vous permet de créer un élément pour tout index. Cependant, avec un objet Vector, vous pouvez affecter uniquement une valeur à un index existant ou à l’index disponible suivant. Celui-ci correspond à la propriété length de l’objet Vector. Utilisez du code comme celui qui est présenté ci-dessous pour ajouter un nouvel élément à un objet Vector de la façon la plus sûre : myVector[myVector.length] = valueToAdd; Trois méthodes des classes Array et Vector, push(), unshift() et splice(), vous permettent d’insérer des éléments dans un tableau indexé. La méthode push() ajoute un ou plusieurs éléments à la fin d’un tableau. Ainsi, le dernier élément inséré dans le tableau à l’aide de la méthode push() aura le numéro d’index le plus élevé. La méthode unshift() insère un ou plusieurs éléments au début d’un tableau, qui est toujours au numéro d’index 0. La méthode splice() insère des éléments au niveau d’un index spécifié dans le tableau. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 32 Utilisation de tableaux Dernière mise à jour le 27/4/2013 L’exemple suivant illustre les trois méthodes. Un tableau appelé planets est créé pour trier les noms des planètes par ordre de proximité par rapport au soleil. La méthode push() est tout d’abord appelée pour ajouter l’élément initial, Mars. Deuxièmement, la méthode unshift() est appelée pour insérer l’élément Mercury au début du tableau. Pour finir, la méthode splice() est appelée pour insérer les éléments Venus et Earth après Mercury, mais avant Mars. Le premier élément envoyé à splice(), l’entier 1, indique à l’insertion de débuter à l’index 1. Le deuxième argument envoyé à splice(), l’entier 0, indique qu’aucun élément ne doit être supprimé. Pour finir, les troisième et quatrième arguments envoyés à splice(), Venus et Earth, sont les éléments à insérer. var planets:Array = new Array(); planets.push("Mars"); // array contents: Mars planets.unshift("Mercury"); // array contents: Mercury,Mars planets.splice(1, 0, "Venus", "Earth"); trace(planets); // array contents: Mercury,Venus,Earth,Mars Les méthodes push() et unshift() renvoient toutes les deux un entier non signé qui représente la longueur du tableau modifié. La méthode splice() renvoie un tableau vide lorsqu’elle est utilisée pour insérer des éléments, ce qui semble étrange mais compréhensible en raison de saversatilité. Vous pouvez utiliser la méthode splice() non seulement pour insérer des éléments dans un tableau, mais également pour en supprimer. Lorsque vous l’utilisez pour supprimer des éléments, la méthode splice() renvoie un tableau contenant les éléments supprimés. Remarque : si une propriété fixed de l’objet Vector est définie sur true, le nombre total d’éléments du vecteur reste immuable. Si vous tentez d’ajouter un nouvel élément à un vecteur de longueur fixe à l’aide des techniques décrites ici, une erreur se produit. Récupération des valeurs et suppression des éléments du tableau Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Utilisez l’opérateur ([]) d’accès au tableau pour récupérer la valeur d’un élément de la façon la plus simple. Pour récupérer la valeur d’un élément de tableau indexé, utilisez le nom d’objet Array ou Vector et le numéro d’index du côté droit d’une instruction d’affectation. var myFavoriteSong:String = songTitles[3]; Il est possible d’essayer de récupérer une valeur à partir d’un tableau ou d’un vecteur à l’aide d’un index où aucun élément n’existe. Dans ce cas, un objet Array renvoie la valeur non définie et un vecteur renvoie une exception RangeError. Trois méthodes des classes Array et Vector, pop(), shift() et splice(), vous permettent de supprimer des éléments. La méthode pop() supprime un élément de la fin du tableau. En d’autres termes, elle supprime l’élément au niveau du numéro d’index le plus élevé. La méthode shift() supprime un élément du début du tableau, ce qui signifie qu’elle supprime toujours l’élément au numéro d’index 0. La méthode splice(), qui peut également être utilisée pour insérer des éléments, supprime un nombre arbitraire d’éléments en commençant au numéro d’index indiqué par le premier argument envoyé à la méthode. L’exemple suivant utilise les trois méthodes pour supprimer des éléments d’une occurrence d’Array. Un tableau nommé oceans est créé pour stocker les noms des océans. Certains noms dans le tableau sont des noms de lacs plutôt que des noms d’océans. Ils doivent donc être supprimés. Premièrement, la méthode splice() est utilisée pour supprimer les éléments Aral et Superior, et insérer les éléments Atlantic et Indian. Le premier argument envoyé à splice(), l’entier 2, indique que l’opération doit commencer par le troisième élément dans la liste, qui est à l’index 2. Le deuxième argument, 2, indique que deux éléments doivent être supprimés. Les arguments restants, Atlantic et Indian, sont des valeurs à insérer à l’index 2. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 33 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Deuxièmement, la méthode pop() est utilisée pour supprimer le dernier élément dans le tableau, Huron. Et troisièmement, la méthode shift() est utilisée pour supprimer le premier élément dans le tableau, Victoria. var oceans:Array = ["Victoria", "Pacific", "Aral", "Superior", "Indian", "Huron"]; oceans.splice(2, 2, "Arctic", "Atlantic"); // replaces Aral and Superior oceans.pop(); // removes Huron oceans.shift(); // removes Victoria trace(oceans);// output: Pacific,Arctic,Atlantic,Indian Les méthodes pop() et shift() renvoient toutes les deux l’élément qui a été supprimé. Pour une occurrence de Array, le type de données de la valeur renvoyée est Object car les tableaux peuvent contenir des valeurs de n’importe quel type de données. Pour une occurrence de Vector, le type de données de la valeur renvoyée est le type de base du vecteur. La méthode splice() renvoie un tableau ou un vecteur contenant les valeurs supprimées. Vous pouvez modifier l’exemple du tableau oceans de façon à ce que l’appel à splice() affecte le tableau renvoyé à une nouvelle variable de tableau, comme illustré dans l’exemple suivant : var lakes:Array = oceans.splice(2, 2, "Arctic", "Atlantic"); trace(lakes); // output: Aral,Superior Il se peut que vous rencontriez un code qui utilise l’opérateur delete sur un élément de l’objet Array. L’opérateur delete définit la valeur d’un élément de tableau sur undefined, mais il ne supprime pas l’élément du tableau. Par exemple, le code suivant utilise l’opérateur delete sur le troisième élément dans le tableau oceans, mais la longueur du tableau demeure à 5 : var oceans:Array = ["Arctic", "Pacific", "Victoria", "Indian", "Atlantic"]; delete oceans[2]; trace(oceans);// output: Arctic,Pacific,,Indian,Atlantic trace(oceans[2]); // output: undefined trace(oceans.length); // output: 5 Vous pouvez tronquer un tableau ou un vecteur à l’aide d’une propriété length de tableau. Si vous définissez la propriété length d’un tableau indexé sur une longueur qui est moindre que la longueur actuelle du tableau, celui-ci est tronqué : tous les éléments stockés à des numéros d’index supérieurs à la nouvelle valeur length, diminuée de 1, sont supprimés. Par exemple, si le tableau oceans était trié de telle façon que toutes les entrées valides se trouvaient au début du tableau, vous pourriez utiliser la propriété length pour supprimer les entrées de fin de tableau, comme l’indique le code ci-dessous : var oceans:Array = ["Arctic", "Pacific", "Victoria", "Aral", "Superior"]; oceans.length = 2; trace(oceans); // output: Arctic,Pacific Remarque : si une propriété fixed de l’objet Vector est définie sur true, le nombre total d’éléments du vecteur reste immuable. Si vous essayez de supprimer un élément d’un vecteur de longueur fixe ou de tronquer celui-ci à l’aide des techniques décrites ici, une erreur se produit. Tri d’un tableau Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Trois méthodes, reverse(), sort() et sortOn(), vous permettent de modifier l’ordre d’un tableau indexé, soit en triant, soit en inversant l’ordre. Toutes ces méthodes modifient le tableau existant. Le tableau ci-dessous résume ces méthodes et leurs comportements pour les objets Array et Vector : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 34 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Méthode reverse() La méthode reverse() ne prend aucun paramètre et ne renvoie aucune valeur mais vous permet de faire basculer l’ordre de votre tableau de son état actuel à l’ordre inverse. L’exemple suivant inverse l’ordre des océans répertoriés dans le tableau oceans : var oceans:Array = ["Arctic", "Atlantic", "Indian", "Pacific"]; oceans.reverse(); trace(oceans); // output: Pacific,Indian,Atlantic,Arctic Tri de base avec la méthode sort() (classe Array uniquement) Pour une occurrence d’Array, la méthode sort() réorganise les éléments dans un tableau à l’aide de l’ordre de tri par défaut. L’ordre de tri par défaut possède les caractéristiques suivantes : • Le tri est sensible à la casse, ce qui signifie que les majuscules précédent les minuscules. Par exemple, la lettre D précède la lettre b. • Le tri est croissant, ce qui signifie que les codes de caractère bas (A, par exemple) précédent les codes de caractère élevés (B, par exemple). • Le tri place les valeurs identiques les unes à côté des autres mais sans ordre particulier. • Le tri est basé sur des chaînes, ce qui signifie que les éléments sont convertis en chaînes avant d’être comparés (par exemple, 10 précède 3 car la chaîne "1" a un code de caractère inférieur à celui de la chaîne "3"). Vous pouvez trier votre tableau en ignorant la casse ou par ordre décroissant. Vous pouvez également trier les nombres de votre tableau par ordre numérique plutôt que par ordre alphabétique. La méthode sort() de la classe Array possède un paramètre options qui vous permet de modifier chaque caractéristique de l’ordre de tri par défaut. Les options sont définies par un ensemble de constantes statiques dans la classe Array, comme indiqué dans la liste suivante : • Array.CASEINSENSITIVE : cette option permet d’ignorer la casse lors du tri. Par exemple, la lettre minuscule b précède la lettre majuscule D. • Array.DESCENDING : cette option inverse le tri croissant par défaut. Par exemple, la lettre B précède la lettre A. • Array.UNIQUESORT : cette option permet d’arrêter le tri si deux valeurs identiques sont repérées. • Array.NUMERIC : cette option permet d’effectuer un tri numérique, de façon à ce que 3 précède 10. L’exemple suivant met en évidence certaines de ces options. Un tableau appelé poets est créé. Il est trié à l’aide de plusieurs options. Méthode Comportement d’Array Comportement de Vector reverse() Modifie l’ordre des éléments de telle sorte que le dernier élément devient le premier élément, le pénultième le deuxième, etc. Identique au comportement d’Array sort() Vous permet de trier les éléments du tableau de diverses façons prédéfinies, comme l’ordre alphabétique ou numérique. Vous pouvez également spécifier un algorithme de tri personnalisé. Trie les éléments suivant l’algorithme de tri personnalisé que vous spécifiez sortOn() Vous permet de trier des objets qui ont une ou plusieurs propriétés en commun en spécifiant la ou les propriétés à utiliser comme critères de tri. Non disponible dans la classe Vector GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 35 Utilisation de tableaux Dernière mise à jour le 27/4/2013 var poets:Array = ["Blake", "cummings", "Angelou", "Dante"]; poets.sort(); // default sort trace(poets); // output: Angelou,Blake,Dante,cummings poets.sort(Array.CASEINSENSITIVE); trace(poets); // output: Angelou,Blake,cummings,Dante poets.sort(Array.DESCENDING); trace(poets); // output: cummings,Dante,Blake,Angelou poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE); // use two options trace(poets); // output: Dante,cummings,Blake,Angelou Tri personnalisé avec la méthode sort() (classes Array et Vector) En plus du tri de base qui est disponible pour un objet Array, vous pouvez également établir une règle de tri personnalisée. Cette technique est la seule forme de méthode sort() disponible pour la classe Vector. Pour définir un tri personnalisé, vous rédigez une fonction de tri personnalisée et la transmettez comme argument à la méthode sort(). Par exemple, si vous avez une liste de noms dans laquelle chaque élément de liste contient le nom entier d’une personne mais que vous souhaitez trier la liste par nom de famille, vous devez utiliser une fonction de tri personnalisé pour analyser chaque élément et utiliser le nom de famille dans la fonction de tri. Le code suivant indique comment procéder avec une fonction personnalisée utilisée comme paramètre pour la méthode Array.sort() : var names:Array = new Array("John Q. Smith", "Jane Doe", "Mike Jones"); function orderLastName(a, b):int { var lastName:RegExp = /\b\S+$/; var name1 = a.match(lastName); var name2 = b.match(lastName); if (name1 < name2) { return -1; } else if (name1 > name2) { return 1; } else { return 0; } } trace(names); // output: John Q. Smith,Jane Doe,Mike Jones names.sort(orderLastName); trace(names); // output: Jane Doe,Mike Jones,John Q. Smith La fonction de tri personnalisé orderLastName() utilise une expression régulière pour extraire le nom de famille de chaque élément à utiliser pour l’opération de comparaison. L’identifiant de fonction orderLastName est l’unique paramètre utilisé lors de l’appel à la méthode sort() sur le tableau names. La fonction de tri accepte deux paramètres, a et b, car elle fonctionne sur deux éléments de tableau à la fois. La valeur renvoyée de la fonction de tri indique la manière dont les éléments doivent être triés : • Une valeur renvoyée de -1 indique que le premier paramètre, a, précède le second paramètre, b. • Une valeur renvoyée de 1 indique que le second paramètre, b, précède le premier, a. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 36 Utilisation de tableaux Dernière mise à jour le 27/4/2013 • Une valeur renvoyée de 0 indique que les éléments ont une précédence de tri équivalente. Méthode sortOn() (classe Array uniquement) La méthode sortOn() est conçue pour des objets Array avec des éléments contenant des objets. Ces objets doivent avoir au moins une propriété en commun pouvant être utilisée comme clé de tri. L’utilisation de la méthode sortOn() pour des tableaux d’autres types provoque des résultats inattendus. Remarque : la classe Vector ne contient pas de méthode sortOn(). Cette méthode n’est disponible que pour les objets Array. L’exemple suivant modifie le tableau poets de façon à ce que chaque élément soit un objet plutôt qu’une chaîne. Chaque objet contient à la fois le nom de famille du poète et sa date de naissance. var poets:Array = new Array(); poets.push({name:"Angelou", born:"1928"}); poets.push({name:"Blake", born:"1757"}); poets.push({name:"cummings", born:"1894"}); poets.push({name:"Dante", born:"1265"}); poets.push({name:"Wang", born:"701"}); Vous pouvez utiliser la méthode sortOn() pour trier le tableau par la propriété born. La méthode sortOn() définit deux paramètres, fieldName et options. L’argument fieldName doit être spécifié en tant que chaîne. Dans l’exemple suivant, la méthode sortOn() est appelée avec deux arguments, "born" et Array.NUMERIC. L’argument Array.NUMERIC est utilisé pour vérifier que le tri est effectué par ordre numérique plutôt que par ordre alphabétique. Ceci est utile même lorsque tous les nombres ont le même nombre de chiffres car vous êtes certain que le tri se fera comme prévu si un nombre comportant un nombre inférieur ou supérieur de chiffres est ensuite ajouté au tableau. poets.sortOn("born", Array.NUMERIC); for (var i:int = 0; i < poets.length; ++i) { trace(poets[i].name, poets[i].born); } /* output: Wang 701 Dante 1265 Blake 1757 cummings 1894 Angelou 1928 */ Tri sans modification du tableau d’origine (classe Array uniquement) Généralement, les méthodes sort() et sortOn() modifient un tableau. Si vous souhaitez trier un tableau sans modifier le tableau existant, transmettez la constante Array.RETURNINDEXEDARRAY avec le paramètre options. Cette option indique aux méthodes de renvoyer un nouveau tableau qui reflète le tri et laisse le tableau d’origine inchangé. Le tableau renvoyé par les méthodes est un tableau simple de numéros d’index qui reflète le nouvel ordre de tri et ne contient aucun élément du tableau d’origine. Par exemple, pour trier le tableau poets par année de naissance sans le modifier, incluez la constante Array.RETURNINDEXEDARRAY dans l’argument transmis pour le paramètre options. L’exemple suivant stocke les informations d’index renvoyées dans un tableau nommé indices et utilise le tableau indices avec le tableau poets inchangé pour trier les poètes dans l’ordre de leur année de naissance : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 37 Utilisation de tableaux Dernière mise à jour le 27/4/2013 var indices:Array; indices = poets.sortOn("born", Array.NUMERIC | Array.RETURNINDEXEDARRAY); for (var i:int = 0; i < indices.length; ++i) { var index:int = indices[i]; trace(poets[index].name, poets[index].born); } /* output: Wang 701 Dante 1265 Blake 1757 cummings 1894 Angelou 1928 */ Interrogation d’un tableau Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les quatre méthodes restantes des classes Array et Vector, concat(), join(), slice(), toString(), interrogent toutes le tableau sans le modifier. Les méthodes concat() et slice() renvoient toutes les deux de nouveaux tableaux, alors que les méthodes join() et toString() renvoient des chaînes. La méthode concat() prend un nouveau tableau ou une liste d’éléments comme arguments et le/la combine avec le tableau existant pour créer un tableau. La méthode slice() possède deux paramètres nommés startIndex et endIndex, et renvoie un nouveau tableau contenant une copie des éléments découpés du tableau existant. La découpe commence avec l’élément à startIndex et se termine avec l’élément juste avant endIndex. Il convient d’insister : l’élément à endIndex n’est pas compris dans la valeur renvoyée. L’exemple suivant utilise concat() et slice() pour créer des tableaux à l’aide d’éléments d’autres tableaux : var array1:Array = ["alpha", "beta"]; var array2:Array = array1.concat("gamma", "delta"); trace(array2); // output: alpha,beta,gamma,delta var array3:Array = array1.concat(array2); trace(array3); // output: alpha,beta,alpha,beta,gamma,delta var array4:Array = array3.slice(2,5); trace(array4); // output: alpha,beta,gamma Vous pouvez utiliser les méthodes join() et toString() pour interroger le tableau et renvoyer son contenu sous la forme d’une chaîne. Si aucun paramètre n’est utilisé pour la méthode join(), les deux méthodes se comportent de façon identique : elles renvoient une chaîne contenant une liste de tous les éléments du tableau, séparés par une virgule. La méthode join(), contrairement à la méthode toString(), accepte un paramètre nommé delimiter, qui permet de choisir le symbole à utiliser comme séparateur entre chaque élément de la chaîne renvoyée. L’exemple suivant crée un tableau nommé rivers et appelle à la fois join() et toString() pour renvoyer les valeurs dans le tableau sous la forme d’une chaîne. La méthode toString() est utilisée pour renvoyer des valeurs séparées par une virgule (riverCSV), alors que la méthode join() est utilisée pour renvoyer des valeurs séparées par le caractère +. var rivers:Array = ["Nile", "Amazon", "Yangtze", "Mississippi"]; var riverCSV:String = rivers.toString(); trace(riverCSV); // output: Nile,Amazon,Yangtze,Mississippi var riverPSV:String = rivers.join("+"); trace(riverPSV); // output: Nile+Amazon+Yangtze+Mississippi GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 38 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Il existe un problème avec la méthode join() ; toutes les occurrences de tableau et de vecteur imbriquées sont toujours renvoyées avec des valeurs séparées par des virgules, quel que soit le séparateur que vous spécifiez pour les éléments de tableau principaux, comme illustré dans l’exemple suivant : var nested:Array = ["b","c","d"]; var letters:Array = ["a",nested,"e"]; var joined:String = letters.join("+"); trace(joined); // output: a+b,c,d+e Tableaux associatifs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un tableau associatif, parfois appelé hachage ou mappage, utilise des clés plutôt qu’un index numérique pour organiser des valeurs stockées. Chaque clé dans un tableau associatif est une chaîne unique qui est utilisée pour accéder à une valeur stockée. Un tableau associatif est une occurrence de la classe Object, ce qui signifie que chaque clé correspond à un nom de propriété. Les tableaux associatifs sont des collections non triées de paires de clés et de valeurs. Votre code ne doit pas s’attendre à ce que les clés d’un tel tableau se présentent dans un ordre précis. ActionScript 3.0 contient aussi un type avancé de tableau associatif appelé dictionnaire. Les dictionnaires, qui sont des occurrences de la classe Dictionary dans le package flash.utils, utilisent des clés de tout type de données. En d’autres termes, les clés de dictionnaire ne sont pas limitées à des valeurs de type String. Tableaux associatifs avec clés de chaîne Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Deux méthodes permettent de créer des tableaux associatifs dans ActionScript 3.0. La première consiste à utiliser une occurrence de Object. Celle-ci vous permet d’initialiser votre tableau avec un littéral d’objet. Une occurrence de la classe Object, également appelée objet générique, fonctionne comme un tableau associatif. Chaque nom de propriété de l’objet générique devient la clé qui permet d’accéder à une valeur stockée. L’exemple suivant crée un tableau associatif appelé monitorInfo, à l’aide d’un littéral d’objet pour initialiser le tableau avec deux paires de clés et de valeurs : var monitorInfo:Object = {type:"Flat Panel", resolution:"1600 x 1200"}; trace(monitorInfo["type"], monitorInfo["resolution"]); // output: Flat Panel 1600 x 1200 Si vous n’avez pas besoin d’initialiser le tableau lors de la déclaration, vous pouvez utiliser le constructeur Object pour créer le tableau, comme suit : var monitorInfo:Object = new Object(); Une fois que le tableau est créé à l’aide d’un littéral d’objet ou du constructeur de la classe Object, vous pouvez lui ajouter de nouvelles valeurs à l’aide de l’opérateur ([]) d’accès au tableau ou de l’opérateur point (.). L’exemple suivant ajoute deux nouvelles valeurs à monitorArray : monitorInfo["aspect ratio"] = "16:10"; // bad form, do not use spaces monitorInfo.colors = "16.7 million"; trace(monitorInfo["aspect ratio"], monitorInfo.colors); // output: 16:10 16.7 million GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 39 Utilisation de tableaux Dernière mise à jour le 27/4/2013 La clé appelée aspect ratio contient un caractère d’espace. Cela est possible dans le cas de l’opérateur ([]) d’accès au tableau, mais avec l’opérateur point, une erreur se produit. L’utilisation d’espace dans le nom de vos clés n’est donc pas conseillée. La seconde méthode pour créer un tableau associatif consiste à utiliser le constructeur Array (ou le constructeur d’une classe dynamique), puis à utiliser l’opérateur ([]) d’accès au tableau ou l’opérateur point (.) pour ajouter les paires de clés et de valeurs au tableau. Si vous déclarez votre tableau associatif comme étant de type Array, vous ne pouvez pas utiliser de littéral d’objet pour l’initialiser. Ce code crée un tableau associatif appelé monitorInfo à l’aide du constructeur Array, et ajoute les clés appelées type et resolution, ainsi que leurs valeurs : var monitorInfo:Array = new Array(); monitorInfo["type"] = "Flat Panel"; monitorInfo["resolution"] = "1600 x 1200"; trace(monitorInfo["type"], monitorInfo["resolution"]); // output: Flat Panel 1600 x 1200 L’utilisation du constructeur Array pour créer un tableau associatif ne présente aucun avantage. Vous ne pouvez pas utiliser la propriété Array.length ou une méthode de la classe Array avec des tableaux associatifs, même si vous utilisez le constructeur Array ou le type de données Array. Il est préférable d’utiliser le constructeur Array pour créer des tableaux indexés. Tableaux associatifs avec clés d’objet (dictionnaires) Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser la classe Dictionary pour créer un tableau associatif qui utilise des objets pour les clés au lieu de chaînes. Ces tableaux sont parfois appelés dictionnaires, hachages ou mappages. Par exemple, supposez que vous avez une application qui détermine l’emplacement d’un objet Sprite selon son association avec un conteneur spécifique. Vous pouvez utiliser un objet Dictionary pour mapper chaque objet Sprite à un conteneur. Le code suivant crée trois occurrences de la classe Sprite qui servent de clés pour l’objet Dictionary. La valeur GroupA ou GroupB est affectée à chaque clé. Les valeurs peuvent être de n’importe quel type de données, mais dans cet exemple, GroupA et GroupB sont des occurrences de la classe Object. Vous pouvez ensuite accéder à la valeur associée à chaque clé avec l’opérateur d’accès au tableau ([]), comme illustré dans le code suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 40 Utilisation de tableaux Dernière mise à jour le 27/4/2013 import flash.display.Sprite; import flash.utils.Dictionary; var groupMap:Dictionary = new Dictionary(); // objects to use as keys var spr1:Sprite = new Sprite(); var spr2:Sprite = new Sprite(); var spr3:Sprite = new Sprite(); // objects to use as values var groupA:Object = new Object(); var groupB:Object = new Object(); // Create new key-value pairs in dictionary. groupMap[spr1] = groupA; groupMap[spr2] = groupB; groupMap[spr3] = groupB; if (groupMap[spr1] == groupA) { trace("spr1 is in groupA"); } if (groupMap[spr2] == groupB) { trace("spr2 is in groupB"); } if (groupMap[spr3] == groupB) { trace("spr3 is in groupB"); } Itération avec des clés d’objet Vous pouvez parcourir en boucle le contenu d’un objet Dictionary à l’aide d’une boucle for..in ou d’une boucle for each..in. Une boucle for..in vous permet d’effectuer une itération en fonction des clés, tandis qu’une boucle for each..in vous permet d’effectuer une itération en fonction des valeurs associées à chaque clé. Utilisez la boucle for..in pour accéder directement aux clés d’objet d’un objet Dictionary. Vous pouvez également accéder aux valeurs de l’objet Dictionary avec l’opérateur d’accès au tableau ([]). Le code suivant utilise l’exemple précédent du dictionnaire groupMap pour indiquer comment parcourir en boucle un objet Dictionary avec la boucle for..in : for (var key:Object in groupMap) { trace(key, groupMap[key]); } /* output: [object Sprite] [object Object] [object Sprite] [object Object] [object Sprite] [object Object] */ Utilisez la boucle for each..in pour accéder directement aux valeurs d’un objet Dictionary. Le code suivant utilise également le dictionnaire groupMap pour indiquer comment parcourir en boucle un objet Dictionary avec la boucle for each..in : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 41 Utilisation de tableaux Dernière mise à jour le 27/4/2013 for each (var item:Object in groupMap) { trace(item); } /* output: [object Object] [object Object] [object Object] */ Clés d’objet et gestion de la mémoire Adobe® Flash® Player et Adobe® AIR™ utilisent un système de nettoyage permettant de récupérer la mémoire qui n’est plus utilisée. Lorsque aucune référence ne pointe vers un objet, ce dernier peut être nettoyé et la mémoire récupérée au prochain nettoyage. Par exemple, le code suivant crée un objet et lui affecte une référence à la variable myObject : var myObject:Object = new Object(); Tant que des références à l’objet existent, le système de nettoyage ne récupère pas la mémoire que l’objet occupe. Si la valeur de myObject est modifiée et qu’elle pointe vers un autre objet ou qu’elle est définie sur null, la mémoire occupée par l’objet d’origine peut être nettoyée. Néanmoins, aucune autre référence à l’objet d’origine ne doit exister. Si vous utilisez myObject comme clé dans un objet Dictionary, vous créez une autre référence à l’objet d’origine. Par exemple, le code suivant crée deux références à un objet, la variable myObject et la clé dans l’objet myMap : import flash.utils.Dictionary; var myObject:Object = new Object(); var myMap:Dictionary = new Dictionary(); myMap[myObject] = "foo"; Pour que l’objet référencé par myObject puisse être nettoyé, vous devez supprimer toutes ses références. Dans ce cas, vous devez modifier la valeur de myObject et supprimer la clé myObject de myMap, comme indiqué dans le code suivant : myObject = null; delete myMap[myObject]; Vous pouvez également utiliser le paramètre useWeakReference du constructeur Dictionary pour que toutes les clés de dictionnaire deviennent des références faibles. Le système de nettoyage ignore les références faibles. Par conséquent, un objet n’ayant que des références faibles peut être nettoyé. Par exemple, dans le code suivant, vous n’avez pas besoin de supprimer la clé myObject de myMap pour que l’objet puisse être nettoyé : import flash.utils.Dictionary; var myObject:Object = new Object(); var myMap:Dictionary = new Dictionary(true); myMap[myObject] = "foo"; myObject = null; // Make object eligible for garbage collection. Tableaux multidimensionnels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les tableaux multidimensionnels contiennent d’autres tableaux comme éléments. Prenons par exemple une liste de tâches stockée sous forme de tableau indexé de chaînes : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 42 Utilisation de tableaux Dernière mise à jour le 27/4/2013 var tasks:Array = ["wash dishes", "take out trash"]; Pour stocker une liste de tâches distincte pour chaque jour de la semaine, vous pouvez créer un tableau multidimensionnel avec un élément pour chaque jour. Chaque élément contient à son tour un tableau indexé (semblable au tableau tasks) qui stocke la liste des tâches. Vous pouvez utiliser n’importe quelle combinaison de tableaux indexés ou associatifs dans des tableaux multidimensionnels. Les exemples des sections suivantes utilisent soit deux tableaux indexés soit un tableau associatif de tableaux indexés. Vous pouvez essayer les autres combinaisons pour vous exercer. Deux tableaux indexés Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous utilisez deux tableaux indexés, vous pouvez visualiser le résultat sous forme de tableau ou de feuille de calcul. Les éléments du premier tableau représentent les lignes alors que les éléments du second tableau représentent les colonnes. Par exemple, le tableau multidimensionnel suivant utilise deux tableaux indexés pour suivre des listes de tâches pour chaque jour de la semaine. Le premier tableau, masterTaskList, est créé à l’aide du constructeur de classe Array. Chaque élément du tableau représente un jour de la semaine, avec l’index 0 représentant lundi et l’index 6 dimanche. Ces éléments peuvent être considérés comme les lignes du tableau. Vous pouvez créer la liste de tâches de chaque jour en affectant un littéral de tableau à chacun des sept éléments que vous créez dans le tableau masterTaskList. Les littéraux de tableau représentent les colonnes du tableau. var masterTaskList:Array = new Array(); masterTaskList[0] = ["wash dishes", "take out trash"]; masterTaskList[1] = ["wash dishes", "pay bills"]; masterTaskList[2] = ["wash dishes", "dentist", "wash dog"]; masterTaskList[3] = ["wash dishes"]; masterTaskList[4] = ["wash dishes", "clean house"]; masterTaskList[5] = ["wash dishes", "wash car", "pay rent"]; masterTaskList[6] = ["mow lawn", "fix chair"]; Vous pouvez accéder à des éléments particuliers sur toute liste des tâches à l’aide de l’opérateur d’accès au tableau ([]). Le premier groupe de crochets représente le jour de la semaine et le second la liste de tâches pour ce jour. Par exemple, pour récupérer la seconde tâche de la liste du mercredi, utilisez d’abord l’index 2 pour mercredi puis utilisez l’index 1 pour la seconde tâche dans la liste. trace(masterTaskList[2][1]); // output: dentist Pour récupérer la première tâche de la liste du dimanche, utilisez l’index 6 pour dimanche et l’index 0 pour la première tâche sur la liste. trace(masterTaskList[6][0]); // output: mow lawn Tableau associatif avec un tableau indexé Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour faciliter l’accès aux tableaux, vous pouvez utiliser un tableau associatif pour les jours de la semaine et un tableau indexé pour les listes de tâche. Les tableaux associatifs vous permettent d’utiliser une syntaxe à point lorsque vous vous référez à un jour particulier de la semaine, mais nécessitent un traitement d’exécution supplémentaire pour accéder à chaque élément du tableau associatif. L’exemple suivant utilise un tableau associatif comme base d’une liste de tâches, avec une paire de clés et de valeurs pour chaque jour de la semaine : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 43 Utilisation de tableaux Dernière mise à jour le 27/4/2013 var masterTaskList:Object = new Object(); masterTaskList["Monday"] = ["wash dishes", "take out trash"]; masterTaskList["Tuesday"] = ["wash dishes", "pay bills"]; masterTaskList["Wednesday"] = ["wash dishes", "dentist", "wash dog"]; masterTaskList["Thursday"] = ["wash dishes"]; masterTaskList["Friday"] = ["wash dishes", "clean house"]; masterTaskList["Saturday"] = ["wash dishes", "wash car", "pay rent"]; masterTaskList["Sunday"] = ["mow lawn", "fix chair"]; La syntaxe à point rend le code plus lisible car elle évite d’utiliser plusieurs groupes de crochets. trace(masterTaskList.Wednesday[1]); // output: dentist trace(masterTaskList.Sunday[0]);// output: mow lawn Vous pouvez parcourir en boucle la liste des tâches en utilisant une boucle for..in, mais vous devez utiliser l’opérateur d’accès au tableau ([]), en lieu et place de la syntaxe à point, pour accéder à la valeur associée à chaque clé. Etant donné que masterTaskList est un tableau associatif, les éléments ne sont pas nécessairement récupérés dans l’ordre que vous attendez, comme l’indique l’exemple suivant : for (var day:String in masterTaskList) { trace(day + ": " + masterTaskList[day]) } /* output: Sunday: mow lawn,fix chair Wednesday: wash dishes,dentist,wash dog Friday: wash dishes,clean house Thursday: wash dishes Monday: wash dishes,take out trash Saturday: wash dishes,wash car,pay rent Tuesday: wash dishes,pay bills */ Clonage de tableaux Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Array ne possède aucune méthode intégrée pour effectuer des copies de tableaux. Vous pouvez créer une copie simple d’un tableau en appelant la méthode concat() ou slice() sans arguments. Dans une copie simple, si le tableau d’origine a des éléments qui sont des objets, seules les références aux objets sont copiées (et non les objets). La copie pointe vers les mêmes objets que l’original. Tout changement effectué sur les objets apparaît dans les deux tableaux. Dans une copie en profondeur, les objets se trouvant dans le tableau d’origine sont copiés également de façon à ce que le nouveau tableau ne pointe pas vers les mêmes objets que le tableau d’origine. La copie en profondeur exige plus d’une ligne de code, ce qui nécessite généralement la création d’une fonction. Une telle fonction peut être créée comme fonction d’utilitaire globale ou comme méthode d’une sous-classe Array. L’exemple suivant définit une fonction appelée clone() qui effectue une copie en profondeur. L’algorithme est issu d’une technique de programmation Java courante. La fonction crée une copie en profondeur en sérialisant le tableau en une occurrence de la classe ByteArray puis en relisant le tableau dans un nouveau tableau. Cette fonction accepte un objet de façon à ce qu’il puisse être utilisé à la fois avec des tableaux indexés et des tableaux associatifs, comme indiqué dans le code suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 44 Utilisation de tableaux Dernière mise à jour le 27/4/2013 import flash.utils.ByteArray; function clone(source:Object):* { var myBA:ByteArray = new ByteArray(); myBA.writeObject(source); myBA.position = 0; return(myBA.readObject()); } Extension de la classe Array Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Array est l’une des classes de base non finale, c’est-à-dire que vous pouvez créer votre sous-classe d’Array. Cette section décrit comment créer une sous-classe d’Array et décrit les problèmes pouvant se poser pendant le processus. Comme mentionné précédemment, les tableaux dans ActionScript ne sont pas typés, mais vous pouvez créer une sousclasse d’Array qui accepte des éléments d’un seul type de données. L’exemple fourni dans les sections suivantes définit une sous-classe Array appelée TypedArray qui limite ses éléments à des valeurs du type de données indiqué dans le premier paramètre. La classe TypedArray est présentée comme un exemple de la façon dont la classe Array est étendue et risque de ne pas être adaptée à des fins de production pour différentes raisons. Premièrement, la vérification du type a lieu lors de l’exécution plutôt que de la compilation. Deuxièmement, lorsqu’une méthode TypedArray rencontre une incompatibilité, elle est ignorée et aucune exception n’est renvoyée, même si vous pouvez facilement modifier les méthodes pour renvoyer des exceptions. Troisièmement, la classe ne peut pas empêcher l’utilisation de l’opérateur d’accès au tableau pour insérer des valeurs de n’importe quel type dans le tableau. Quatrièmement, le style de codage privilégie la simplicité par rapport à l’optimisation des performances. Remarque : vous pouvez utiliser la technique décrite ici pour créer un tableau typé. Cependant, utiliser un objet Vector constitue une meilleure démarche. Une occurrence de Vector est un véritable tableau typé. Elle dépasse la classe Array ou toute sous-classe par ses performances et ses améliorations. Une illustration de la création d’une sous-classe Array constitue l’objet de cette description. Déclaration de la sous-classe Utilisez le mot-clé extends pour indiquer qu’une classe est une sous-classe d’Array. Une sous-classe d’Array doit utiliser l’attribut dynamic, comme la classe Array. Autrement, votre sous-classe ne fonctionne pas correctement. Le code suivant représente la définition de la classe TypedArray, qui comporte une constante contenant le type de données, une méthode de constructeur et les quatre méthodes permettant d’ajouter des éléments au tableau. Le code pour chaque méthode est omis dans cet exemple, mais il est décrit de façon détaillée dans les sections qui suivent : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 45 Utilisation de tableaux Dernière mise à jour le 27/4/2013 public dynamic class TypedArray extends Array { private const dataType:Class; public function TypedArray(...args) {} AS3 override function concat(...args):Array {} AS3 override function push(...args):uint {} AS3 override function splice(...args) {} AS3 override function unshift(...args):uint {} } Les quatre méthodes de remplacement utilisent l’espace de nom AS3 au lieu de l’attribut public car cet exemple suppose que l’option -as3 du compilateur est définie sur true et l’option -es du compilateur sur false. Il s’agit des paramètres par défaut pour Adobe Flash Builder et AdobeFlashProfessional. Si vous êtes un développeur expérimenté et que vous préférez utiliser l’héritage de prototype, vous pouvez apporter deux changements mineurs à la classe TypedArray afin qu’elle compile avec l’option -es du compilateur définie sur true. Commencez par supprimer toutes les occurrences de l’attribut override et remplacez l’espace de nom AS3 par l’attribut public. Remplacez ensuite Array.prototype pour les quatre occurrences de super. Constructeur TypedArray Le constructeur de sous-classe pose un défi intéressant car il doit accepter une liste d’arguments de longueur arbitraire. Il s’agit de savoir comment transférer les arguments au superconstructeur pour créer le tableau. Si vous transmettez la liste des arguments sous forme d’un tableau, le superconstructeur le considère comme un seul argument de type Array et le tableau résultant a toujours une longueur d’1 élément. Le transfert de listes d’arguments se fait généralement au moyen de la méthode Function.apply(), qui prend un tableau d’arguments comme second paramètre mais le convertit en une liste d’arguments lors de l’exécution de la fonction. Malheureusement, vous ne pouvez pas utiliser la méthode Function.apply() avec des constructeurs. La seule solution est de recréer la logique du constructeur Array dans le constructeur TypedArray. Le code suivant indique l’algorithme utilisé dans le constructeur de classe Array, que vous pouvez réutiliser dans votre constructeur de sous-classe Array : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 46 Utilisation de tableaux Dernière mise à jour le 27/4/2013 public dynamic class Array { public function Array(...args) { var n:uint = args.length if (n == 1 && (args[0] is Number)) { var dlen:Number = args[0]; var ulen:uint = dlen; if (ulen != dlen) { throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")"); } length = ulen; } else { length = n; for (var i:int=0; i < n; i++) { this[i] = args[i] } } } } Le constructeur TypedArray partage une grande partie du code du constructeur Array, avec seulement quatre changements apportés au code. Premièrement, la liste des paramètres comprend un nouveau paramètre obligatoire de type Class qui permet d’indiquer le type de données du tableau. Deuxièmement, le type de données transmis au constructeur est affecté à la variable dataType. Troisièmement, dans l’instruction else, la valeur de la propriété length est affectée après la boucle for de façon à ce que length comprenne uniquement des arguments du type correct. Quatrièmement, le corps de la boucle for utilise la version de remplacement de la méthode push() de façon à ce que seuls des arguments du type de données correct soient ajoutés au tableau. L’exemple suivant présente la fonction constructeur TypedArray : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 47 Utilisation de tableaux Dernière mise à jour le 27/4/2013 public dynamic class TypedArray extends Array { private var dataType:Class; public function TypedArray(typeParam:Class, ...args) { dataType = typeParam; var n:uint = args.length if (n == 1 && (args[0] is Number)) { var dlen:Number = args[0]; var ulen:uint = dlen if (ulen != dlen) { throw new RangeError("Array index is not a 32-bit unsigned integer ("+dlen+")") } length = ulen; } else { for (var i:int=0; i < n; i++) { // type check done in push() this.push(args[i]) } length = this.length; } } } Méthodes de remplacement TypedArray La classe TypedArray remplace les quatre méthodes de la classe Array qui permettent d’ajouter des éléments à un tableau. Dans chaque cas, la méthode de remplacement ajoute une vérification du type qui empêche d’ajouter des éléments qui ne sont pas du type de données correct. Chaque méthode appelle ensuite sa version de superclasse. La méthode push() parcourt en boucle la liste des arguments avec une boucle for..in et effectue une vérification du type sur chaque argument. Les arguments qui ne sont pas de type correct sont supprimés du tableau args avec la méthode splice(). Une fois que la boucle for..in se termine, le tableau args contient des valeurs de type dataType uniquement. La version de superclasse de push() est ensuite appelée avec le tableau args mis à jour, comme indiqué dans le code suivant : AS3 override function push(...args):uint { for (var i:* in args) { if (!(args[i] is dataType)) { args.splice(i,1); } } return (super.push.apply(this, args)); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 48 Utilisation de tableaux Dernière mise à jour le 27/4/2013 La méthode concat() crée un TypedArray temporaire appelé passArgs pour stocker les arguments soumis à la vérification de type. Ceci permet de réutiliser le code de vérification de type qui existe dans la méthode push(). Une boucle for..in effectue une itération sur le tableau args et appelle push() sur chaque argument. Etant donné que passArgs est typé sous la forme TypedArray, la version TypedArray de push() est exécutée. La méthode concat() appelle ensuite sa version de superclasse, comme indiqué dans le code suivant : AS3 override function concat(...args):Array { var passArgs:TypedArray = new TypedArray(dataType); for (var i:* in args) { // type check done in push() passArgs.push(args[i]); } return (super.concat.apply(this, passArgs)); } La méthode splice() prend une liste d’arguments arbitraire, mais les deux premiers arguments se réfèrent toujours à un numéro d’index et au nombre d’éléments à supprimer. C’est pourquoi la méthode de remplacement splice() effectue la vérification de type uniquement pour les éléments du tableau args dans les positions d’index 2 ou supérieures. Il est intéressant de noter que dans le code, il semble y avoir un appel récursif à splice() à l’intérieur de la boucle for, mais en réalité, ce n’est pas le cas car args est de type Array et non de type TypedArray, ce qui signifie que l’appel à args.splice() est un appel à la version de superclasse de la méthode. Une fois que la boucle for..in se termine, le tableau args contient des valeurs du type correct uniquement dans les positions d’index 2 ou supérieures, et splice() appelle sa version de superclasse, comme indiqué dans le code suivant : AS3 override function splice(...args):* { if (args.length > 2) { for (var i:int=2; i< args.length; i++) { if (!(args[i] is dataType)) { args.splice(i,1); } } } return (super.splice.apply(this, args)); } La méthode unshift(), qui ajoute des éléments au début d’un tableau, accepte une liste d’arguments arbitraire également. La méthode de remplacement unshift() utilise un algorithme très semblable à celui utilisé par la méthode push(), comme indiqué dans le code suivant : AS3 override function unshift(...args):uint { for (var i:* in args) { if (!(args[i] is dataType)) { args.splice(i,1); } } return (super.unshift.apply(this, args)); } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 49 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Exemple de tableau : PlayList Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple PlayList présente les techniques d’utilisation des tableaux, dans le contexte d’une application de lecture musicale qui gère une liste de chansons. Ces techniques sont les suivantes : • Création d’un tableau indexé • Ajout d’éléments à un tableau indexé • Tri d’un tableau d’objets en fonction de différentes propriétés, à l’aide d’options de tri différentes • Conversion d’un tableau en une chaîne séparée par des caractères Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application PlayList se trouvent dans le dossier Samples/PlayList. L’application se compose des fichiers suivants : Présentation de la classe PlayList Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe PlayList gère un ensemble d’objets Song. Elle a des méthodes publiques qui permettent d’ajouter une chanson à la liste de lecture (la méthode addSong()) et de trier les chansons dans la liste (la méthode sortList()). En outre, la classe comprend une propriété d’accesseur en lecture seule, songList, qui permet d’accéder au groupe de chansons dans la liste de lecture. En interne, la classe PlayList conserve une trace de ses chansons à l’aide d’une variable Array privée : public class PlayList { private var _songs:Array; private var _currentSort:SortProperty = null; private var _needToSort:Boolean = false; ... } En plus de la variable Array _songs utilisée par la classe PlayList pour conserver une trace de sa liste de chansons, deux autres variables privées vérifient si la liste doit être triée (_needToSort) et contrôlent la propriété sur laquelle est basé le tri de la liste de chansons à un moment donné (_currentSort). Fichier Description PlayList.mxml ou PlayList.fla Fichier d’application principal dans Flash (FLA) ou Flex (MXML). com/example/programmingas3/playlist/PlayList.as Classe représentant une liste de morceaux. Elle utilise un tableau pour enregistrer la liste et gère le tri des éléments de la liste. com/example/programmingas3/playlist/Song.as Objet de valeur représentant des informations sur une seule chanson. Les éléments gérés par la classe PlayList sont des occurrences Song. com/example/programmingas3/playlist/SortProperty.as Pseudo-énumération dont les valeurs disponibles représentent les propriétés de la classe Song en fonction desquelles une liste d’objets Song peut être triée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 50 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Comme avec tous les objets, lorsque vous avez déclaré une occurrence de Array, vous n’avez effectué que la moitié du travail consistant à créer un tableau. Avant d’accéder à des méthodes ou à des propriétés d’une occurrence de Array, cette dernière doit être instanciée dans le constructeur de la classe PlayList. public function PlayList() { this._songs = new Array(); // Set the initial sorting. this.sortList(SortProperty.TITLE); } La première ligne du constructeur instancie la variable _songs pour qu’elle puisse être utilisée. En outre, la méthode sortList() est appelée pour définir la propriété de tri initiale. Ajout d’une chanson à la liste Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsqu’un utilisateur ajoute une nouvelle chanson dans l’application, le code dans le formulaire de saisie des données appelle la méthode addSong() de la classe PlayList. /** * Adds a song to the playlist. */ public function addSong(song:Song):void { this._songs.push(song); this._needToSort = true; } A l’intérieur de addSong(), la méthode push() du tableau _songs est appelée. Ceci permet d’ajouter l’objet Song transmis à addSong() en tant que nouvel élément dans ce tableau. Avec la méthode push() , le nouvel élément est ajouté à la fin du tableau, indépendamment du tri appliqué précédemment. Ceci signifie qu’une fois que la méthode push() a été appelée, la liste des chansons risque de ne plus être triée correctement. Par conséquent, la variable _needToSort est définie sur true. Théoriquement, la méthode sortList() pourrait être appelée immédiatement afin d’éviter de vérifier si la liste est triée ou non à un moment donné. En pratique, cependant, la liste des chansons n’a pas besoin d’être triée jusqu’au moment précédant immédiatement sa récupération. En retardant l’opération de tri, l’application n’effectue pas de tri inutile si, par exemple, plusieurs chansons sont ajoutées à la liste avant sa récupération. Tri de la liste de chansons Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Etant donné que les occurrences Song gérées par la liste de lecture sont des objets complexes, les utilisateurs de l’application peuvent trier la liste de lecture en fonction de différentes propriétés (titre de la chanson ou année de publication, par exemple). Dans l’application PlayList, le tri de la liste des chansons s’effectue en trois étapes : identification de la propriété sur laquelle est basé le tri de la liste, indication des options de tri à utiliser lors du tri en fonction de cette propriété et exécution du tri. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 51 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Propriétés de tri Un objet Song conserve la trace de plusieurs propriétés, notamment le titre de la chanson, l’artiste, l’année de publication, le nom du fichier et un ensemble de genres sélectionné par l’utilisateur auquel la chanson appartient. Seules les trois premières propriétés sont pratiques pour le tri. Dans un souci de commodité pour les développeurs, l’exemple inclut la classe SortProperty, qui agit comme une énumération avec des valeurs représentant les propriétés disponibles pour le tri. public static const TITLE:SortProperty = new SortProperty("title"); public static const ARTIST:SortProperty = new SortProperty("artist"); public static const YEAR:SortProperty = new SortProperty("year"); La classe SortProperty contient trois classes, TITLE, ARTIST et YEAR. Chacune d’elles stocke une chaîne comportant le nom de la propriété de la classe Song pouvant être utilisée pour le tri. Chaque fois qu’une propriété de tri est indiquée dans le reste du code, le membre de l’énumération est utilisé. Par exemple, dans le constructeur PlayList, la liste est triée initialement en appelant la méthode sortList(), comme suit : // Set the initial sorting. this.sortList(SortProperty.TITLE); Etant donné que la propriété de tri est spécifiée sous la forme SortProperty.TITLE, les chansons sont triées par titre. Tri par propriété et définition d’options de tri La classe PlayList trie la liste de chansons dans la méthode sortList(), comme suit : /** * Sorts the list of songs according to the specified property. */ public function sortList(sortProperty:SortProperty):void { ... var sortOptions:uint; switch (sortProperty) { case SortProperty.TITLE: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.ARTIST: sortOptions = Array.CASEINSENSITIVE; break; case SortProperty.YEAR: sortOptions = Array.NUMERIC; break; } // Perform the actual sorting of the data. this._songs.sortOn(sortProperty.propertyName, sortOptions); // Save the current sort property. this._currentSort = sortProperty; // Record that the list is sorted. this._needToSort = false; } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 52 Utilisation de tableaux Dernière mise à jour le 27/4/2013 Lors du tri par titre ou par artiste, il est préférable d’effectuer un tri par ordre alphabétique. En revanche, lors du tri par année, il est plus logique d’effectuer un tri numérique. L’instruction switch sert à définir l’option de tri appropriée, stockée dans la variable sortOptions, en fonction de la valeur indiquée dans le paramètre sortProperty. Ici encore, les membres de l’énumération nommés sont utilisés pour faire la différence entre les propriétés, plutôt que les valeurs absolues. Une fois que vous avez déterminé la propriété et les options de tri, le tableau _songs est trié en appelant sa méthode sortOn(), en transmettant ces deux valeurs comme paramètres. La propriété de tri est enregistrée et la liste des chansons est triée. Combinaison d’éléments de tableau en une chaîne séparée par des caractères Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Cet exemple utilise non seulement un tableau pour conserver la liste des chansons dans la classe PlayList mais également des tableaux dans la classe Song pour gérer la liste des genres auxquels une chanson appartient. Considérons ce fragment de code issu de la définition de la classe Song : private var _genres:String; public function Song(title:String, artist:String, year:uint, filename:String, genres:Array) { ... // Genres are passed in as an array // but stored as a semicolon-separated string. this._genres = genres.join(";"); } Lors de la création d’une occurrence de Song, le paramètre genres utilisé pour spécifier le genre (ou les genres) auquel la chanson appartient est défini comme occurrence d’Array. Ainsi, vous pouvez regrouper plusieurs genres en une seule variable qui peut être transmise au constructeur. Néanmoins, la classe Song conserve, en interne, les genres dans la variable privée _genres sous la forme d’une occurrence de String séparée par des points-virgules. Le paramètre Array est converti en une chaîne séparée par des points-virgules en appelant sa méthode join() avec la valeur de chaîne littérale ";" comme séparateur spécifié. De la même façon, les accesseurs genres permettent de définir ou de récupérer des genres sous la forme d’un tableau : public function get genres():Array { // Genres are stored as a semicolon-separated String, // so they need to be transformed into an Array to pass them back out. return this._genres.split(";"); } public function set genres(value:Array):void { // Genres are passed in as an array, // but stored as a semicolon-separated string. this._genres = value.join(";"); } L’accesseur genresset se comporte exactement comme le constructeur ; il accepte un tableau et appelle la méthode join() pour la convertir en une chaîne séparée par des points-virgules. L’accesseur get effectue l’opération inverse : la méthode split() de la variable _genres est appelée. Elle divise la chaîne en un tableau de valeurs utilisant le séparateur spécifié (la valeur de chaîne littérale ";" comme précédemment). 53 Dernière mise à jour le 27/4/2013 Chapitre 4 : Gestion des erreurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures « Gérer » une erreur signifie que vous intégrez des fonctions logiques à l’application pour réagir à une erreur ou la corriger. Les erreurs sont générées lors de la compilation d’une application ou lors de l’exécution d’une application compilée. Lorsque l’application gère les erreurs, il se produit une réaction à l’erreur. Il arrive en revanche qu’une erreur soit ignorée (auquel cas le processus à l’origine de l’erreur échoue silencieusement). La gestion des erreurs, lorsqu’elle est utilisée correctement, protège votre application et ses utilisateurs contre un comportement inattendu. Cependant, la gestion des erreurs est une catégorie large qui englobe la réponse à de nombreux types d’erreurs générées lors de la phase de compilation ou lors de l’exécution d’une application. Nous allons passer en revue la gestion des erreurs d’exécution (renvoyées lors de l’exécution d’une application), les différents types d’erreurs générés et les avantages du système de gestion des erreurs d’ActionScript 3.0. Principes de base de la gestion des erreurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Une erreur d’exécution est une erreur qui se produit dans votre code ActionScript et qui empêche le contenu ActionScript de s’exécuter comme prévu. Pour assurer l’exécution correcte du code ActionScript du point de vue de l’utilisateur, écrivez le code dans l’application qui gère l’erreur (la corrige, la contourne ou informe au moins l’utilisateur qu’elle a eu lieu). Ce processus est appelé gestion des erreurs. La gestion des erreurs est une catégorie large qui englobe la réponse à de nombreux types d’erreurs générées lors de la phase de compilation ou lors de l’exécution d’une application. Les erreurs qui se produisent lors de la compilation sont souvent plus faciles à identifier. Corrigez-les pour terminer la création d’un fichier SWF. Les erreurs d’exécution peuvent être difficiles à détecter car elles se produisent lorsque le code erroné est exécuté. Si un segment de votre programme contient plusieurs branches de code, telle une instruction if..then..else, testez toutes les conditions possibles, avec toutes les valeurs en entrée susceptibles d’être utilisées par un utilisateur réel, pour confirmer que le code ne contient pas d’erreur. Les erreurs d’exécution peuvent être divisées en deux catégories : les erreurs de programme sont des erreurs dans votre code ActionScript (spécification du type de données incorrect pour un paramètre de méthode, par exemple) ; les erreurs logiques sont des erreurs dans la logique (le contrôle des données et la manipulation des valeurs) de votre programme (utilisation de la formule incorrecte pour calculer les taux d’intérêt dans une application bancaire, par exemple). Encore une fois, ces deux types d’erreurs peuvent souvent être détectés et corrigés à l’avance en testant attentivement votre application. Il serait idéal d’identifier et de supprimer toutes les erreurs de votre application avant de la mettre à la disposition des utilisateurs finaux. Cependant, toutes les erreurs ne peuvent pas être prévues ni évitées. Supposons, par exemple, que l’application ActionScript charge des informations depuis un site Web particulier sur lequel vous n’avez aucun contrôle. Si ce site Web n’est pas disponible, la partie de l’application qui dépend de ces données externes ne se comporte pas correctement. L’aspect primordial de la gestion des erreurs consiste à anticiper ces cas de figure et à les traiter judicieusement. Il est préférable que l’exécution de l’application ne soit pas interrompue ou, tout du moins, qu’un message indique à l’utilisateur pourquoi elle ne fonctionne pas. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 54 Gestion des erreurs Dernière mise à jour le 27/4/2013 Les erreurs d’exécution sont représentées de deux façons dans ActionScript : • Classes d’erreur : de nombreuses erreurs sont associées à une classe Error. Lorsqu’une erreur se produit, le moteur d’exécution Flash (Flash Player ou Adobe AIR, par exemple) crée une occurrence de la classe Error spécifique associée à cette erreur. Votre code peut utiliser les informations contenues dans cet objet erreur pour donner une réponse appropriée à l’erreur. • Evénements d’erreur : il arrive qu’une erreur se produise lorsque le moteur d’exécution Flash déclencherait normalement un événement. Si tel est le cas, un événement d’erreur est alors déclenché. Chaque événement d’erreur étant associé à une classe, le moteur d’exécution de Flash transmet une occurrence de cette classe aux méthodes enregistrées auprès de l’événement d’erreur. Pour déterminer si une méthode donnée peut déclencher une erreur ou un événement d’erreur, voir la rubrique correspondante dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs à la programmation de routines de gestion des erreurs : Asynchrone Commande de programme telle qu’un appel de méthode qui ne fournit pas un résultat immédiat, mais qui produit un résultat (ou une erreur) sous la forme d’un événement. Capture Lorsqu’une exception (une erreur d’exécution) se produit et que votre code la découvre, ce dernier la capture. Lorsqu’une exception est capturée, le moteur d’exécution Flash cesse d’indiquer à un autre code ActionScript que l’exception s’est produite. Version de débogage Version spéciale du moteur d’exécution Flash, telle que la version de débogage de Flash Player ou l’application de débogage du lanceur AIR (ADL), qui contient le code requis pour avertir les utilisateurs de la présence d’erreurs d’exécution. Dans la version standard de Flash Player ou Adobe AIR (celle que possèdent la plupart des utilisateurs), les erreurs qui ne sont pas gérées par votre code ActionScript sont ignorées. Dans les versions de débogage (intégrées à Adobe Flash CS4 Professional et Adobe Flash Builder), un message d’avertissement apparaît lorsqu’une erreur non gérée se produit. Exception Erreur qui se produit lorsqu’une application est en cours d’exécution et que le moteur d’exécution Flash ne peut pas la résoudre seul. Renvoi Lorsque votre code capture une exception, le moteur d’exécution Flash cesse de signaler l’exception à d’autres objets. S’il est important pour d’autres objets que l’exception leur soit signalée, le code doit renvoyer l’exception pour recommencer le processus de notification. Synchrone Commande de programme (un appel de méthode, par exemple) qui fournit un résultat immédiat (ou qui renvoie immédiatement une erreur), ce qui signifie que la réponse peut être utilisée dans le même bloc de code. Envoi Le fait de signaler au moteur d’exécution Flash (et par conséquent, à d’autres objets et au code ActionScript) qu’une erreur s’est produite s’appelle envoyer une erreur. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 55 Gestion des erreurs Dernière mise à jour le 27/4/2013 Types d’erreurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous développez et exécutez des applications, vous rencontrez différents types d’erreurs et de termes. La liste suivante présente les principaux termes et types d’erreurs : • Erreurs de compilation : générées par le compilateur ActionScript lors de la compilation du code. Les erreurs de compilation ont lieu lorsque des problèmes de syntaxe dans votre code empêchent de créer votre application. • Erreurs d’exécution : générées lorsque vous exécutez votre application après l’avoir compilée. Les erreurs d’exécution représentent des erreurs qui se produisent lors de la lecture d’un fichier SWF dans un moteur d’exécution Flash tel qu’Adobe Flash Player ou Adobe AIR. Dans la plupart des cas, il est possible de gérer les erreurs d’exécution au moment où elles se produisent, de les signaler à l’utilisateur et de prendre les mesures requises pour poursuivre l’exécution de l’application. S’il s’agit d’une erreur grave (impossibilité de se connecter à un site Web distant ou de charger des données), vous pouvez utiliser la gestion des erreurs pour mettre fin à l’application en douceur. • Erreurs synchrones : erreurs d’exécution générées lorsqu’une fonction est appelée. Par exemple, lorsque vous tentez d’utiliser une méthode spécifique et que l’argument que vous lui transmettez n’est pas valide, le moteur d’exécution de Flash renvoie une exception. La plupart des erreurs se produisent en mode synchrone (au moment de l’exécution d’une instruction) et le flux de contrôle passe immédiatement à l’instruction catch la plus appropriée. Par exemple, l’extrait de code suivant renvoie une erreur d’exécution, car la méthode browse() n’est pas appelée avant que le programme ne tente de charger un fichier : var fileRef:FileReference = new FileReference(); try { fileRef.upload(new URLRequest("http://www.yourdomain.com/fileupload.cfm")); } catch (error:IllegalOperationError) { trace(error); // Error #2037: Functions called in incorrect sequence, or earlier // call was unsuccessful. } Dans ce cas, une erreur d’exécution est renvoyée de façon synchrone car Flash Player a déterminé que la méthode browse() n’a pas été appelée avant la tentative de chargement du fichier. Pour obtenir des informations détaillées relatives à la gestion des erreurs synchrones, voir « Gestion des erreurs synchrones dans une application » à la page 59. • Les erreursasynchrones sont des erreurs du moteur d’exécution qui se produisent hors du flux normal du programme. Elles génèrent des événements, interceptés par des écouteurs d’événement. Une opération asynchrone est une opération dans laquelle une fonction lance une opération mais n’attend pas qu’elle se termine. Vous pouvez créer un écouteur d’événements d’erreur pour attendre que l’application ou l’utilisateur tente une opération. Si cette dernière échoue, vous interceptez l’erreur avec un écouteur d’événements et répondez à l’événement d’erreur. Ensuite, l’écouteur d’événement appelle une fonction de gestionnaire d’événement pour répondre à l’événement d’erreur avec pertinence. Par exemple, le gestionnaire d’événement peut lancer une boîte de dialogue qui invite l’utilisateur à résoudre l’erreur. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 56 Gestion des erreurs Dernière mise à jour le 27/4/2013 Reprenez l’exemple d’erreur synchrone lors du chargement d’un fichier présenté précédemment. Si vous réussissez à appeler la méthode browse() avant de lancer le chargement d’un fichier, Flash Player distribue plusieurs événements. Par exemple, au démarrage d’un chargement, l’événement open est distribué. A la fin du chargement, l’événement complete est distribué. Etant donné que la gestion d’événements est asynchrone (c’est-à-dire qu’elle n’a pas lieu à des moments prédéfinis, connus et spécifiques), faites appel à la méthode addEventListener() pour détecter ces événements spécifiques, comme l’indique le code suivant : var fileRef:FileReference = new FileReference(); fileRef.addEventListener(Event.SELECT, selectHandler); fileRef.addEventListener(Event.OPEN, openHandler); fileRef.addEventListener(Event.COMPLETE, completeHandler); fileRef.browse(); function selectHandler(event:Event):void { trace("...select..."); var request:URLRequest = new URLRequest("http://www.yourdomain.com/fileupload.cfm"); request.method = URLRequestMethod.POST; event.target.upload(request); } function openHandler(event:Event):void { trace("...open..."); } function completeHandler(event:Event):void { trace("...complete..."); } Pour obtenir des informations détaillées sur la gestion des erreurs asynchrones, voir « Réponse à des événements et à l’état d’erreur » à la page 65. • Exceptions non interceptées : renvoyées sans logique correspondante (telle une instruction catch) pour y répondre. Si votre application renvoie une erreur, et qu’aucune instruction catch ni gestionnaire d’événement approprié n’est trouvé au niveau actuel ou supérieur pour gérer l’erreur, cette dernière est considérée comme une exception non interceptée. Lorsqu’il se produit une erreur non interceptée, le moteur d’exécution distribue un événement uncaughtError. Cet événement porte également le nom de « gestionnaire d’erreur global ». Il est distribué par l’objet UncaughtErrorEvents du fichier SWF et est proposé par la propriété LoaderInfo.uncaughtErrorEvents. Si aucun écouteur n’est enregistré pour l’événement uncaughtError, le moteur d’exécution ignore les erreurs non interceptées et tente de poursuivre son exécution, dès lors que l’erreur n’interrompt pas le fichier SWF. Outre la distribution de l’événement uncaughtError, les versions de débogage du moteur d’exécution de Flash répondent aux erreurs non interceptées en mettant fin au script actif. Elles affichent ensuite les erreurs non interceptées dans le résultat de l’instruction trace ou écrivent le message d’erreur dans un fichier journal. Si l’objet exception est une occurrence de la classe Error ou de l’une de ses sous-classes, les informations de trace de la pile s’affichent également dans le résultat. Pour plus d’informations sur l’utilisation de la version de débogage des moteurs d’exécution Flash, voir « Utilisation des versions de débogage des moteurs d’exécution Flash » à la page 58. Remarque : lors du traitement d’un événement uncaughtError, si un événement d’erreur est renvoyé par un gestionnaire uncaughtError, celui-ci est appelé plusieurs fois. Il se produit alors une boucle infinie d’exceptions. Il est donc recommandé d’éviter ce type de scénario. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 57 Gestion des erreurs Dernière mise à jour le 27/4/2013 Gestion des erreurs dans ActionScript 3.0 Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Etant donné que de nombreuses applications peuvent être exécutées sans créer de logique pour gérer les erreurs, les développeurs sont tentés de retarder la création de la gestion des erreurs dans leurs applications. Néanmoins, sans gestion des erreurs, une application risque de s’interrompre ou de poser des problèmes à l’utilisateur si elle ne fonctionne pas comme prévu. ActionScript 2.0 possède une classe Error qui vous permet de créer une logique dans des fonctions personnalisées afin de renvoyer une exception avec un message spécifique. Etant donné que la gestion des erreurs est cruciale pour rendre une application conviviale, ActionScript 3.0 inclut une architecture étendue pour intercepter les erreurs. Remarque : bien que le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash passe en revue les exceptions renvoyées par de nombreuses méthodes, il ne contient pas nécessairement toutes les exceptions associées à chaque méthode. une méthode risque de renvoyer une exception due à une erreur de syntaxe ou d’autres problèmes qui ne sont pas signalés explicitement dans la description de la méthode, même si cette dernière répertorie certaines exceptions renvoyées. Eléments de gestion des erreurs ActionScript 3.0 Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 3.0 comprend de nombreux outils permettant de gérer les erreurs, notamment : • Classes Error : ActionScript 3.0 comprend un large éventail de classes Error destinées à multiplier le nombre de situations susceptibles de produire des objets d’erreur. Chaque classe Error permet aux applications de gérer et de répondre à des conditions d’erreur spécifiques, qu’elles soient liées à des erreurs système (comme une condition MemoryError), à des erreurs de codage (comme une condition ArgumentError), à des erreurs de réseau et de communication (comme une condition URIError), ou d’autres situations. Pour plus d’informations sur chaque classe, voir « Comparaison des classes Error » à la page 68. • Moins d’échecs silencieux : dans les versions précédentes de Flash Player, les erreurs étaient générées et signalées uniquement si vous utilisiez explicitement l’instruction throw. Les méthodes et propriétés ActionScript natives renvoient des erreurs d’exécution pour le moteur d’exécution de Flash Player 9 et des versions ultérieures de Flash. Ces erreurs permettent de gérer les exceptions de manière plus efficace au moment où elles se produisent, puis de réagir à chaque exception. • Messages d’erreur clairs affichés lors du débogage : Lorsque vous utilisez la version de débogage d’un moteur d’exécution de Flash, les situations ou le code à l’origine du problème génèrent des messages d’erreur détaillés qui vous aident à identifier les raisons de l’échec d’un bloc de code particulier. Ces messages optimisent la résolution des erreurs. Pour plus d’informations, voir « Utilisation des versions de débogage des moteurs d’exécution Flash » à la page 58. • Les erreurs précises permettent d’afficher des messages d’erreur clairs pour les utilisateurs. Dans les versions précédentes de Flash Player, la méthode FileReference.upload() renvoyait la valeur booléenne false en cas d’échec de l’appel upload(), indiquant l’une des cinq erreurs possibles. Si une erreur se produit lorsque vous appelez la méthode upload() dans ActionScript 3.0, quatre erreurs spécifiques vous aident à afficher des messages d’erreur plus précis à l’intention des utilisateurs finaux. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 58 Gestion des erreurs Dernière mise à jour le 27/4/2013 • Gestion des erreurs affinée : des erreurs distinctes sont renvoyées pour de nombreuses situations courantes. Par exemple, dans ActionScript 2.0, avant qu’un objet FileReference ne soit renseigné, la propriété name possède la valeur null (par conséquent, avant d’utiliser ou d’afficher la propriété name, vérifiez qu’elle est définie sur une valeur autre que null). Dans ActionScript 3.0, si vous tentez d’accéder à la propriété name avant qu’elle ne soit renseignée, Flash Player ou AIR renvoie une erreur IllegalOperationError qui vous indique que la valeur n’a pas été définie. Vous pouvez utiliser des blocs try..catch..finally pour gérer l’erreur. Pour plus d’informations, voir « Utilisation des instructions try..catch..finally » à la page 59. • Aucun problème sérieux de performance : l’utilisation de blocs try..catch..finally pour gérer des erreurs ne nécessite pas ou peu de ressources supplémentaires par rapport aux versions précédentes d’ActionScript. • Une classe ErrorEvent qui vous permet de créer des écouteurs pour des événements d’erreurs asynchrones spécifiques : pour plus d’informations, voir « Réponse à des événements et à l’état d’erreur » à la page 65. Stratégies de gestion des erreurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Tant que l’application ne rencontre pas de condition problématique, vous pouvez continuer à l’exécuter sans créer de logique de gestion des erreurs dans le code. En revanche, si vous ne gérez pas d’erreurs de façon active et que votre application rencontre un problème, vos utilisateurs ignoreront toujours la raison de son échec. Vous pouvez aborder la gestion des erreurs de diverses façons dans votre application. La liste suivante résume les trois principales options de gestion des erreurs : • Utilisez les instructions try..catch..finally. Ces instructions interceptent les erreurs synchrones lorsqu’elles se produisent. Vous pouvez imbriquer vos instructions dans une hiérarchie pour intercepter des exceptions à différents niveaux d’exécution du code. Pour plus d’informations, voir « Utilisation des instructions try..catch..finally » à la page 59. • Créez des objets d’erreur personnalisés. Vous pouvez utiliser la classe Error pour créer des objets d’erreur personnalisés afin de suivre des opérations spécifiques dans votre application qui ne sont pas couvertes par des types d’erreur intégrés. Vous pouvez ensuite appliquer des instructions try..catch..finally aux objets d’erreur personnalisés. Pour plus d’informations, voir « Création de classes d’erreur personnalisées » à la page 64. • Ecrivez des gestionnaires et des écouteurs d’événement pour répondre à des événements d’erreur. Cette stratégie permet de créer des gestionnaires d’erreurs globaux destinés à gérer des événements similaires sans dupliquer un volume élevé de code dans les blocs try..catch..finally. Il est également plus probable que vous interceptiez des erreurs asynchrones à l’aide de cette approche. Pour plus d’informations, voir « Réponse à des événements et à l’état d’erreur » à la page 65. Utilisation des versions de débogage des moteurs d’exécution Flash Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Adobe propose aux développeurs des éditions spéciales des moteurs d’exécution Flash, destinées à les aider à exécuter des opérations de débogage. Vous obtenez une copie de la version de débogage de Flash Player lorsque vous installez Adobe Flash Professional ou Adobe Flash Builder. Vous disposez également d’un utilitaire de débogage des applications Adobe AIR, appelé ADL, lorsque vous installez l’un de ces outils ou dans le cadre de l’installation du SDK d’Adobe AIR. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 59 Gestion des erreurs Dernière mise à jour le 27/4/2013 Il existe une grande différence dans la façon dont les versions de débogage et les versions de Flash Player et Adobe AIR mises sur le marché signalent les erreurs. Les versions de débogage indiquent le type d’erreur (Error, IOError ou EOFError générique), le numéro de l’erreur et un message d’erreur sous une forme lisible par une personne. Les versions mises sur le marché indiquent uniquement le type d’erreur et son numéro. Considérons par exemple le code qui suit : try { tf.text = myByteArray.readBoolean(); } catch (error:EOFError) { tf.text = error.toString(); } Si la méthode readBoolean() renvoie une erreur EOFError dans la version de débogage de Flash Player, le message suivant s’affiche dans le champ de texte tf : « EOFError: Erreur #2030: Fin de fichier détectée ». Dans une version commerciale de Flash Player ou d’Adobe AIR, le même code afficherait le texte suivant : « EOFError: Erreur #2030 ». Remarque : étant donné que les lecteurs de débogage diffusent l’événement « allComplete », évitez de créer des événements personnalisés portant le nom « allComplete ». Vous risquez sinon de rencontrer un comportement imprévisible lors du débogage. Ce type de version ne comprend pas de chaîne de message d’erreur, afin de réduire au minimum la taille et les ressources requises. Vous pouvez consulter le numéro d’erreur dans la documentation (annexes du manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash) pour l’associer à un message d’erreur. Vous pouvez également reproduire l’erreur dans les versions de débogage de Flash Player et AIR pour visualiser le message entier. Gestion des erreurs synchrones dans une application Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La gestion des erreurs la plus courante est la logique de gestion des erreurs synchrones, qui consiste à insérer des instructions dans votre code pour intercepter les erreurs synchrones lors de l’exécution d’une application. Ce type de gestion des erreurs permet à votre application de repérer des erreurs d’exécution et de les résoudre lorsque des fonctions échouent. La logique d’interception d’une erreur synchrone fait appel aux instructions try..catch..finally, qui tentent littéralement une opération, interceptent toute réponse à l’erreur émanant du moteur d’exécution Flash, puis exécutent une autre opération pour gérer l’opération qui a échoué. Utilisation des instructions try..catch..finally Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous manipulez des erreurs d’exécution synchrones, utilisez les instructions try..catch..finally pour intercepter les erreurs. Lorsqu’une erreur d’exécution se produit, le moteur d’exécution Flash renvoie une exception, ce qui signifie qu’il suspend l’exécution normale et crée un objet spécial de type Error. L’objet Error est ensuite renvoyé au premier bloc catch disponible. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 60 Gestion des erreurs Dernière mise à jour le 27/4/2013 L’instruction try regroupe les instructions pouvant créer des erreurs. Vous utilisez toujours l’instruction catch avec une instruction try. Si une erreur est détectée dans l’une des instructions du bloc try, les instructions catch associées à cette instruction try sont exécutées. L’instruction finally regroupe les instructions exécutées, qu’une erreur se produise ou non dans le bloc try. S’il ne se produit pas d’erreur, les instructions du bloc finally sont exécutées au terme de l’exécution des instructions du bloc try. S’il se produit une erreur, l’instruction catch appropriée est exécutée en premier lieu, suivie des instructions du bloc finally. Le code suivant illustre la syntaxe d’utilisation des instructions try..catch..finally : try { // some code that could throw an error } catch (err:Error) { // code to react to the error } finally { // Code that runs whether an error was thrown. This code can clean // up after the error, or take steps to keep the application running. } Chaque instruction catch identifie un type d’exception spécifique qu’elle gère. L’instruction catch peut spécifier uniquement des classes d’erreur qui sont des sous-classes de la classe Error. Chaque instruction catch est vérifiée dans l’ordre. Seule la première instruction catch qui correspond au type d’erreur renvoyé est exécutée. En d’autres termes, si vous vérifiez d’abord la classe Error de niveau supérieur, puis une sous-classe de la classe Error, seule la classe Error de niveau supérieur est prise en compte. Le code suivant illustre ce point : try { throw new ArgumentError("I am an ArgumentError"); } catch (error:Error) { trace(" " + error.message); } catch (error:ArgumentError) { trace(" " + error.message); } Le code précédent affiche le résultat suivant : I am an ArgumentError Pour intercepter correctement l’erreur ArgumentError, assurez-vous que les types d’erreur les plus spécifiques sont répertoriés en premier, suivis des types d’erreur plus génériques, comme l’indique le code suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 61 Gestion des erreurs Dernière mise à jour le 27/4/2013 try { throw new ArgumentError("I am an ArgumentError"); } catch (error:ArgumentError) { trace(" " + error.message); } catch (error:Error) { trace(" " + error.message); } Plusieurs méthodes et propriétés de l’API d’ActionScript renvoient des erreurs d’exécution si elles en rencontrent lors de leur exécution. Par exemple, la méthode close() de la classe Sound renvoie une erreur IOError si la méthode ne parvient pas à fermer le flux audio, comme indiqué dans le code suivant : var mySound:Sound = new Sound(); try { mySound.close(); } catch (error:IOError) { // Error #2029: This URLStream object does not have an open stream. } Au fur et à mesure que vous vous familiariserez avec le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash, vous identifierez les méthodes qui renvoient des exceptions, comme indiqué dans la description de chaque méthode. Instruction throw Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les moteurs d’exécution Flash renvoient des exceptions s’ils rencontrent des erreurs lors de l’exécution de votre application. En outre, vous pouvez renvoyer des exceptions de façon explicite à l’aide de l’instruction throw. Si tel est le cas, Adobe vous conseille de renvoyer des occurrences de la classe Error ou de ses sous-classes. Le code suivant illustre une instruction throw qui renvoie une occurrence de la classe Error, MyErr, et appelle une fonction, myFunction() en réponse au renvoi de l’erreur : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 62 Gestion des erreurs Dernière mise à jour le 27/4/2013 var MyError:Error = new Error("Encountered an error with the numUsers value", 99); var numUsers:uint = 0; try { if (numUsers == 0) { trace("numUsers equals 0"); } } catch (error:uint) { throw MyError; // Catch unsigned integer errors. } catch (error:int) { throw MyError; // Catch integer errors. } catch (error:Number) { throw MyError; // Catch number errors. } catch (error:*) { throw MyError; // Catch any other error. } finally { myFunction(); // Perform any necessary cleanup here. } Les instructions catch sont classées de façon à ce que les types de données les plus spécifiques apparaissent en premier. Si l’instruction catch associée au type de données Number est répertoriée en premier, ni l’instruction catch associée au type de données uint, ni l’instruction catch associée au type de données int n’est exécutée. Remarque : dans le langage de programmation Java, chaque fonction qui peut renvoyer une exception doit le déclarer en répertoriant les classes d’exception qu’elle peut renvoyer dans une clause throws associée à la déclaration de la fonction. ActionScript ne requiert pas que vous déclariez les exceptions renvoyées par une fonction. Affichage d’un message d’erreur simple Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’un des avantages majeurs du nouveau modèle d’événement d’erreur et d’exception consiste à permettre d’informer les utilisateurs du moment où une action échoue et de la raison de cet échec. Votre rôle consiste à écrire le code pour afficher le message et à offrir des options en réponse. Le code suivant illustre une instruction try..catch simple permettant d’afficher l’erreur dans un champ de texte : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 63 Gestion des erreurs Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; import flash.text.TextField; public class SimpleError extends Sprite { public var employee:XML = 1234 1-234 ; public function SimpleError() { try { if (employee.costCenter.length() != 1) { throw new Error("Error, employee must have exactly one cost center assigned."); } } catch (error:Error) { var errorMessage:TextField = new TextField(); errorMessage.autoSize = TextFieldAutoSize.LEFT; errorMessage.textColor = 0xFF0000; errorMessage.text = error.message; addChild(errorMessage); } } } } En utilisant un plus grand nombre de classes d’erreur et d’erreurs de compilateur intégrées, ActionScript 3.0 fournit de plus amples informations sur les raisons de l’échec d’une action que les versions précédentes. Ces informations permettent de créer des applications plus stables qui gèrent mieux les erreurs. Renvoi des erreurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous créez une application, vous êtes parfois amené à renvoyer une erreur si vous ne parvenez pas à la gérer correctement. Par exemple, le code suivant illustre un bloc try..catch imbriqué, qui renvoie une erreur ApplicationError personnalisée si le bloc catch imbriqué n’est pas capable de gérer l’erreur : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 64 Gestion des erreurs Dernière mise à jour le 27/4/2013 try { try { trace("<< try >>"); throw new ApplicationError("some error which will be rethrown"); } catch (error:ApplicationError) { trace("<< catch >> " + error); trace("<< throw >>"); throw error; } catch (error:Error) { trace("<< Error >> " + error); } } catch (error:ApplicationError) { trace("<< catch >> " + error); } Le résultat issu du fragment de code précédent serait le suivant : << try >> << catch >> ApplicationError: some error which will be rethrown << throw >> << catch >> ApplicationError: some error which will be rethrown Le bloc try imbriqué renvoie une erreur ApplicationError personnalisée qui est interceptée par le bloc catch suivant. Ce bloc catch imbriqué peut tenter de gérer l’erreur et, si la tentative échoue, renvoyer l’objet ApplicationError au bloc try..catch. Création de classes d’erreur personnalisées Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez étendre l’une des classes Error standard pour créer vos classes d’erreur spécialisées dans ActionScript. Vous pouvez créer vos classes d’erreur pour les motifs suivants : • Identifier des erreurs ou des groupes d’erreurs spécifiques uniques pour votre application. Outre les erreurs interceptées par un moteur d’exécution de Flash, vous pouvez par exemple gérer différemment les erreurs renvoyées par votre propre code. Vous pouvez créer une sous-classe de la classe Error pour suivre le nouveau type de données d’erreur dans les blocs try..catch. • Fournir des fonctionnalités d’affichage d’erreurs exceptionnelles pour les erreurs générées par votre application. Par exemple, vous pouvez créer une méthode toString() qui formate vos messages d’erreur d’une certaine façon. Vous pouvez également définir une méthode lookupErrorString() qui prend un code d’erreur et récupère le message adéquat en fonction du langage que l’utilisateur préfère. Une classe d’erreur spécialisée doit étendre la classe Error d’ActionScript de base. Voici un exemple de classe AppError spécialisée qui étend la classe Error : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 65 Gestion des erreurs Dernière mise à jour le 27/4/2013 public class AppError extends Error { public function AppError(message:String, errorID:int) { super(message, errorID); } } L’exemple suivant illustre l’utilisation d’une classe AppError dans votre projet : try { throw new AppError("Encountered Custom AppError", 29); } catch (error:AppError) { trace(error.errorID + ": " + error.message) } Remarque : si vous souhaitez remplacer la méthode Error.toString() dans votre sous-classe, fournissez-lui un paramètre ...(rest). La spécification du langage ECMAScript sur laquelle est basé ActionScript 3.0 définit ainsi la méthode Error.toString() et ActionScript 3.0 respecte cette définition à des fins de rétrocompatibilité. Par conséquent, lorsque vous remplacez la méthode Error.toString(), veillez à ce que les paramètres se correspondent exactement. Vous ne pouvez pas transmettre de paramètres à la méthode toString() lors de l’exécution, car ils sont ignorés. Réponse à des événements et à l’état d’erreur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’une des améliorations majeures apportées à la gestion des erreurs dans ActionScript 3.0 est la prise en charge de la gestion des événements d’erreur pour répondre à des erreurs asynchrones lors de l’exécution d’une application. (Pour obtenir une définition des erreurs asynchrones, voir « Types d’erreurs » à la page 55). Vous pouvez créer des écouteurs d’événement et des gestionnaires d’événements pour répondre aux événements d’erreurs. De nombreuses classes distribuent des événements d’erreurs de la même façon que d’autres événements. Par exemple, une occurrence de la classe XMLSocket distribue normalement trois types d’événements :Event.CLOSE, Event.CONNECT et DataEvent.DATA. Néanmoins, lorsqu’un problème se produit, la classe XMLSocket peut distribuer IOErrorEvent.IOError ou SecurityErrorEvent.SECURITY_ERROR. Pour plus d’informations sur les écouteurs et les gestionnaires d’événement, voir « Gestion des événements » à la page 129. Les événements d’erreurs peuvent être classés en deux catégories : • Evénements d’erreurs qui étendent la classe ErrorEvent La classe flash.events.ErrorEvent contient les propriétés et les méthodes permettant de gérer les erreurs d’exécution liées à des opérations de réseau et de communication dans une application en cours d’exécution. Les classes AsyncErrorEvent, IOErrorEvent et SecurityErrorEvent étendent la classe ErrorEvent. Si vous utilisez la version de débogage d’un moteur d’exécution de Flash, une boîte de dialogue vous informe, lors de l’exécution, de la présence d’événements d’erreurs sans fonctions d’écouteur rencontrés par le lecteur. • Evénements d’erreurs basés sur le statut GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 66 Gestion des erreurs Dernière mise à jour le 27/4/2013 Les événements d’erreur basés sur le statut sont liés aux propriétés netStatus et status des classes de communication et de réseau. Si un moteur d’exécution Flash rencontre un problème lors de la lecture ou de l’écriture des données, la valeur des propriétés netStatus.info.level ou status.level (selon l’objet de classe que vous utilisez) est définie sur la valeur "error". Vous répondez à cette erreur en vérifiant que la propriété level contient la valeur "error" dans votre fonction de gestionnaire d’événement. Utilisation d’événements d’erreurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe ErrorEvent et ses sous-classes contiennent des types d’erreurs destinés à gérer les erreurs distribuées par les moteurs d’exécution Flash lorsqu’ils tentent de lire ou d’écrire des données. L’exemple suivant utilise à la fois une instruction try..catch et des gestionnaires d’événement d’erreur pour afficher toute erreur détectée lors de la tentative de lecture d’un fichier local. Vous pouvez ajouter un code de gestion plus élaboré pour proposer des options à l’utilisateur ou gérer l’erreur automatiquement aux endroits indiqués par le commentaire « your error-handling code here » : package { import flash.display.Sprite; import flash.errors.IOError; import flash.events.IOErrorEvent; import flash.events.TextEvent; import flash.media.Sound; import flash.media.SoundChannel; import flash.net.URLRequest; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class LinkEventExample extends Sprite { private var myMP3:Sound; public function LinkEventExample() { myMP3 = new Sound(); var list:TextField = new TextField(); list.autoSize = TextFieldAutoSize.LEFT; list.multiline = true; list.htmlText = "Track 1
"; list.htmlText += "Track 2
"; addEventListener(TextEvent.LINK, linkHandler); addChild(list); } private function playMP3(mp3:String):void { try { myMP3.load(new URLRequest(mp3)); myMP3.play(); } catch (err:Error) GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 67 Gestion des erreurs Dernière mise à jour le 27/4/2013 { trace(err.message); // your error-handling code here } myMP3.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); } private function linkHandler(linkEvent:TextEvent):void { playMP3(linkEvent.text); // your error-handling code here } private function errorHandler(errorEvent:IOErrorEvent):void { trace(errorEvent.text); // your error-handling code here } } } Utilisation d’événements de changement de statut Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les moteurs d’exécution Flash changent dynamiquement la valeur des propriétés netStatus.info.level ou status.level pour les classes qui prennent en charge la propriété level pendant qu’une application s’exécute. Les classes qui ont la propriété netStatus.info.level sont NetConnection, NetStream et SharedObject. Les classes qui ont la propriété status.level sont HTTPStatusEvent, Camera, Microphone et LocalConnection. Vous pouvez écrire une fonction de gestionnaire pour répondre au changement de valeur level et suivre les erreurs de communication. L’exemple suivant utilise une fonction netStatusHandler() pour tester la valeur de la propriété level. Si la propriété level indique qu’une erreur a été rencontrée, le code suit le message « Video stream failed ». package { import flash.display.Sprite; import flash.events.NetStatusEvent; import flash.events.SecurityErrorEvent; import flash.media.Video; import flash.net.NetConnection; import flash.net.NetStream; public class VideoExample extends Sprite { private var videoUrl:String = "Video.flv"; private var connection:NetConnection; private var stream:NetStream; public function VideoExample() { connection = new NetConnection(); connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); connection.connect(null); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 68 Gestion des erreurs Dernière mise à jour le 27/4/2013 private function netStatusHandler(event:NetStatusEvent):void { if (event.info.level == "error") { trace("Video stream failed") } else { connectStream(); } } private function securityErrorHandler(event:SecurityErrorEvent):void { trace("securityErrorHandler: " + event); } private function connectStream():void { var stream:NetStream = new NetStream(connection); var video:Video = new Video(); video.attachNetStream(stream); stream.play(videoUrl); addChild(video); } } } Comparaison des classes Error Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript fournit de nombreuses classes Error prédéfinies. Vous pouvez toutefois faire appel aux mêmes classes Error dans votre propre code. Il existe deux types principaux de classes Error dans ActionScript 3.0 : les classes Error de base d’ActionScript et les classes Error du package flash.error. Le package flash.error contient des classes supplémentaires permettant le débogage et le développement d’applications ActionScript 3.0. Classes Error de base Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Parmi les classes Error de base figurent les classes Error, ArgumentError, EvalError, RangeError, ReferenceError, SecurityError, SyntaxError, TypeError, URIError et VerifyError. Chacune de ces classes se trouve dans l’espace de noms de niveau supérieur. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 69 Gestion des erreurs Dernière mise à jour le 27/4/2013 Nom de classe Description Remarques Error La classe Error permet de renvoyer des exceptions et correspond à la classe de base des autres classes d’exception définies dans ECMAScript : EvalError, RangeError, ReferenceError, SyntaxError, TypeError et URIError. La classe Error sert de classe de base à toutes les erreurs d’exécution et est recommandée pour toutes les classes d’erreur personnalisées. ArgumentError La classe ArgumentError représente une erreur qui se produit lorsque les valeurs de paramètre fournies lors d’un appel de fonction ne correspondent pas aux paramètres définis pour celle-ci. Voici des exemples d’erreurs d’argument : • Trop ou trop peu d’arguments sont fournis à une méthode. • Un argument devait être membre d’une énumération, et cela n’a pas été le cas. EvalError Une exception EvalError est renvoyée si des paramètres sont transmis au constructeur de la classe Function ou si le code utilisateur appelle la fonction eval(). Dans ActionScript 3.0, la prise en charge de la fonction eval() a été supprimée et toute tentative d’utilisation de la fonction entraîne le renvoi d’une erreur. Les versions précédentes de Flash Player utilisaient la fonction eval() pour accéder à des variables, des propriétés, des objets ou des clips par nom. RangeError Une exception RangeError est renvoyée si une valeur numérique excède la plage acceptable. Par exemple, une exception RangeError est renvoyée par la classe Timer si un retard est négatif ou infini. Elle peut également être renvoyée si vous tentez d’ajouter un objet d’affichage à une profondeur non valide. ReferenceError Une exception ReferenceError est renvoyée lorsque vous tentez d’utiliser une référence à une propriété non définie pour un objet scellé (non dynamique). Les versions du compilateur ActionScript antérieures à ActionScript 3.0 ne renvoyaient pas d’erreur lorsque vous tentiez d’accéder à une propriété non définie. ActionScript 3.0 renvoie toutefois l’exception ReferenceError dans ce cas de figure. Les exceptions pour des variables non définies pointent vers des bogues éventuels afin d’améliorer la qualité du logiciel. Cependant, si vous n’avez pas l’habitude d’initialiser les variables, ce nouveau comportement d’ActionScript requiert de vous quelques changements lorsque vous écrivez du code. SecurityError L’exception SecurityError est renvoyée lorsqu’une violation de sécurité se produit et que l’accès est refusé. Voici des exemples d’erreurs de sécurité : • Un accès à une propriété ou un appel de méthode non autorisé est effectué en franchissant les limites du sandbox de sécurité. • Il s’est produit une tentative d’accès à une URL non autorisée par le sandbox de sécurité. • Il s’est produit une tentative de connexion socket sur un port, mais le fichier de régulation socket approprié n’était pas présent. • Il s’est produit une tentative d’accès à la caméra ou au microphone de l’utilisateur et celui-ci a refusé l’accès au périphérique. SyntaxError Une exception SyntaxError est renvoyée lorsqu’il se produit une erreur d’analyse dans votre code ActionScript. Une exception SyntaxError peut être renvoyée dans les cas suivants : • ActionScript renvoie des exceptions SyntaxError lorsque la classe RegExp analyse une expression régulière non valide. • ActionScript renvoie des exceptions SyntaxError lorsque la classe XMLDocument analyse un code XML non valide. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 70 Gestion des erreurs Dernière mise à jour le 27/4/2013 Classes Error du package flash.error Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le package flash.error contient des classes Error considérées comme parties intégrantes de l’API des moteurs d’exécution de Flash. A l’encontre des classes Error décrites, le package flash.error communique les événements d’erreurs propres aux moteurs d’exécution de Flash (tel Flash Player ou Adobe AIR). TypeError L’exception TypeError est renvoyée lorsque le type réel d’un opérande ne correspond pas au type prévu. Une exception TypeError peut être renvoyée dans les cas suivants : • Un paramètre réel de fonction ou de méthode ne peut pas être forcé à correspondre au type de paramètre formel. • Une valeur est affectée à une variable et ne peut pas être forcée à correspondre au type de la variable. • Le côté droit de l’opérateur is ou instanceof n’est pas un type valide. • L’utilisation du mot clé super n’est pas valide. • Une recherche de propriété donne lieu à plusieurs liaisons, soit un résultat ambigu. • Une méthode est appelée pour un objet incompatible. Par exemple, une exception TypeError est renvoyée si une méthode de la classe RegExp est « greffée » sur un objet générique, puis appelée. URIError L’exception URIError est renvoyée lorsque l’une des fonctions de gestion URI globales est utilisée d’une manière qui n’est pas compatible avec sa définition. Une exception URIError peut être renvoyée dans les cas suivants : Un URI non valide est défini par une fonction API de Flash Player qui s’attend à un URI valide, comme Socket.connect(). VerifyError Une erreur VerifyError est renvoyée lorsqu’un fichier SWF incorrect ou altéré est détecté. Lorsqu’un fichier SWF charge un autre fichier SWF, le fichier SWF parent peut intercepter une exception VerifyError générée par le fichier SWF chargé. Nom de classe Description Remarques GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 71 Gestion des erreurs Dernière mise à jour le 27/4/2013 Nom de classe Description Remarques EOFError Une exception EOFError est émise lors d’une tentative de lecture au-delà de la fin des données disponibles. Par exemple, une exception EOFError est émise chaque fois qu’une méthode de lecture de l’interface IDataInput est appelée et que les données sont insuffisantes pour répondre à la requête de lecture. IllegalOperationError Une exception IllegalOperationError est renvoyée lorsqu’une méthode n’est pas implémentée ou si l’implémentation ne couvre pas l’utilisation actuelle. Voici quelques exemples d’exceptions d’erreurs liées à des opérations non valides : • Une classe de base, telle que DisplayObjectContainer, propose plus de fonctionnalités qu’une scène ne peut prendre en charge. Par exemple, si vous tentez d’obtenir ou de définir un masque sur la scène (à l’aide de stage.mask), le moteur d’exécution de Flash renvoie une exception IllegalOperationError accompagnée du message « La classe Stage n’implémente ni cette propriété, ni cette méthode ». • Une sous-classe hérite d’une méthode dont elle n’a pas besoin et qu’elle ne souhaite pas prendre en charge. • Certaines méthodes d’accessibilité sont appelées lorsque Flash Player est compilé sans les fonctions d’accessibilité. • Les fonctions réservées à la création sont appelées à partir d’une version d’exécution de Flash Player. • Vous tentez de définir le nom d’un objet placé sur le scénario. IOError Une exception IOError est renvoyée lorsqu’un type d’exception E/S se produit. Vous obtenez cette erreur, par exemple, lorsque vous tentez une opération de lecture-écriture sur un socket qui n’est pas connecté ou qui est déconnecté. MemoryError Une exception MemoryError est renvoyée lors de l’échec d’une requête d’allocation de mémoire. Par défaut, ActionScript Virtual Machine 2 n’impose pas de limite à la quantité de mémoire allouée par un programme ActionScript. Sur un système de bureau, les échecs d’allocation de mémoire sont rares. Une erreur est renvoyée lorsque le système ne parvient pas à allouer la mémoire requise pour une opération. Par conséquent, sur un système de bureau, cette exception est peu fréquente, à moins qu’une requête d’allocation ne soit extrêmement importante (par exemple, une requête de 3 milliards d’octets est impossible, car un programme Microsoft® Windows® de 32 bits peut accéder à 2 Go d’espace d’adressage uniquement). ScriptTimeoutError Une exception ScriptTimeoutError est renvoyée lorsqu’un intervalle de délai d’expiration du script de 15 secondes est atteint. En interceptant une exception ScriptTimeoutError, vous pouvez gérer le délai d’expiration du script plus en douceur. Si aucun gestionnaire d’exception n’est défini, le gestionnaire de l’exception non interceptée affiche une boîte de dialogue contenant un message d’erreur. Pour éviter qu’un développeur n’intercepte l’exception et reste dans une boucle sans fin, seule la première exception ScriptTimeoutError renvoyée au cours d’un script donné peut être interceptée. Le code ne peut pas intercepter une exception ScriptTimeoutError ultérieure. Elle passe donc immédiatement au gestionnaire de l’exception non interceptée. StackOverflowError L’exception StackOverflowError est renvoyée lorsque la pile disponible pour le script a été épuisée. Une exception StackOverflowError peut indiquer qu’un problème de récursivité à l’infini s’est produit. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 72 Gestion des erreurs Dernière mise à jour le 27/4/2013 Exemple de gestion des erreurs : application CustomErrors Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application CustomErrors décrit les techniques d’utilisation des erreurs personnalisées lors de la création d’une application. Ces techniques sont les suivantes : • Validation d’un paquet XML • Ecriture d’une erreur personnalisée • Renvoi d’erreurs personnalisées • Notification des utilisateurs lors du renvoi d’une erreur Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application CustomErrors se trouvent dans le dossier Samples/CustomError. L’application se compose des fichiers suivants : Présentation de l’application CustomErrors Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Au chargement de l’application, la méthode initApp() est appelée dans les applications Flex ou le code du scénario (autre qu’une fonction) est exécuté dans les applications Flash Professional. Ce code définit un exemple de paquet XML que la classe Validator vérifiera. Le code suivant est exécuté : employeeXML = John Doe 12345 67890 ; } Le paquet XML est ensuite affiché dans une occurrence du composant TextArea sur la scène. Cette étape permet de modifier le paquet XML avant de tenter de le revalider. Fichier Description CustomErrors.mxml ou CustomErrors.fla Fichier d’application principal en FLA pour Flash ou en MXML pour Flex com/example/programmingas3/errors/ApplicationError.as Une classe servant de classe Error de base pour les classes FatalError et WarningError. com/example/programmingas3/errors/FatalError.as Une classe qui définit une erreur FatalError renvoyée par l’application. Cette classe étend la classe ApplicationError personnalisée. com/example/programmingas3/errors/Validator.as Une classe qui définit une seule méthode qui valide un paquet XML employee fourni par l’utilisateur. com/example/programmingas3/errors/WarningError.as Une classe qui définit une erreur WarningError renvoyée par l’application. Cette classe étend la classe ApplicationError personnalisée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 73 Gestion des erreurs Dernière mise à jour le 27/4/2013 Lorsque l’utilisateur clique sur le bouton de validation, la méthode validateData() est appelée. Cette méthode valide le paquet XML employee à l’aide de la méthode validateEmployeeXML() de la classe Validator. Le code suivant présente la méthode validateData() : function validateData():void { try { var tempXML:XML = XML(xmlText.text); Validator.validateEmployeeXML(tempXML); status.text = "The XML was successfully validated."; } catch (error:FatalError) { showFatalError(error); } catch (error:WarningError) { showWarningError(error); } catch (error:Error) { showGenericError(error); } } Un objet XML temporaire est d’abord créé à l’aide du contenu de l’occurrence du composant TextArea xmlText. La méthode validateEmployeeXML() de la classe Validator personnalisée (com.example.programmingas3/errors/Validator.as) est ensuite appelée et transmet l’objet XML temporaire comme paramètre. Si le paquet XML est valide, l’occurrence du composant Label status affiche un message de réussite et l’application se ferme. Si la méthode validateEmployeeXML() renvoie une erreur personnalisée (c’est-à-dire qu’une erreur FatalError, WarningError ou une erreur générique se produit), l’instruction catch appropriée s’exécute et appelle les méthodes showFatalError(), showWarningError() ou showGenericError(). Chacune de ces méthodes affiche un message approprié dans une zone de texte appelée statusText pour avertir l’utilisateur de l’erreur spécifique qui s’est produite. Chaque méthode met également à jour l’occurrence du composant Label status avec un message spécifique. Si une erreur grave se produit pendant une tentative de validation du paquet XML employee, le message d’erreur s’affiche dans la zone de texte statusText et l’occurrence du composant TextArea xmlText et l’occurrence du composant Button validateBtn sont désactivées, comme l’indique le code suivant : function showFatalError(error:FatalError):void { var message:String = error.message + "\n\n"; var title:String = error.getTitle(); statusText.text = message + " " + title + "\n\nThis application has ended."; this.xmlText.enabled = false; this.validateBtn.enabled = false; hideButtons(); } S’il se produit une erreur d’avertissement au lieu d’une erreur grave, le message d’erreur est affiché dans l’occurrence de TextArea statusText, mais les occurrences de composant TextField xmlText et Button ne sont pas désactivées. La méthode showWarningError() affiche le message d’erreur personnalisé dans la zone de texte statusText. Le message invite également l’utilisateur à indiquer s’il souhaite poursuivre la validation de l’objet XML ou annuler le script. Le fragment de code suivant présente la méthode showWarningError() : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 74 Gestion des erreurs Dernière mise à jour le 27/4/2013 function showWarningError(error:WarningError):void { var message:String = error.message + "\n\n" + "Do you want to exit this application?"; showButtons(); var title:String = error.getTitle(); statusText.text = message; } Lorsque l’utilisateur clique sur le bouton Oui ou Non, la méthode closeHandler() est appelée. Le fragment de code suivant présente la méthode closeHandler() : function closeHandler(event:CloseEvent):void { switch (event.detail) { case yesButton: showFatalError(new FatalError(9999)); break; case noButton: statusText.text = ""; hideButtons(); break; } } Si l’utilisateur souhaite annuler le script en cliquant sur Oui, une exception FatalError est renvoyée, provoquant l’arrêt de l’application. Création d’une validation personnalisée Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Validator personnalisée contient une seule méthode, validateEmployeeXML(). La méthode validateEmployeeXML() gère un seul argument, employee, qui correspond au paquet XML à valider. La méthode validateEmployeeXML() est la suivante : public static function validateEmployeeXML(employee:XML):void { // checks for the integrity of items in the XML if (employee.costCenter.length() < 1) { throw new FatalError(9000); } if (employee.costCenter.length() > 1) { throw new WarningError(9001); } if (employee.ssn.length() != 1) { throw new FatalError(9002); } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 75 Gestion des erreurs Dernière mise à jour le 27/4/2013 Un employé doit appartenir à un (et un seul) centre de coût pour être validé. S’il n’appartient à aucun centre de coût, la méthode renvoie une erreur FatalError, qui se propage jusqu’à la méthode validateData() dans le fichier d’application principale. Si l’employé appartient à plusieurs centres de coût, une erreur WarningError est renvoyée. La dernière vérification de la validation XML contrôle que l’utilisateur possède un seul numéro de sécurité sociale défini (le noeud ssn dans le paquet XML). S’il n’y a pas exactement un noeud ssn, une erreur FatalError est renvoyée. Vous pouvez ajouter des vérifications supplémentaires à la méthode validateEmployeeXML() afin de vérifier, par exemple, que le noeud ssn contient un numéro valide, ou que l’employé possède au moins un numéro de téléphone et une adresse électronique, et que ces deux valeurs sont valides. Vous pouvez également modifier le XML de façon à ce que chaque employé ait un ID unique et spécifie l’ID de son responsable. Définition de la classe ApplicationError Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe ApplicationError sert de classe de base aux classes FatalError et WarningError. Elle étend la classe Error et définit ses propres propriétés et méthodes personnalisées, y compris un ID d’erreur, la gravité et un objet XML contenant les codes d’erreur personnalisés et les messages. Cette classe définit également deux constantes statiques utilisées pour définir la gravité de chaque type d’erreur. La méthode du constructeur de la classe ApplicationError est la suivante : public function ApplicationError() { messages = ; } Chaque noeud d’erreur dans l’objet XML contient un code numérique unique et un message d’erreur. Vous pouvez consulter facilement les messages d’erreur par code d’erreur à l’aide d’E4X, comme indiqué dans la méthode getMessageText() suivante : public function getMessageText(id:int):String { var message:XMLList = messages.error.(@code == id); return message[0].text(); } La méthode getMessageText() prend un seul argument entier, id, et renvoie une chaîne. L’argument id correspond au code de l’erreur à rechercher. Par exemple, lorsque vous transmettez un id de 9001, l’erreur indiquant que les employés doivent être affectés à un seul centre de coût est renvoyée. Si plusieurs erreurs ont le même code, ActionScript renvoie le message d’erreur uniquement pour le premier résultat trouvé (message[0] dans l’objet XMLList renvoyé). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 76 Gestion des erreurs Dernière mise à jour le 27/4/2013 La méthode suivante de cette classe, getTitle(), ne prend aucun paramètre et renvoie une valeur de chaîne qui contient l’ID de cette erreur spécifique. Cette valeur permet d’identifier aisément l’erreur exacte qui s’est produite lors de la validation du paquet XML. Le fragment de code suivant présente la méthode getTitle() : public function getTitle():String { return "Error #" + id; } La dernière méthode finale de la classe ApplicationError est toString(). Cette méthode remplace la fonction définie dans la classe Error pour que vous puissiez personnaliser la présentation du message d’erreur. La méthode renvoie une chaîne qui identifie le numéro d’erreur spécifique et le message qui s’est affiché. public override function toString():String { return "[APPLICATION ERROR #" + id + "] " + message; } Définition de la classe FatalError Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe FatalError étend la classe ApplicationError personnalisée et définit trois méthodes : le constructeur FatalError, getTitle() et toString(). La première méthode, le constructeur FatalError, prend un seul argument entier, errorID, et définit la gravité de l’erreur à l’aide des valeurs de constante statiques définies dans la classe ApplicationError. Elle obtient le message de l’erreur spécifique en appelant la méthode getMessageText() dans la classe ApplicationError. Le constructeur FatalError se présente comme suit : public function FatalError(errorID:int) { id = errorID; severity = ApplicationError.FATAL; message = getMessageText(errorID); } La méthode suivante de la classe FatalError, getTitle(), remplace la méthode getTitle() définie précédemment dans la classe ApplicationError et ajoute le texte “-- FATAL” dans le titre pour informer l’utilisateur qu’une erreur grave s’est produite. La méthode getTitle() se présente comme suit : public override function getTitle():String { return "Error #" + id + " -- FATAL"; } La méthode finale dans cette classe, toString(), remplace la méthode toString() définie dans la classe ApplicationError. La méthode toString() est la suivante : public override function toString():String { return "[FATAL ERROR #" + id + "] " + message; } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 77 Gestion des erreurs Dernière mise à jour le 27/4/2013 Définition de la classe WarningError Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe WarningError étend la classe ApplicationError et est presque identique à la classe FatalError, à l’exception de quelques changements de chaîne mineurs. Elle définit la gravité de l’erreur sur ApplicationError.WARNING au lieu de ApplicationError.FATAL, comme indiqué dans le code suivant : public function WarningError(errorID:int) { id = errorID; severity = ApplicationError.WARNING; message = super.getMessageText(errorID); } 78 Dernière mise à jour le 27/4/2013 Chapitre 5 : Utilisation d’expressions régulières Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Une expression régulière décrit un modèle servant à rechercher et à manipuler du texte de correspondance dans des chaînes. Les expressions régulières ressemblent à des chaînes, mais elles comprennent des codes spéciaux pour décrire des modèles et des répétitions. Par exemple, l’expression régulière suivante correspond à une chaîne qui commence par le caractère A suivi d’un ou de plusieurs chiffres séquentiels : /A\d+/ Les rubriques suivantes sont consacrées à la syntaxe de base de construction d’expressions régulières. Néanmoins, les expressions régulières peuvent être très complexes et comporter de nombreuses nuances. Vous pouvez vous documenter sur les expressions régulières sur le Web et dans les librairies. Différents environnements de programmation implémentent des expressions régulières de différentes façons. ActionScript 3.0 implémente des expressions régulières comme défini dans la version 3 de la spécification du langage ECMAScript (ECMA-262). Voir aussi RegExp Principes de base des expressions régulières Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Une expression régulière décrit un modèle de caractères. Les expressions régulières servent généralement à vérifier qu’une valeur de texte est conforme à un modèle particulier (par exemple, vérifier qu’un numéro de téléphone saisi par l’utilisateur comporte le nombre de chiffres correct) ou à remplacer des portions d’une valeur de texte qui correspondent à un modèle donné. Les expressions régulières peuvent être simples. Par exemple, supposons que vous souhaitiez confirmer qu’une chaîne particulière correspond à ABC ou que vous souhaitiez remplacer chaque occurrence d’ABC dans une chaîne par un autre texte. Dans ce cas, vous pouvez utiliser l’expression régulière suivante qui définit le modèle comportant les lettres A, B et C, dans l’ordre : /ABC/ Le littéral de l’expression régulière est délimité avec la barre oblique (/). Les modèles d’expression régulière peuvent également être complexes et parfois sembler obscures, comme l’expression suivante pour établir une correspondance avec une adresse électronique valide : /([0-9a-zA-Z]+[-._+&])*[0-9a-zA-Z]+@([-0-9a-zA-Z]+[.])+[a-zA-Z]{2,6}/ GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 79 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Vous utiliserez le plus souvent des expressions régulières pour rechercher des modèles dans des chaînes et pour remplacer des caractères. Dans ces cas, vous créerez un objet d’expression régulière et l’utiliserez comme paramètre pour une ou plusieurs méthodes de classe String. Les méthodes suivantes de la classe String prennent des expressions régulières comme paramètres : match(), replace(), search() et split(). Pour plus d’informations sur ces méthodes, voir « Recherche de modèles dans des chaînes et remplacement de sous-chaînes » à la page 17. La classe RegExp comprend les méthodes suivantes : test() et exec(). Pour plus d’informations, voir « Méthodes d’utilisation d’expressions régulières avec des chaînes » à la page 93. Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs à la fonctionnalité étudiée. Caractère d’échappement Caractère indiquant que le caractère qui suit doit être considéré comme un caractère de remplacement plutôt que comme un caractère littéral. Dans une syntaxe d’expression régulière, la barre oblique inverse (\) est le caractère d’échappement. Par conséquent, une barre oblique inverse suivie d’un autre caractère est un code spécial plutôt que le caractère à proprement parler. Indicateur Caractère qui spécifie une option associée au mode d’utilisation du modèle d’expression régulière (respect de la casse, par exemple). Caractère de remplacement Caractère qui a une signification spéciale dans un modèle d’expression régulière et qui ne représente pas littéralement ce caractère dans le modèle. Quantificateur Caractères indiquant le nombre de répétitions d’une partie du modèle. Par exemple, un quantificateur peut être utilisé pour indiquer qu’un code postal américain doit contenir cinq ou neuf chiffres. Expression régulière Instruction de programme définissant un modèle de caractères qui permet de confirmer si d’autres chaînes correspondent à ce modèle ou de remplacer des sections d’une chaîne. Syntaxe d’expression régulière Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Cette section décrit tous les éléments de la syntaxe d’expression régulière d’ActionScript. Comme vous pourrez le constater, les expressions régulières peuvent être très complexes et comporter de nombreuses nuances. Vous pouvez vous documenter sur les expressions régulières sur le Web et dans les librairies. Différents environnements de programmation implémentent des expressions régulières de différentes façons. ActionScript 3.0 implémente des expressions régulières comme défini dans la version 3 de la spécification du langage ECMAScript (ECMA-262). Généralement, vous utilisez des expressions régulières qui correspondent à des modèles plus compliqués qu’une simple chaîne de caractères. Par exemple, l’expression régulière suivante définit le modèle comportant les lettres A, B et C, dans l’ordre, suivies par un chiffre : /ABC\d/ Le code \d représente un chiffre. La barre oblique inverse (\) est appelée caractère d’échappement. Lorsqu’elle est combinée au caractère qui la suit (dans ce cas, la lettre d), elle a une signification spéciale dans l’expression régulière. L’expression régulière suivante définit le modèle des lettres ABC suivies par des chiffres (remarquez l’astérisque) : /ABC\d*/ GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 80 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 L’astérisque (*) est un caractère de remplacement. Un caractère de remplacement est un caractère ayant une signification spéciale dans les expressions régulières. L’astérisque est un type de caractère de remplacement spécifique appelé quantificateur, utilisé pour quantifier le nombre de répétitions d’un caractère ou groupe de caractères. Pour plus de détails, voir « Quantificateurs » à la page 85. Outre son modèle, une expression régulière peut contenir des indicateurs qui spécifient comment l’expression régulière doit être mise en correspondance. Par exemple, l’expression régulière suivante utilise l’indicateur i qui indique qu’elle ignore le respect de la casse dans les chaînes de correspondance : /ABC\d*/i Pour plus d’informations, voir « Indicateurs et propriétés » à la page 89. Vous pouvez utiliser des expressions régulières à l’aide des méthodes suivantes de la classe String : match(), replace() et search(). Pour plus d’informations sur ces méthodes, voir « Recherche de modèles dans des chaînes et remplacement de sous-chaînes » à la page 17. Création d’une occurrence d’expression régulière Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Il existe deux façons de créer une occurrence d’expression régulière. L’une des méthodes consiste à utiliser des barres obliques (/) pour délimiter l’expression régulière, et l’autre consiste à utiliser le constructeur new. Par exemple, les expressions régulières suivantes sont équivalentes : var pattern1:RegExp = /bob/i; var pattern2:RegExp = new RegExp("bob", "i"); Des barres obliques délimitent un littéral d’expression régulière de la même façon que des guillemets délimitent un littéral de chaîne. La partie de l’expression régulière contenue entre les barres obliques définit le modèle. L’expression régulière peut également inclure des indicateurs après la barre de délimitation finale. Ces indicateurs sont considérés comme faisant partie de l’expression régulière, mais ils sont séparés de son modèle. Lorsque vous utilisez le constructeur new, vous utilisez deux chaînes pour définir l’expression régulière. La première chaîne définit le modèle, et la seconde les indicateurs, comme dans l’exemple suivant : var pattern2:RegExp = new RegExp("bob", "i"); Lorsque vous incluez une barre oblique dans une expression régulière qui est définie à l’aide de délimiteurs de barre oblique, vous devez faire précéder la barre oblique du caractère d’échappement (\). Par exemple, l’expression régulière suivante correspond au modèle 1/2 : var pattern:RegExp = /1\/2/; Pour inclure des guillemets dans une expression régulière définie avec le constructeur new, vous devez ajouter un caractère d’échappement (\) avant les guillemets (comme lorsque vous définissez un littéral String). Par exemple, les expressions régulières suivantes correspondent au modèle eat at "joe's" : var pattern1:RegExp = new RegExp("eat at \"joe's\"", ""); var pattern2:RegExp = new RegExp('eat at "joe\'s"', ""); N’utilisez pas le caractère d’échappement avec des guillemets dans des expressions régulières définies à l’aide des délimiteurs de barre oblique. De même, n’utilisez pas le caractère d’échappement avec des barres obliques dans des expressions régulières définies avec le constructeur new. Les expressions régulières suivantes sont équivalentes. Elles définissent le modèle 1/2 "joe's" : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 81 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 var pattern1:RegExp = /1\/2 "joe's"/; var pattern2:RegExp = new RegExp("1/2 \"joe's\"", ""); var pattern3:RegExp = new RegExp('1/2 "joe\'s"', ''); De même, dans une expression régulière définie à l’aide du constructeur new, tapez deux fois le caractère barre oblique inverse pour utiliser une métaséquence débutant par le caractère barre oblique inverse(\), telle que \d (qui correspond à n’importe quel chiffre). var pattern:RegExp = new RegExp("\\d+", ""); // matches one or more digits Vous devez taper deux fois le caractère barre oblique inverse, car le premier paramètre de la méthode constructeur RegExp() est une chaîne. Dans un littéral de chaîne, ce caractère doit être entré deux fois pour être interprété comme une barre oblique inverse unique. La section qui suit décrit la syntaxe servant à définir des modèles d’expression régulière. Pour plus d’informations, voir « Indicateurs et propriétés » à la page 89. Caractères, caractères de remplacement et métaséquences Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’expression régulière la plus simple est celle qui correspond à une séquence de caractères, comme dans l’exemple suivant : var pattern:RegExp = /hello/; Néanmoins, les caractères suivants, appelés caractères de remplacement, ont des significations spéciales dans des expressions régulières : ^ $ \ . * + ? ( ) [ ] { } | Par exemple, l’expression régulière suivante correspond à la lettre A suivie par zéro ou plusieurs occurrences de la lettre B (le caractère de remplacement astérisque indique cette répétition), suivie par la lettre C : /AB*C/ Pour inclure un caractère de remplacement sans sa signification spéciale dans un modèle d’expression régulière, vous devez utiliser le caractère d’échappement (\). Par exemple, l’expression régulière suivante correspond à la lettre A suivie par la lettre B, suivie par un astérisque, suivie par la lettre C : var pattern:RegExp = /AB\*C/; Une métaséquence, comme un caractère de remplacement, a une signification spéciale dans une expression régulière. Une métaséquence est constituée de plusieurs caractères. Les sections suivantes fournissent des détails sur l’utilisation des caractères de remplacement et des métaséquences. A propos des caractères de remplacement Le tableau suivant répertorie les caractères de remplacement que vous pouvez utiliser dans des expressions régulières : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 82 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Caractère de remplacement Description ^ (caret) Etablit une correspondance au début d’une chaîne. Lorsque l’indicateur m (multiline) est défini, le caret correspond au début d’une ligne également (voir « Indicateurs et propriétés » à la page 89). Lorsqu’il est utilisé au début d’une classe de caractère, le caret indique la négation et non le début d’une chaîne. Pour plus d’informations, voir « Classes de caractère » à la page 83. $(signe dollar) Etablit une correspondance à la fin d’une chaîne. Lorsque l’indicateur m (multiline) est défini, $ correspond à la position avant une nouvelle ligne (\n) également. Pour plus d’informations, voir « Indicateurs et propriétés » à la page 89. \ (caractère d’échappement) Echappe la signification spéciale du caractère de remplacement des caractères spéciaux. Vous pouvez également utiliser le caractère d’échappement si vous souhaitez utiliser une barre oblique dans un littéral d’expression régulière, comme dans /1\/2/ (pour correspondre au caractère 1, suivi par la barre oblique, suivi par le caractère 2). . (point) Correspond à un seul caractère. Un point correspond à un caractère de nouvelle ligne (\n) uniquement si l’indicateur s (dotall) est défini. Pour plus d’informations, voir « Indicateurs et propriétés » à la page 89. * (étoile) Correspond à l’élément précédent répété zéro ou plusieurs fois. Pour plus de détails, voir « Quantificateurs » à la page 85. + (plus) Correspond à l’élément précédent répété une ou plusieurs fois. Pour plus de détails, voir « Quantificateurs » à la page 85. ? (point d’interrogation) Correspond à l’élément précédent répété zéro ou une fois. Pour plus de détails, voir « Quantificateurs » à la page 85. ( et ) Définit des groupes dans l’expression régulière. Utilisez des groupes pour : • confiner le domaine du permutateur | : /(a|b|c)d/ • définir le domaine d’un quantificateur :/(walla.){1,2}/ • dans des backreferences. Par exemple, le \1 dans l’expression régulière suivante correspond à toute correspondance au premier groupe entre parenthèses du modèle : • /(\w*) est répété : \1/ Pour plus d’informations, voir « Groupes » à la page 87. [ et ] Spécifie une classe de caractère qui définit des correspondances possibles pour un seul caractère : /[aeiou]/ correspond à l’un des caractères spécifiés. Dans les classes de caractère, utilisez le trait d’union (-) pour désigner une plage de caractères : /[A-Z0-9]/ correspond aux lettres majuscules A à Z ou aux chiffres 0 à 9. Dans les classes de caractère, insérez un caractère d’échappement pour échapper les caractères ] et les caractères -: /[+\-]\d+/ correspond à + ou à - avant un ou plusieurs chiffres. Dans les classes de caractère, d’autres caractères (qui sont normalement des caractères de remplacement) sont considérés comme des caractères normaux (et non comme des caractères de remplacement), sans qu’une barre oblique inverse soit nécessaire : /[$]/£ correspond à $ou à £. Pour plus d’informations, voir « Classes de caractère » à la page 83. | (opérateur de transfert de données) Utilisé pour la permutation, pour correspondre à la partie de gauche ou à celle de droite : /abc|xyz/ correspond à abc ou à xyz. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 83 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 A propos des métaséquences Les métaséquences sont des séquences de caractères ayant une signification spéciale dans un modèle d’expression régulière. Le tableau suivant décrit ces métaséquences : Classes de caractère Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous utilisez des classes de caractère pour spécifier une liste de caractères devant correspondre à une position dans l’expression régulière. Vous définissez des classes de caractère avec des crochets ( [ et ] ). Par exemple, l’expression régulière suivante définit une classe de caractère qui remplace bag, beg, big, bog ou bug : /b[aeiou]g/ Métaséquence Description {n} {n,} et {n,n} Indique un quantificateur numérique ou une plage de quantificateurs pour l’élément précédent : /A{27}/ correspond au caractère A répété 27 fois. /A{3}/ correspond au caractère A répété 3 fois ou plus. /A{3,5}/ correspond au caractère A répété 3 à 5 fois. Pour plus de détails, voir « Quantificateurs » à la page 85. \b Etablit une correspondance à la position entre un caractère mot et un caractère non-mot. Si le premier ou le dernier caractère dans la chaîne est un caractère mot, correspond également au début ou à la fin de la chaîne. \B Etablit une correspondance à la position entre deux caractères mot. Correspond également à la position entre deux caractères non-mot. \d Correspond à une décimale. \D Correspond à tout caractère autre qu’un chiffre. \f Correspond à un caractère de changement de page. \n Correspond au caractère de nouvelle ligne. \r Correspond au caractère de retour de chariot. \s Correspond à tout caractère d’espace blanc (un espace, une tabulation, une nouvelle ligne ou un caractère de retour de chariot). \S Correspond à tout caractère autre qu’un caractère d’espace blanc. \t Correspond au caractère de tabulation. \unnnn Correspond au caractère Unicode avec le code de caractère spécifié par le nombre hexadécimal nnnn. Par exemple, \u263a est le caractère smiley. \v Correspond à un caractère d’avancement vertical. \w Correspond à un caractère mot (AZ–, az–, 0-9 ou _). \w ne correspond pas aux caractères qui ne sont pas anglais tels que é, ñ, ou ç. \W Correspond à tout caractère autre qu’un caractère mot. \\xnn Correspond au caractère avec la valeur ASCII spécifiée, comme défini par le nombre hexadécimal nn. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 84 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Séquences d’échappement dans des classes de caractère La plupart des caractères de remplacement et des métaséquences ayant normalement des significations spéciales dans une expression régulière n’ont pas ces mêmes significations dans une classe de caractère. Par exemple, dans une expression régulière, l’astérisque est utilisé pour la répétition, mais ce n’est pas le cas lorsqu’il apparaît dans une classe de caractère. La classe de caractère suivante correspond à l’astérisque de façon littérale, avec tout autre caractère répertorié : /[abc*123]/ Cependant, les trois caractères répertoriés dans le tableau suivant fonctionnent comme des caractères de remplacement, avec une signification spéciale, dans des classes de caractère : Pour que ces caractères soient reconnus comme caractères littéraux (dans la signification du caractère de remplacement spéciale), vous devez faire précéder le caractère du caractère d’échappement. Par exemple, l’expression régulière suivante inclut une classe de caractère qui correspond à l’un des quatre symboles ($, \, ] ou -) : /[$\\\]\-]/ Outre les caractères de remplacement qui conservent leurs significations spéciales, les métaséquences suivantes fonctionnent comme des métaséquences dans des classes de caractère : D’autres caractères de remplacement et métaséquences d’expression régulière sont considérés comme des caractères normaux dans une classe de caractère. Plages de caractères dans des classes de caractère Utilisez le trait d’union pour spécifier une plage de caractères telle que A-Z, a-z, ou 0-9. Ces caractères doivent constituer une plage valide dans le jeu de caractères. Par exemple, la classe de caractère suivante correspond à un caractère compris dans la plage a-z ou un chiffre : /[a-z0-9]/ Vous pouvez également utiliser le code de caractère ASCII \\xnn pour spécifier une plage par valeur ASCII. Par exemple, la classe de caractère suivante correspond à un caractère d’un jeu de caractères ASCII étendus (é et ê, par exemple) : \\x Caractère de remplacement Signification dans des classes de caractère ] Définit la fin de la classe de caractère. - Définit une plage de caractères (voir la section suivante, " Plages de caractères dans des classes de caractère ”). \ Définit des métaséquences et annule la signification spéciale des caractères de remplacement. Métaséquence Signification dans des classes de caractère \n Correspond à un caractère de nouvelle ligne. \r Correspond à un caractère de retour de chariot. \t Correspond à un caractère de tabulation. \unnnn Correspond au caractère avec la valeur de point de code Unicode spécifiée (comme défini par le nombre hexadécimal nnnn). \\xnn Correspond au caractère avec la valeur ASCII spécifiée (comme défini par le nombre hexadécimal nn). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 85 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Classes de caractère niées Lorsque vous utilisez un caret (^) au début d’une classe de caractère, il la nie (tout caractère non répertorié est considéré comme une correspondance). La classe de caractère suivante correspond à tout caractère sauf une lettre minuscule (az–) ou un chiffre : /[^a-z0-9]/ Vous devez taper le caret (^) au début d’une classe de caractère pour indiquer la négation. Autrement, vous ajoutez simplement le caret aux caractères dans la classe de caractère. Par exemple, la classe de caractère suivante correspond à un symbole (le caret, notamment) : /[!.,#+*%$&^]/ Quantificateurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous utilisez des quantificateurs pour spécifier des répétitions de caractères ou de séquences dans des modèles, comme suit : Vous pouvez appliquer un quantificateur à un seul caractère, à une classe de caractère ou à un groupe : • /a+/ correspond au caractère a répété une ou plusieurs fois. • /\d+/ correspond à un ou plusieurs chiffres. • /[abc]+/ correspond à une répétition d’un ou de plusieurs caractères, a, b, ou c. • /(very, )*/ correspond au mot very suivi par une virgule et un espace répété zéro ou plusieurs fois. Vous pouvez utiliser des quantificateurs dans des groupes de parenthèses auxquels sont appliqués des quantificateurs. Par exemple, le quantificateur suivant correspond à des chaînes du type word et word-word-word : /\w+(-\w+)*/ Par défaut, les expressions régulières effectuent un greedy matching. Tout sous-modèle dans l’expression régulière (.*, par exemple) tente de mettre en correspondance autant de caractères que possible dans la chaîne avant de passer à la partie suivante de l’expression régulière. Par exemple, considérez l’expression régulière et la chaîne suivantes : var pattern:RegExp = /

.*<\/p>/; str:String = "

Paragraph 1

Paragraph 2

"; L’expression régulière correspond à la chaîne entière :

Paragraph 1

Paragraph 2

Caractère de remplacement de quantificateur Description * (étoile) Correspond à l’élément précédent répété zéro ou plusieurs fois. + (plus) Correspond à l’élément précédent répété une ou plusieurs fois. ? (point d’interrogation) Correspond à l’élément précédent répété zéro ou une fois. {n} {n,} et {n,n} Indique un quantificateur numérique ou une plage de quantificateurs pour l’élément précédent : /A{27}/ correspond au caractère A répété 27 fois. /A{3}/ correspond au caractère A répété 3 fois ou plus. /A{3,5}/ correspond au caractère A répété 3 à 5 fois. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 86 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Supposez, néanmoins, que vous souhaitez établir une correspondance avec un seul groupe

...

. Vous pouvez procéder comme suit :

Paragraph 1

Ajoutez un point d’interrogation (?) après les quantificateurs pour qu’ils deviennent des quantificateurs paresseux. Par exemple, l’expression régulière suivante, qui utilise le quantificateur paresseux *? , correspond à

suivi du nombre minimum de caractères possible (paresseux), suivi de

: /

.*?<\/p>/ Lisez attentivement les points suivants concernant les quantificateurs : • Les quantificateurs {0} et {0,0} n’excluent pas un élément d’une correspondance. • Ne combinez pas plusieurs quantificateurs, comme dans /abc+*/. • Le caractère point (.) ne divise pas les lignes en deux à moins de définir l’indicateur s (dotall), même s’il est suivi d’un quantificateur *. Considérons par exemple le code qui suit : var str:String = "

Test\n"; str += "Multiline

"; var re:RegExp = /

.*<\/p>/; trace(str.match(re)); // null; re = /

.*<\/p>/s; trace(str.match(re)); // output:

Test // Multiline

Pour plus d’informations, voir « Indicateurs et propriétés » à la page 89. Permutation Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Utilisez le caractère | (barre) dans une expression régulière pour que son moteur tienne compte des autres possibilités pour une correspondance. Par exemple, l’expression régulière suivante correspond à l’un des mots cat, dog, pig, rat : var pattern:RegExp = /cat|dog|pig|rat/; Vous pouvez utiliser des parenthèses pour définir des groupes et limiter le domaine du permutateur |. L’expression régulière suivante correspond à cat suivi de nap ou nip : var pattern:RegExp = /cat(nap|nip)/; Pour plus d’informations, voir « Groupes » à la page 87. Les deux expressions régulières suivantes (l’une utilisant le permutateur |, l’autre une classe de caractère (définie avec [ et ] )) sont équivalentes : /1|3|5|7|9/ /[13579]/ Pour plus d’informations, voir « Classes de caractère » à la page 83. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 87 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Groupes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez spécifier un groupe dans une expression régulière en utilisant des parenthèses, comme suit : /class-(\d*)/ Un groupe est une sous-section d’un modèle. Vous pouvez utiliser des groupes pour effectuer les opérations suivantes : • Appliquer un quantificateur à plusieurs caractères • Délimiter des sous-modèles à appliquer avec la permutation (à l’aide du caractère |) • Capturer des correspondances de sous-chaîne (par exemple, en utilisant \1 dans une expression régulière pour établir une correspondance avec un groupe mis en correspondance précédemment, ou en utilisant $1 de la même façon dans la méthode replace() de la classe String) Les sections suivantes fournissent des détails sur ces utilisations de groupes. Utilisation de groupes avec des quantificateurs Si vous n’utilisez pas de groupe, un quantificateur s’applique au caractère ou à la classe de caractère qui le précède, comme indiqué ci-dessous : var pattern:RegExp = /ab*/ ; // matches the character a followed by // zero or more occurrences of the character b pattern = /a\d+/; // matches the character a followed by // one or more digits pattern = /a[123]{1,3}/; // matches the character a followed by // one to three occurrences of either 1, 2, or 3 Néanmoins, vous pouvez utiliser un groupe pour appliquer un quantificateur à plusieurs caractères ou classes de caractère : var pattern:RegExp = /(ab)*/; // matches zero or more occurrences of the character a // followed by the character b, such as ababab pattern = /(a\d)+/; // matches one or more occurrences of the character a followed by // a digit, such as a1a5a8a3 pattern = /(spam ){1,3}/; // matches 1 to 3 occurrences of the word spam followed by a space Pour plus d’informations sur les quantificateurs, voir « Quantificateurs » à la page 85. Utilisation de groupes avec le permutateur (|) Vous pouvez utiliser des groupes pour définir le groupe de caractères auquel vous souhaitez appliquer un permutateur (|), comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 88 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 var pattern:RegExp = /cat|dog/; // matches cat or dog pattern = /ca(t|d)og/; // matches catog or cadog Utilisation de groupes pour capturer des correspondances de sous-chaîne Lorsque vous définissez un groupe entre parenthèses standard dans un modèle, vous pouvez ensuite vous y référer dans l’expression régulière. Il s’agit d’une backreference. Ces types de groupes sont appelés groupes capturés. Par exemple, dans l’expression régulière suivante, la séquence \1 correspond à toute sous-chaîne mise en correspondance avec le groupe entre parenthèses capturé : var pattern:RegExp = /(\d+)-by-\1/; // matches the following: 48-by-48 Vous pouvez spécifier jusqu’à 99 backreferences dans une expression régulière en tapant \1,\2,...,\99. De même, dans la méthode replace() de la classe String, vous pouvez utiliser $1–$99 pour insérer des correspondances de chaîne de groupe capturé dans la chaîne de remplacement : var pattern:RegExp = /Hi, (\w+)\./; var str:String = "Hi, Bob."; trace(str.replace(pattern, "$1, hello.")); // output: Bob, hello. Si vous utilisez des groupes capturés, la méthode exec() de la classe RegExp et la méthode match() de la classe String renvoient des sous-chaînes qui correspondent aux groupes capturés : var pattern:RegExp = /(\w+)@(\w+).(\w+)/; var str:String = "bob@example.com"; trace(pattern.exec(str)); // bob@example.com,bob,example,com Utilisation de groupes non capturés et de groupes d’anticipation Un groupe non capturé est utilisé pour le regroupement uniquement ; il n’est pas collecté et il ne correspond pas à des backreferences numérotées. Utilisez (?: et ) pour définir des groupes non capturés, comme suit : var pattern = /(?:com|org|net); Par exemple, notez la différence entre mettre (com|org) dans un groupe capturé et dans un groupe non capturé (la méthode exec() répertorie les groupes capturés après la correspondance complète) : var pattern:RegExp = /(\w+)@(\w+).(com|org)/; var str:String = "bob@example.com"; trace(pattern.exec(str)); // bob@example.com,bob,example,com //noncapturing: var pattern:RegExp = /(\w+)@(\w+).(?:com|org)/; var str:String = "bob@example.com"; trace(pattern.exec(str)); // bob@example.com,bob,example Un type spécial de groupe non capturé est le groupe d’animation dont il existe deux types : le groupe d’animation positif et le groupe d’animation négatif. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 89 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Utilisez (?= et ) pour définir un groupe d’anticipation positif, qui spécifie que le sous-modèle dans le groupe doit établir une correspondance à la position. Néanmoins, la portion de la chaîne qui correspond au groupe d’anticipation positif peut correspondre aux modèles restants dans l’expression régulière. Par exemple, étant donné que (?=e) est un groupe d’anticipation positif dans le code suivant, le caractère e auquel il correspond peut être mis en correspondance par une partie suivante de l’expression régulière (dans ce cas, le groupe capturé, \w*) : var pattern:RegExp = /sh(?=e)(\w*)/i; var str:String = "Shelly sells seashells by the seashore"; trace(pattern.exec(str)); // Shelly,elly Utilisez (?= et ) pour définir un groupe d’anticipation négatif, qui indique que le sous-modèle dans le groupe ne doit pas établir une correspondance à la position. Exemple : var pattern:RegExp = /sh(?!e)(\w*)/i; var str:String = "She sells seashells by the seashore"; trace(pattern.exec(str)); // shore,ore Utilisation de groupes nommés Un groupe nommé est un type de groupe dans une expression régulière ayant un identificateur nommé. Utilisez (?P et ) pour définir le groupe nommé. Par exemple, l’expression régulière suivante inclut un groupe nommé avec l’identificateur nommé digits : var pattern = /[a-z]+(?P\d+)[a-z]+/; Lorsque vous utilisez la méthode exec(), un groupe nommé de correspondance est ajouté comme propriété du tableau result : var myPattern:RegExp = /([a-z]+)(?P\d+)[a-z]+/; var str:String = "a123bcd"; var result:Array = myPattern.exec(str); trace(result.digits); // 123 Voici un autre exemple, qui utilise deux groupes nommés, avec les identificateurs name et dom : var emailPattern:RegExp = /(?P(\w|[_.\-])+)@(?P((\w|-)+))+\.\w{2,4}+/; var address:String = "bob@example.com"; var result:Array = emailPattern.exec(address); trace(result.name); // bob trace(result.dom); // example Remarque : les groupes nommés ne font pas partie de la spécification du langage ECMAScript. Ils représentent une fonction ajoutée dans ActionScript 3.0. Indicateurs et propriétés Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le tableau suivant répertorie les cinq indicateurs que vous pouvez définir pour des expressions régulières. Vous pouvez accéder à chaque indicateur en tant que propriété de l’objet d’expression régulière. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 90 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Ces propriétés sont en lecture seule. Vous pouvez définir les indicateurs (g, i, m, s, x) lorsque vous définissez une variable d’expression régulière, comme suit : var re:RegExp = /abc/gimsx; Cependant, vous ne pouvez pas définir directement les propriétés nommées. Par exemple, le code suivant génère une erreur : var re:RegExp = /abc/; re.global = true; // This generates an error. Par défaut, à moins de les spécifier dans la déclaration d’expression régulière, les indicateurs ne sont pas définis, et les propriétés correspondantes sont également définies sur false. De plus, il existe deux autres propriétés d’une expression régulière : • La propriété lastIndex spécifie la position d’index dans la chaîne à utiliser pour l’appel suivant à la méthode exec() ou test() d’une expression régulière. • La propriété source spécifie la chaîne qui définit la portion de modèle de l’expression régulière. L’indicateur g (global) Lorsque l’indicateur g (global) n’est pas inclus, une expression régulière n’a pas plus d’une correspondance. Par exemple, avec l’indicateur g exclu de l’expression régulière, la méthode String.match() renvoie une sous-chaîne de correspondance uniquement : var str:String = "she sells seashells by the seashore."; var pattern:RegExp = /sh\w*/; trace(str.match(pattern)) // output: she Lorsque l’indicateur g est défini, la méthode Sting.match() renvoie plusieurs correspondances, comme suit : var str:String = "she sells seashells by the seashore."; var pattern:RegExp = /sh\w*/g; // The same pattern, but this time the g flag IS set. trace(str.match(pattern)); // output: she,shells,shore L’indicateur i (ignoreCase) Par défaut, les correspondances d’expression régulière sont sensibles à la casse. Lorsque vous définissez l’indicateur i (ignoreCase), le respect de la casse est ignoré. Par exemple, la lettre minuscule s dans l’expression régulière ne correspond pas à la lettre majuscule S, le premier caractère de la chaîne : var str:String = "She sells seashells by the seashore."; trace(str.search(/sh/)); // output: 13 -- Not the first character Indicateur Propriété Description g global A plusieurs correspondances. i ignoreCase Correspondance sensible à la casse. S’applique aux caractères A—Z et a—z mais pas à des caractères étendus tels que É et é. m multiline Lorsque cet indicateur est défini, $ et ^ peuvent correspondre au début d’une ligne et à la fin d’une ligne, respectivement. s dotall Lorsque cet indicateur est défini, . (point) peut correspondre au caractère de nouvelle ligne (\n). x extended Autorise les expressions régulières étendues. Vous pouvez tapez des espaces dans l’expression régulière. Ils sont ignorés dans le cadre du modèle. Ceci vous permet de taper un code d’expression régulière de façon plus lisible. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 91 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Lorsque l’indicateur i est défini, cependant, l’expression régulière correspond à la lettre majuscule S : var str:String = "She sells seashells by the seashore."; trace(str.search(/sh/i)); // output: 0 L’indicateur i ignore le respect de la casse uniquement pour les caractères A–Z et a–z, mais par pour les caractères étendus tels que É et é . L’indicateur m (multiline) Si l’indicateur m (multiline) n’est pas défini, le ^ correspond au début de la chaîne et le $ à sa fin. Si l’indicateur m est défini, ces caractères correspondent au début d’une ligne et à la fin d’une ligne, respectivement. Considérez la chaîne suivante, qui inclut un caractère de nouvelle ligne : var str:String = "Test\n"; str += "Multiline"; trace(str.match(/^\w*/g)); // Match a word at the beginning of the string. Même si l’indicateur g (global) est défini dans l’expression régulière, la méthode match() correspond à une seule sous-chaîne, car il n’existe qu’une seule correspondance pour le ^ (le début de la chaîne). Le résultat est le suivant : Test Voici le même code avec l’indicateur m défini : var str:String = "Test\n"; str += "Multiline"; trace(str.match(/^\w*/gm)); // Match a word at the beginning of lines. Cette fois, le résultat inclut les mots au début des deux lignes : Test,Multiline Seul le caractère \n signale la fin d’une ligne. Ce n’est pas le cas des caractères suivants : • Retour de chariot (\r) • Séparateur de ligne Unicode (\u2028) • Séparateur de paragraphe Unicode (\u2028) L’indicateur s (dotall) Si l’indicateur s (dotall ou “dot all”) n’est pas défini, un point (.) dans un modèle d’expression régulière ne correspond pas à un caractère de nouvelle ligne (\n). Par conséquent, il n’existe aucune correspondance pour l’exemple suivant : var str:String = "

Test\n"; str += "Multiline

"; var re:RegExp = /

.*?<\/p>/; trace(str.match(re)); Néanmoins, si l’indicateur s est défini, le point correspond au caractère de nouvelle ligne : var str:String = "

Test\n"; str += "Multiline

"; var re:RegExp = /

.*?<\/p>/s; trace(str.match(re)); Dans ce cas, la correspondance est la sous-chaîne entière dans les balises

, y compris le caractère de nouvelle ligne :

Test Multiline

GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 92 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 L’indicateur x (extended) Les expressions régulières peuvent être difficiles à lire, notamment lorsqu’elles comprennent de nombreux métasymboles et métaséquences. Exemple : /|(\s*[^>]*>)).*?<\/p>/gi Lorsque vous utilisez l’indicateur x (extended) dans une expression régulière, les espaces vides que vous tapez dans le modèle sont ignorés. Par exemple, l’expression régulière suivante est identique à l’exemple précédent : /

| (\s* [^>]* >)) .*? <\/p> /gix Si l’indicateur x est défini et que vous souhaitez établir une correspondance avec un espace vide, faites précéder l’espace vide d’une barre oblique. Par exemple, les deux expressions régulières suivantes sont équivalentes : /foo bar/ /foo \ bar/x La propriété lastIndex La propriété lastIndex spécifie la position d’index dans la chaîne à laquelle la recherche suivante doit démarrer. Cette propriété affecte les méthodes exec() et test() appelées sur une expression régulière dont l’indicateur g est défini sur true. Considérons par exemple le code qui suit : var pattern:RegExp = /p\w*/gi; var str:String = "Pedro Piper picked a peck of pickled peppers."; trace(pattern.lastIndex); var result:Object = pattern.exec(str); while (result != null) { trace(pattern.lastIndex); result = pattern.exec(str); } La propriété lastIndex est défini sur 0 par défaut (pour commencer les recherches au début de la chaîne). Après chaque correspondance, elle est définie sur la position d’index suivant la correspondance. Par conséquent, le résultat pour le code précédent est le suivant : 0 5 11 18 25 36 44 Si l’indicateur global est défini sur false, les méthodes exec() et test() n’utilisent pas ni ne définissent la propriété lastIndex. Les méthodes match(), replace() et search() de la classe String lancent toutes les recherches du début de la chaîne, indépendamment du réglage de la propriété lastIndex de l’expression régulière utilisée dans l’appel à la méthode (néanmoins, la méthode match() définit lastIndex sur 0). Vous pouvez définir la propriété lastIndex de sorte à ajuster la position de début dans la chaîne pour la mise en correspondance des expressions régulières. La propriété source La propriété source spécifie la chaîne qui définit la portion de modèle d’une expression régulière. Exemple : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 93 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 var pattern:RegExp = /foo/gi; trace(pattern.source); // foo Méthodes d’utilisation d’expressions régulières avec des chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe RegExp comprend deux méthodes : exec() et test(). Outre les méthodes exec() et test() de la classe RegExp, la classe String comprend les méthodes suivantes qui vous permettent d’établir une correspondance avec des expressions régulières dans des chaînes : match(), replace(), search() et splice(). La méthode test() Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode test() de la classe RegExp vérifie si la chaîne fournie contient une correspondance pour l’expression régulière, comme l’indique l’exemple suivant : var pattern:RegExp = /Class-\w/; var str = "Class-A"; trace(pattern.test(str)); // output: true La méthode exec() Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode exec() de la classe RegExp vérifie si la chaîne fournie contient une correspondance pour l’expression régulière et renvoie un tableau avec les éléments suivants : • La sous-chaîne correspondante • Les correspondances de sous-chaîne pour les groupes entre parenthèses dans l’expression régulière Le tableau inclut également une propriété index qui indique la position d’index du début de la correspondance de sous-chaîne. Considérons par exemple le code qui suit : var pattern:RegExp = /\d{3}\-\d{3}-\d{4}/; //U.S phone number var str:String = "phone: 415-555-1212"; var result:Array = pattern.exec(str); trace(result.index, " - ", result); // 7-415-555-1212 Utilisez la méthode exec() plusieurs fois pour établir une correspondance avec plusieurs sous-chaînes lorsque l’indicateur g (global) est défini pour l’expression régulière : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 94 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 var pattern:RegExp = /\w*sh\w*/gi; var str:String = "She sells seashells by the seashore"; var result:Array = pattern.exec(str); while (result != null) { trace(result.index, "\t", pattern.lastIndex, "\t", result); result = pattern.exec(str); } //output: // 0 3 She // 10 19 seashells // 27 35 seashore Méthodes de chaîne utilisant des paramètres RegExp Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les méthodes suivantes de la classe String prennent des expressions régulières comme paramètres : match(), replace(), search() et split(). Pour plus d’informations sur ces méthodes, voir « Recherche de modèles dans des chaînes et remplacement de sous-chaînes » à la page 17. Exemple d’expression régulière : analyseur Wiki Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Cet exemple simple de conversion de texte Wiki illustre des utilisations d’expressions régulières : • Conversion de lignes de texte qui mettent en correspondance un modèle Wiki source et les chaînes de sortie HTML appropriées. • Utilisation d’une expression régulière pour convertir des modèles URL en balises de lien hypertexte HTML • Utilisation d’une expression régulière pour convertir les chaînes dollar américain ("$9.95", par exemple) en chaînes euro ("8.24 €", par exemple) Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers de l’application WikiEditor se trouvent dans le dossier Samples/WikiEditor. L’application se compose des fichiers suivants : Fichier Description WikiEditor.mxml ou WikiEditor.fla Fichier d’application principal dans Flash (FLA) ou Flex (MXML). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 95 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Définition de la classe WikiParser Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe WikiParser inclut des méthodes qui convertissent le texte d’entrée Wiki en sortie HTML équivalente. Il ne s’agit pas d’une application de conversion Wiki très puissante, mais elle illustre des utilisations d’expressions régulières pour la mise en correspondance de modèle et la conversion de chaîne. La fonction constructeur et la méthode setWikiData() initialisent un exemple de chaîne de texte d’entrée Wiki, comme suit : public function WikiParser() { wikiData = setWikiData(); } Lorsque l’utilisateur clique sur le bouton de test dans l’application exemple, cette dernière appelle la méthode parseWikiString() de l’objet WikiParser. Cette méthode appelle plusieurs autres méthodes, qui assemblent à leur tour la chaîne HTML résultante. public function parseWikiString(wikiString:String):String { var result:String = parseBold(wikiString); result = parseItalic(result); result = linesToParagraphs(result); result = parseBullets(result); return result; } Chaque méthode appelée—parseBold(), parseItalic(), linesToParagraphs(), et parseBullets()—utilise la méthode replace() de la chaîne pour remplacer les modèles de correspondance, définis par une expression régulière, de façon à transformer le texte Wiki en texte formaté HTML. Conversion des modèles de texte en gras et en italique La méthode parseBold() recherche un modèle de texte Wiki en gras ('''foo''', par exemple) et le transforme en son équivalent HTML (foo, par exemple), comme suit : private function parseBold(input:String):String { var pattern:RegExp = /'''(.*?)'''/g; return input.replace(pattern, "$1"); } com/example/programmingas3/regExpExamples/WikiParser.as Une classe qui comprend des méthodes utilisant des expressions régulières pour convertir des modèles de texte d’entrée Wiki en sortie HTML équivalente. com/example/programmingas3/regExpExamples/URLParser.as Une classe qui comprend des méthodes utilisant des expressions régulières pour convertir des chaînes URL en balises de lien hypertexte HTML . com/example/programmingas3/regExpExamples/CurrencyConverter.as Une classe qui comprend des méthodes utilisant des expressions régulières pour convertir des chaînes dollar américain en chaînes euro. Fichier Description GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 96 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Notez que la portion (.?*) de l’expression régulière correspond à des caractères (*) entre les deux modèles de définition '''. Le quantificateur ? rend la correspondance nongreedy, de façon à ce que pour une chaîne telle que '''aaa''' bbb '''ccc''', la première chaîne mise en correspondance soit '''aaa''' et non la chaîne entière (qui commence et se termine par le modèle '''). Les parenthèses dans l’expression régulière définissent un groupe capturé, et la méthode replace() se réfère à ce groupe en utilisant le code $1 dans la chaîne de remplacement. L’indicateur g (global) dans l’expression régulière vérifie que la méthode replace() remplace toutes les correspondances dans la chaîne (pas simplement la première). La méthode parseItalic() fonctionne comme la méthode parseBold(), sauf qu’elle recherche deux apostrophes ('') comme séparateur pour le texte en italique (au lieu de trois) : private function parseItalic(input:String):String { var pattern:RegExp = /''(.*?)''/g; return input.replace(pattern, "$1"); } Conversion de modèles de puce Comme dans l’exemple suivant, la méthode parseBullet() recherche le modèle de puce Wiki (* foo, par exemple) et le transforme en son équivalent HTML (

  • foo
  • , par exemple) : private function parseBullets(input:String):String { var pattern:RegExp = /^\*(.*)/gm; return input.replace(pattern, "
  • $1
  • "); } Le symbole ^ au début de l’expression régulière correspond au début d’une ligne. L’indicateur m (multiline) dans l’expression régulière fait en sorte que cette dernière compare le symbole ^ au début d’une ligne, et non simplement au début de la chaîne. Le modèle \* correspond à un astérisque (la barre oblique est utilisée pour signaler un astérisque littéral au lieu d’un quantificateur *). Les parenthèses dans l’expression régulière définissent un groupe capturé, et la méthode replace() se réfère à ce groupe en utilisant le code $1 dans la chaîne de remplacement. L’indicateur g (global) dans l’expression régulière vérifie que la méthode replace() remplace toutes les correspondances dans la chaîne (pas simplement la première). Conversion de modèles Wiki de paragraphe La méthode linesToParagraphs() convertit chaque ligne dans la chaîne Wiki d’entrée en une balise de paragraphe HTML

    . Ces lignes dans la méthode extraient des lignes vides de la chaîne d’entrée Wiki : var pattern:RegExp = /^$/gm; var result:String = input.replace(pattern, ""); Les symboles ^ et $ dans l’expression régulière correspondent au début et à la fin d’une ligne. L’indicateur m (multiline) dans l’expression régulière fait en sorte que cette dernière compare le symbole ^ au début d’une ligne, et non simplement au début de la chaîne. La méthode replace() remplace toutes les chaînes de correspondance (lignes vides) par une chaîne vide (""). L’indicateur g (global) dans l’expression régulière vérifie que la méthode replace() remplace toutes les correspondances dans la chaîne (pas simplement la première). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 97 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 Conversion d’URL en balises HTML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque l’utilisateur clique sur le bouton de test dans l’exemple d’application et qu’il a coché la case urlToATag, l’application appelle la méthode statique URLParser.urlToATag() pour convertir les chaînes URL de la chaîne Wiki d’entrée en balises HTML . var protocol:String = "((?:http|ftp)://)"; var urlPart:String = "([a-z0-9_-]+\.[a-z0-9_-]+)"; var optionalUrlPart:String = "(\.[a-z0-9_-]*)"; var urlPattern:RegExp = new RegExp(protocol + urlPart + optionalUrlPart, "ig"); var result:String = input.replace(urlPattern, "$1$2$3"); La fonction constructeur RegExp() sert à assembler une expression régulière (urlPattern) à partir de plusieurs parties constituantes. Ces parties constituantes sont représentées par chaque chaîne définissant une partie du modèle de l’expression régulière. La première partie du modèle de l’expression régulière, définie par la chaîne protocol, définit un protocole URL : http:// ou ftp://. Les parenthèses définissent un groupe non capturé, indiqué par le symbole ?. Ceci signifie que les parenthèses servent simplement à définir un groupe pour le modèle de permutation | ; le groupe ne correspondra pas à des codes de backreference ($1, $2, $3) dans la chaîne de remplacement de la méthode replace(). Les autres parties constituantes de l’expression régulière utilisent chacune des groupes capturés (indiqués par des parenthèses dans le modèle) qui sont ensuite utilisés dans les codes de backreference ($1, $2, $3) dans la chaîne de remplacement de la méthode replace(). La partie du modèle définie par la chaîne urlPart correspond au moins à l’un des caractères suivants : a-z, 0-9, _ ou -. La quantificateur + indique qu’au moins un caractère a une correspondance. Le \. indique un point obligatoire (.). Et le reste correspond à une autre chaîne d’au moins un de ces caractères : a-z, 0-9, _ ou -. La partie du modèle définie par la chaîne optionalUrlPart correspond à zéro ou plus des caractères suivants : un point (.) suivi par n’importe quel nombre de caractères alphanumériques (y compris _ et -). Le quantificateur * indique que zéro ou plus de caractères ont une correspondance. L’appel à la méthode replace() utilise l’expression régulière et assemble la chaîne HTML de remplacement, à l’aide de backreferences. La méthode urlToATag() appelle ensuite la méthode emailToATag(), qui utilise des techniques semblables pour remplacer des modèles de courrier électronique par des chaînes de lien hypertexte HTML . Les expressions régulières utilisées pour correspondre à des URL HTTP, FTP et de courrier électronique dans le fichier sont assez simples car elles sont données à titre d’exemple. Elles sont beaucoup plus compliquées si l’on souhaite établir une correspondance plus correcte. Conversion des chaînes dollar américain en chaînes euro Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque l’utilisateur clique sur le bouton de test dans l’exemple d’application et qu’il a coché la case dollarToEuro , l’application appelle la méthode statique CurrencyConverter.usdToEuro() pour convertir des chaînes dollar américain ("$9.95", par exemple) en chaînes euro ("8.24€", par exemple), comme suit : var usdPrice:RegExp = /\$([\d,]+.\d+)+/g; return input.replace(usdPrice, usdStrToEuroStr); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 98 Utilisation d’expressions régulières Dernière mise à jour le 27/4/2013 La première ligne définit un modèle simple pour établir une correspondance avec des chaînes dollar américain. Le caractère $ est précédé du caractère d’échappement (\). La méthode replace() utilise l’expression régulière pour établir une correspondance avec le modèle et appelle la fonction usdStrToEuroStr() pour déterminer la chaîne de remplacement (une valeur en euros). Lorsqu’un nom de fonction est utilisé comme deuxième paramètre de la méthode replace(), les éléments suivants sont transmis comme paramètres à la fonction appelée : • La partie correspondante de la chaîne. • Tout groupe entre parenthèses capturé correspondant. Le nombre d’arguments transmis de cette façon varie selon le nombre de correspondances de groupes entre parenthèses capturées. Pour déterminer le nombre de correspondances de groupes entre parenthèses capturés, vérifiez arguments.length - 3 dans le code de la fonction. • La position d’index dans la chaîne où débute la correspondance. • La chaîne complète. La méthode usdStrToEuroStr() convertit les modèles de chaîne dollar américain en chaînes euro, comme suit : private function usdToEuro(...args):String { var usd:String = args[1]; usd = usd.replace(",", ""); var exchangeRate:Number = 0.828017; var euro:Number = Number(usd) * exchangeRate; trace(usd, Number(usd), euro); const euroSymbol:String = String.fromCharCode(8364); // € return euro.toFixed(2) + " " + euroSymbol; } args[1] représente le groupe entre parenthèses capturé mis en correspondance par l’expression régulière usdPrice. Il s’agit de la portion numérique de la chaîne dollar américain, c’est-à-dire la quantité en dollar, sans le signe $. La méthode applique une conversion de taux de change et renvoie la chaîne résultante (avec un symbole de fin de ligne € au lieu du symbole $ placé à gauche). 99 Dernière mise à jour le 27/4/2013 Chapitre 6 : Utilisation de XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 3.0 inclut un groupe de classes basé sur la spécification ECMAScript pour XML (E4X) (ECMA-357 version 2). Ces classes comprennent une fonctionnalité puissante et facile à utiliser permettant de travailler avec des données XML. A l’aide d’E4X, vous pouvez développer un code avec des données XML plus rapidement qu’avec les techniques de programmation précédentes. En outre, le code que vous produisez est plus facile à lire. Voir aussi Classe XML Spécification ECMA-357 Principes de base de XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures XML est un moyen standard de représenter des informations structurées afin de permettre aux ordinateurs de les utiliser facilement et aux utilisateurs de les écrire et de les comprendre. XML est l’abréviation de eXtensible Markup Language. La norme XML est disponible à l’adresse www.w3.org/XML/. XML offre une façon pratique et standard de classer des données, afin de faciliter leur lecture, leur accès et leur manipulation. XML utilise une arborescence et une structure de balises identiques à celle du code HTML. Voici un exemple simple de données XML : What you know? Steve and the flubberblubs 1989 2006-10-17-08:31 Les données XML peuvent également être plus complexes, avec des balises imbriquées dans d’autres balises ainsi que des attributs et d’autres composants structurels. Voici un exemple plus complexe de données XML : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 100 Utilisation de XML Dernière mise à jour le 27/4/2013 Questions, unanswered Steve and the flubberblubs 1989 What do you know? Steve and the flubberblubs 2006-10-17-08:31 Who do you know? Steve and the flubberblubs 2006-10-17-08:35 When do you know? Steve and the flubberblubs 2006-10-17-08:39 Do you know? Steve and the flubberblubs 2006-10-17-08:44 Vous remarquerez que ce document XML contient d’autres structures XML complètes (les balises song avec leurs enfants, par exemple). Il démontre également d’autres structures XML telles que des attributs (tracknumber et length dans les balises song), et des balises qui contiennent d’autres balises au lieu de données (la balise tracks, par exemple). Prise en main de XML Si vous avez peu ou pas d’expérience avec XML, voici une brève description des aspects les plus courants des données XML. Les données XML sont écrites sous forme de texte brut, avec une syntaxe spécifique permettant d’organiser les informations en un format structuré. Généralement, un seul jeu de données XML est appelé un document XML. Dans le format XML, les données sont organisées en éléments (qui peuvent être des éléments de données uniques ou des conteneurs pour d’autres éléments) à l’aide d’une structure hiérarchique. Chaque document XML possède un élément comme niveau supérieur ou élément principal. Cet élément racine peut contenir une seule information, même s’il est plus probable qu’il contienne d’autres éléments qui, à leur tour, contiennent d’autres éléments, et ainsi de suite. Par exemple, ce document XML contient les informations relatives à un album musical : What do you know? Steve and the flubberblubs Happy 2006-10-17-08:31 Chaque élément se distingue par un ensemble de balises—le nom de l’élément placé entre chevrons (signes inférieur à et supérieur à). La balise de début, indiquant le début de l’élément, porte le nom de l’élément : La balise de fin, qui marque la fin de l’élément, a une barre oblique avant le nom de l’élément : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 101 Utilisation de XML Dernière mise à jour le 27/4/2013 Si un élément est vide, il peut être écrit comme élément vide (parfois appelé élément de fin automatique). Dans XML, cet élément : est identique à cet élément : Outre le contenu de l’élément placé entre les balises de début et de fin, un élément peut comporter d’autres valeurs, appelées attributs, définies dans la balise de début de l’élément. Par exemple, cet élément XML définit un seul attribut appelé length, avec la valeur "4:19" : Chaque élément XML possède un contenu qui est soit une valeur, soit un ou plusieurs éléments XML, ou rien du tout (pour un élément vide). En savoir plus sur XML Pour en savoir plus sur l’utilisation de XML, un grand nombre de livres et de ressources sont disponibles, ainsi que les sites Web suivants : • Didacticiel XML W3Schools : http://w3schools.com/xml/ • Didacticiels XMLpitstop, listes de discussions, etc. : http://xmlpitstop.com/ Classes ActionScript pour utiliser XML ActionScript 3.0 inclut plusieurs classes permettant d’utiliser des informations structurées XML. Les deux classes principales sont les suivantes : • XML : représente un seul élément XML, qui peut être un document XML avec plusieurs enfants ou un élément à une seule valeur dans un document. • XMLList : représente un ensemble d’éléments XML. Un objet XMLList est utilisé lorsque plusieurs éléments XML sont des frères (au même niveau, et contenus par le même parent, dans la hiérarchie du document XML). Par exemple, une occurrence de XMLList serait le moyen le plus facile d’utiliser cet ensemble d’éléments XML (probablement contenus dans un document XML): Fred Wilson James Schmidt Susan Harriet Thurndon Pour des utilisations plus avancées impliquant des espaces de noms XML, ActionScript inclut également les classes Namespace et QName. Pour plus d’informations, voir « Utilisation des espaces de noms XML » à la page 114. Outre les classes intégrées permettant d’utiliser XML, ActionScript 3.0 comprend également plusieurs opérateurs offrant des fonctionnalités spécifiques pour accéder et manipuler des données XML. Cette approche d’utilisation de XML au moyen de ces classes et de ces opérateurs est appelée ECMAScript pour XML (E4X), comme défini par la spécification ECMA-357 version 2. Concepts importants et terminologie La liste de référence suivante contient des termes importants utilisés dans le cadre de la programmation de routines de gestion des éléments XML : Elément Entité unique dans un document XML correspondant au contenu compris entre une balise de début et une balise de fin (balises comprises). Les éléments XML peuvent contenir des données de texte ou d’autres éléments, ou bien être vides. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 102 Utilisation de XML Dernière mise à jour le 27/4/2013 Elément vide Elément XML qui ne contient aucun élément enfant. Les éléments vides sont souvent écrits en tant que balises de fin automatique (, par exemple). Document Structure XML unique. Un document XML peut contenir n’importe quel nombre d’éléments (ou peut être constitué d’un seul élément vide) ; cependant, un document XML doit avoir un seul élément de niveau supérieur qui contient tous les autres éléments dans le document. Noeud Autre nom d’un élément XML. Attribut Valeur nommée associée à un élément qui est écrite dans la balise de début de l’élément au format attributename="valeur", plutôt que d’être écrite comme élément enfant séparé imbriqué dans l’élément. Approche E4X concernant le traitement XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La spécification ECMAScript pour XML définit un ensemble de classes et de fonctionnalités permettant d’utiliser des données XML. Cet ensemble de classes et de fonctionnalités est connu sous le nom de E4X. ActionScript 3.0 intègre les classes E4X suivantes : XML, XMLList, QName et Namespace. Les méthodes, propriétés et opérateurs des classes E4X sont conçus avec les objectifs suivants : • Simplicité : lorsque cela est possible, E4X facilite l’écriture et la compréhension du code à utiliser avec des données XML. • Cohérence : les méthodes et le raisonnement E4X sont cohérents avec eux-mêmes et avec d’autres parties d’ActionScript. • Connaissance : vous manipulez des données XML avec des opérateurs bien connus tels que l’opérateur point (.). Remarque : ActionScript 2.0 intègre une autre classe XML. Dans ActionScript 3.0, cette classe a été renommée XMLDocument, pour éviter tout conflit de nom avec la classe XML d’ActionScript 3.0 qui fait partie d’E4X. Dans ActionScript 3.0, les classes héritées (XMLDocument, XMLNode, XMLParser et XMLTag) sont comprises dans le package flash.xml, pour la prise en charge du contenu hérité principalement. Les nouvelles classes E4X sont des classes de base. Vous ne devez pas importer de package pour les utiliser. Pour plus d’informations sur les classes XML d’ActionScript 2.0 existantes, voir le package flash.xml dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Voici un exemple de manipulation de données avec E4X : var myXML:XML = burger 3.95 fries 1.45 Votre application charge souvent des données XML depuis une source externe telle qu’un service Web ou un flux RSS. Toutefois, par souci de clarté, les exemples de code ci-après affectent les données XML en tant que littéraux. Comme l’indique le code suivant, E4X inclut des opérateurs intuitifs tels que les opérateurs point (.) et identifiant d’attribut (@) pour accéder aux propriétés et aux attributs dans l’XML : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 103 Utilisation de XML Dernière mise à jour le 27/4/2013 trace(myXML.item[0].menuName); // Output: burger trace(myXML.item.(@id==2).menuName); // Output: fries trace(myXML.item.(menuName=="burger").price); // Output: 3.95 Utilisez la méthode appendChild() pour affecter un nouveau noeud enfant à l’XML, comme l’indique le code suivant : var newItem:XML = medium cola 1.25 myXML.appendChild(newItem); Utilisez les opérateurs @ et. non seulement pour lire des données mais également pour les affecter, comme dans l’exemple suivant : myXML.item[0].menuName="regular burger"; myXML.item[1].menuName="small fries"; myXML.item[2].menuName="medium cola"; myXML.item.(menuName=="regular burger").@quantity = "2"; myXML.item.(menuName=="small fries").@quantity = "2"; myXML.item.(menuName=="medium cola").@quantity = "2"; Utilisez une boucle for pour parcourir en boucle les noeuds de l’XML, comme suit : var total:Number = 0; for each (var property:XML in myXML.item) { var q:int = Number(property.@quantity); var p:Number = Number(property.price); var itemTotal:Number = q * p; total += itemTotal; trace(q + " " + property.menuName + " $" + itemTotal.toFixed(2)) } trace("Total: $", total.toFixed(2)); Objets XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un objet XML peut représenter un élément XML, un attribut, un commentaire, une instruction de traitement ou un élément de texte. Un objet XML est classé soit dans la catégorie des objets ayant un contenu simple, soit dans celle des objets ayant un contenu complexe. Un objet XML ayant des noeuds enfant est considéré comme ayant un contenu complexe. Le contenu est considéré comme simple s’il correspond à un attribut, un commentaire, une instruction de traitement ou un noeud de texte. Par exemple, l’objet XML suivant contient un contenu complexe, y compris un commentaire et une instruction de traitement : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 104 Utilisation de XML Dernière mise à jour le 27/4/2013 XML.ignoreComments = false; XML.ignoreProcessingInstructions = false; var x1:XML = burger 3.95 fries 1.45 Comme l’indique l’exemple suivant, vous pouvez maintenant utiliser les méthodes comments() et processingInstructions() pour créer des objets XML, un commentaire et une instruction de traitement : var x2:XML = x1.comments()[0]; var x3:XML = x1.processingInstructions()[0]; Propriétés XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe XML a cinq propriétés statiques : • Les propriétés ignoreComments et ignoreProcessingInstructions déterminent si les commentaires ou les instructions de traitement sont ignorés lorsque l’objet XML est analysé. • La propriété ignoreWhitespace détermine si les espaces blancs sont ignorés dans les balises d’un élément et les expressions intégrées séparées uniquement par des espaces blancs. • Les propriétés prettyIndentet prettyPrinting servent à formater le texte renvoyé par les méthodes toString() et toXMLString() de la classe XML. Pour plus d’informations sur ces propriétés, voir le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Méthodes XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les méthodes suivantes vous permettent d’utiliser la structure hiérarchique des objets XML : • appendChild() • child() • childIndex() • children() • descendants() • elements() • insertChildAfter() GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 105 Utilisation de XML Dernière mise à jour le 27/4/2013 • insertChildBefore() • parent() • prependChild() Les méthodes suivantes vous permettent d’utiliser des attributs d’objet XML : • attribute() • attributes() Les méthodes suivantes vous permettent d’utiliser des propriétés d’objet XML : • hasOwnProperty() • propertyIsEnumerable() • replace() • setChildren() Les méthodes suivantes vous permettent d’utiliser des espaces de nom et des noms qualifiés : • addNamespace() • inScopeNamespaces() • localName() • name() • namespace() • namespaceDeclarations() • removeNamespace() • setLocalName() • setName() • setNamespace() Les méthodes suivantes vous permettent d’utiliser et de déterminer certains types de contenu XML : • comments() • hasComplexContent() • hasSimpleContent() • nodeKind() • processingInstructions() • text() Les méthodes suivantes vous permettent d’effectuer des conversions en chaînes et de formater des objets XML : • defaultSettings() • setSettings() • settings() • normalize() • toString() • toXMLString() GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 106 Utilisation de XML Dernière mise à jour le 27/4/2013 Il existe quelques méthodes supplémentaires : • contains() • copy() • valueOf() • length() Pour plus d’informations sur ces méthodes, voir le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Objets XMLList Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Une occurrence de XMLList représente un ensemble arbitraire d’objets XML. Elle peut contenir des documents XML complets, des fragments XML ou les résultats d’une requête XML. Les méthodes suivantes vous permettent d’utiliser la structure hiérarchique des objets XMLList : • child() • children() • descendants() • elements() • parent() Les méthodes suivantes vous permettent d’utiliser des attributs d’objet XMLList : • attribute() • attributes() Les méthodes suivantes vous permettent d’utiliser des propriétés XMLList : • hasOwnProperty() • propertyIsEnumerable() Les méthodes suivantes vous permettent d’utiliser et de déterminer certains types de contenu XML : • comments() • hasComplexContent() • hasSimpleContent() • processingInstructions() • text() Les méthodes suivantes vous permettent d’effectuer des conversions en chaînes et de formater les objets XMLList : • normalize() • toString() • toXMLString() GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 107 Utilisation de XML Dernière mise à jour le 27/4/2013 Il existe quelques méthodes supplémentaires : • contains() • copy() • length() • valueOf() Pour plus d’informations sur ces méthodes, voir le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Pour un objet XMLList qui contient exactement un élément XML, vous pouvez utiliser toutes les propriétés et les méthodes de la classe XML car un XMLList avec un élément XML est traité comme un objet XML. Par exemple, dans le code suivant, étant donné que doc.div est un objet XMLList contenant un élément, vous pouvez utiliser la méthode appendChild() de la classe XML : var doc:XML =

    ; doc.div.appendChild(

    World

    ); Pour consulter la liste des méthodes et des propriétés XML, voir « Objets XML » à la page 103. Initialisation de variables XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez affecter un littéral XML à un objet XML, comme suit : var myXML:XML = burger 3.95 fries 1.45 Comme indiqué dans le code suivant, vous pouvez également utiliser le constructeur new pour créer une occurrence d’un objet XML à partir d’une chaîne contenant des données XML : var str:String = "burger" + "3.95"; var myXML:XML = new XML(str); Si les données XML dans la chaîne ne sont pas bien formées (par exemple, s’il manque une balise de fin), une erreur d’exécution se produit. Vous pouvez également transmettre des données par référence (à partir d’autres variables) dans un objet XML, comme indiqué dans l’exemple suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 108 Utilisation de XML Dernière mise à jour le 27/4/2013 var tagname:String = "item"; var attributename:String = "id"; var attributevalue:String = "5"; var content:String = "Chicken"; var x:XML = <{tagname} {attributename}={attributevalue}>{content}; trace(x.toXMLString()) // Output: Chicken Pour charger des données XML depuis une URL, utilisez la classe URLLoader, comme indiqué dans l’exemple suivant : import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; var externalXML:XML; var loader:URLLoader = new URLLoader(); var request:URLRequest = new URLRequest("xmlFile.xml"); loader.load(request); loader.addEventListener(Event.COMPLETE, onComplete); function onComplete(event:Event):void { var loader:URLLoader = event.target as URLLoader; if (loader != null) { externalXML = new XML(loader.data); trace(externalXML.toXMLString()); } else { trace("loader is not a URLLoader!"); } } Pour lire des données XML depuis une connexion de socket, utilisez la classe XMLSocket . Pour plus d’informations, voir la classe XMLSocket dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Assemblage et transformation d’objets XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Utilisez la méthode prependChild() ou appendChild() pour ajouter une propriété au début ou à la fin de la liste des propriétés d’un objet XML, comme indiqué dans l’exemple suivant : var x1:XML =

    Line 1

    var x2:XML =

    Line 2

    var x:XML = x = x.appendChild(x1); x = x.appendChild(x2); x = x.prependChild(

    Line 0

    ); // x ==

    Line 0

    Line 1

    Line 2

    Utilisez la méthode insertChildBefore() ou insertChildAfter() pour ajouter une propriété avant ou après une propriété spécifiée, comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 109 Utilisation de XML Dernière mise à jour le 27/4/2013 var x:XML =

    Paragraph 1

    Paragraph 2

    var newNode:XML =

    Paragraph 1.5

    x = x.insertChildAfter(x.p[0], newNode) x = x.insertChildBefore(x.p[2],

    Paragraph 1.75

    ) Comme indiqué dans l’exemple suivant, vous pouvez également utiliser des accolades ( { et } ) pour transmettre des données par référence (à partir d’autres variables) lorsque vous construisez des objets XML : var ids:Array = [121, 122, 123]; var names:Array = [["Murphy","Pat"], ["Thibaut","Jean"], ["Smith","Vijay"]] var x:XML = new XML(""); for (var i:int = 0; i < 3; i++) { var newnode:XML = new XML(); newnode = {names[i][0]} {names[i][1]} ; x = x.appendChild(newnode) } Vous pouvez affecter des propriétés et des attributs à un objet XML à l’aide de l’opérateur =, comme dans l’exemple suivant : var x:XML = Smith x.firstname = "Jean"; x.@id = "239"; Ceci définit l’objet XML x de la façon suivante : Smith Jean Vous pouvez utiliser les opérateurs + et += pour concaténer des objets XMLList : var x1:XML =
    test1 var x2:XML = test2 var xList:XMLList = x1 + x2; xList += test3 Ceci définit l’objet XMLList xList de la façon suivante : test1 test2 test3 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 110 Utilisation de XML Dernière mise à jour le 27/4/2013 Parcours de structures XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’une des fonctions puissantes d’XML est sa capacité à fournir des données imbriquées, complexes, via une chaîne linéaire de caractères de texte. Lorsque vous chargez des données dans un objet XML, ActionScript les analyse et charge sa structure hiérarchique en mémoire (ou envoie une erreur d’exécution si les données XML ne sont pas formées correctement). Les opérateurs et les méthodes des objets XML et XMLList permettent de parcourir aisément la structure des données XML. Utilisez l’opérateur point (.) et l’opérateur d’accesseur descendant (..) pour accéder aux propriétés enfant d’un objet XML. Considérez l’objet XML suivant : var myXML:XML = Baking Extravagant Pastries with Kumquats Contino Chuck 238 Emu Care and Breeding Case Justin 115 L’objet myXML.book est un objet XMLList contenant des propriétés enfant de l’objet myXML appelées book. Ces deux objets XML correspondent aux deux propriétés book de l’objet myXML. L’objet myXML..lastName est un objet XMLList contenant des propriétés descendantes appelées lastName. Ces deux objets XML correspondent aux deux propriétés lastName de l’objet myXML. L’objet myXML.book.editor.lastName est un objet XMLList contenant tout enfant appelé lastName des enfants appelés editor des enfants appelés book de l’objet myXML : en l’occurrence, un objet XMLList contenant un seul objet XML (la propriété lastName dont la valeur correspond à « Case »). Accès aux noeuds enfant et parent Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode parent() renvoie le parent d’un objet XML. Vous pouvez utiliser les valeurs d’index ordinales d’une liste enfant pour accéder à des objets enfant spécifiques. Par exemple, considérez un objet XML myXML ayant deux propriétés enfant appelées book. Chaque propriété enfant appelée book possède un numéro d’index qui lui est associé : myXML.book[0] myXML.book[1] GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 111 Utilisation de XML Dernière mise à jour le 27/4/2013 Pour accéder à un petit-enfant spécifique, vous pouvez indiquer des numéros d’index pour les noms de l’enfant et du petit-enfant : myXML.book[0].title[0] Cependant, s’il n’existe qu’un seul enfant de x.book[0] nommé title, vous pouvez omettre la référence d’index, comme suit : myXML.book[0].title De même, s’il n’existe qu’un seul enfant book de l’objet x et que cet objet enfant possède un seul objet title, vous pouvez omettre les deux références d’index, de la façon suivante : myXML.book.title Vous pouvez utiliser la méthode child() pour accéder à des enfants dont le nom est basé sur une variable ou une expression, comme indiqué dans l’exemple suivant : var myXML:XML = Dictionary ; var childName:String = "book"; trace(myXML.child(childName).title) // output: Dictionary Accès à des attributs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Utilisez le symbole @ (l’opérateur identifiant d’attribut) pour accéder aux attributs dans un objet XML ou XMLList, comme indiqué dans le code suivant : var employee:XML = Wu Erin ; trace(employee.@id); // 6401 Vous pouvez utiliser le symbole de caractère générique * avec le symbole @ pour accéder à tous les attributs d’un objet XML ou XMLList, comme dans le code suivant : var employee:XML = Wu Erin ; trace(employee.@*.toXMLString()); // 6401 // 233 Vous pouvez utiliser la méthode attribute() ou attributes() pour accéder à un attribut spécifique ou à tous les attributs d’un objet XML ou XMLList, comme dans le code suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 112 Utilisation de XML Dernière mise à jour le 27/4/2013 var employee:XML = Wu Erin ; trace(employee.attribute("id")); // 6401 trace(employee.attribute("*").toXMLString()); // 6401 // 233 trace(employee.attributes().toXMLString()); // 6401 // 233 Vous pouvez également utiliser la syntaxe suivante pour accéder à des attributs, comme indiqué dans l’exemple suivant : employee.attribute("id") employee["@id"] employee.@["id"] Ils sont tous équivalents à employee.@id. Cependant, la syntaxe employee.@id est préférable. Filtrage par attribut ou valeur d’élément Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser les opérateurs parenthèses— ( et ) —pour filtrer des éléments avec un nom d’élément spécifique ou une valeur d’attribut. Considérez l’objet XML suivant : var x:XML = Zmed Sue Data analyst McGee Chuck Jr. data analyst Les expressions suivantes sont toutes valides : • x.employee.(lastName == "McGee")—Il s’agit du deuxième noeud employee. • x.employee.(lastName == "McGee").firstName—Il s’agit de la propriété firstName du deuxième noeud employee. • x.employee.(lastName == "McGee").@id—Il s’agit de la valeur de l’attribut id du deuxième noeud employee. • x.employee.(@id == 347)—Le premier noeud employee. • x.employee.(@id == 347).lastName—Il s’agit de la propriété lastName du premier noeud employee. • x.employee.(@id > 300)—Il s’agit d’un XMLList avec deux propriétés employee. • x.employee.(position.toString().search("analyst") > -1)—Il s’agit d’un XMLList avec deux propriétés position. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 113 Utilisation de XML Dernière mise à jour le 27/4/2013 Si vous tentez d’appliquer un filtre à des attributs ou des éléments qui n’existent pas, une exception est renvoyée. Par exemple, la dernière ligne du code suivant génère une erreur car il n’existe aucun attribut id dans le deuxième élément p : var doc:XML =

    Hello, Bob.

    Hello.

    ; trace(doc.p.(@id == '123')); De même, la dernière ligne du code suivant génère une erreur car il n’existe aucune propriété b du deuxième élément p : var doc:XML =

    Hello, Bob.

    Hello.

    ; trace(doc.p.(b == 'Bob')); Pour éviter ces erreurs, vous pouvez identifier les propriétés ayant les éléments ou les attributs correspondants, à l’aide des méthodes attribute() et elements(), comme dans le code suivant : var doc:XML =

    Hello, Bob.

    Hello.

    ; trace(doc.p.(attribute('id') == '123')); trace(doc.p.(elements('b') == 'Bob')); Vous pouvez également utiliser la méthode hasOwnProperty(), comme dans le code suivant : var doc:XML =

    Hello, Bob.

    Hello.

    ; trace(doc.p.(hasOwnProperty('@id') && @id == '123')); trace(doc.p.(hasOwnProperty('b') && b == 'Bob')); Utilisation de for..in et for each.. dans les instructions Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 3.0 propose les instructions for..in et for each..in pour permettre les itérations dans les objets XMLList. Par exemple, considérez l’objet XML suivant, myXML, et l’objet XMLList, myXML.item. L’objet XMLList, myXML.item, est constitué de deux noeuds item de l’objet XML. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 114 Utilisation de XML Dernière mise à jour le 27/4/2013 var myXML:XML = burger 3.95 fries 1.45 ; La boucle for..in permet de procéder à une itération sur un ensemble de noms de propriété dans un objet XMLList : var total:Number = 0; for (var pname:String in myXML.item) { total += myXML.item.@quantity[pname] * myXML.item.price[pname]; } La boucle for each..in permet de procéder à une itération dans les propriétés de l’objet XMLList : var total2:Number = 0; for each (var prop:XML in myXML.item) { total2 += prop.@quantity * prop.price; } Utilisation des espaces de noms XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les espaces de noms dans un objet (ou document) XML identifient le type de données que contient l’objet. Par exemple, lorsque vous envoyez et fournissez des données XML à un service Web qui utilise le protocole de messagerie SOAP, vous déclarez l’espace de noms dans la balise de début de l’XML : var message:XML = 78 ; L’espace de nom a un préfixe, soap, et un URI qui le définit, http://schemas.xmlsoap.org/soap/envelope/. ActionScript 3.0 inclut la classe Namespace pour utiliser des espaces de noms XML. Pour l’objet XML de l’exemple précédent, vous pouvez utiliser la classe Namespace comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 115 Utilisation de XML Dernière mise à jour le 27/4/2013 var soapNS:Namespace = message.namespace("soap"); trace(soapNS); // Output: http://schemas.xmlsoap.org/soap/envelope/ var wNS:Namespace = new Namespace("w", "http://www.test.com/weather/"); message.addNamespace(wNS); var encodingStyle:XMLList = message.@soapNS::encodingStyle; var body:XMLList = message.soapNS::Body; message.soapNS::Body.wNS::GetWeatherResponse.wNS::tempurature = "78"; Les méthodes suivantes de la classe XML permettent d’utiliser les espaces de nom : addNamespace(), inScopeNamespaces(), localName(), name(), namespace(), namespaceDeclarations(), removeNamespace(), setLocalName(), setName() et setNamespace(). La directive default xml namespace vous permet d’affecter un espace de nom par défaut associé aux objets XML. Par exemple, dans l’exemple suivant, x1 et x2 partagent le même espace de nom par défaut : var ns1:Namespace = new Namespace("http://www.example.com/namespaces/"); default xml namespace = ns1; var x1:XML = ; var x2:XML = ; Conversion de type XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez convertir des objets XML et XMLList en valeurs String. De même, vous pouvez convertir des chaînes en objets XML et XMLList. Sachez que toutes les valeurs d’attribut, les noms et les valeurs de texte XML sont des chaînes. Les sections suivantes décrivent toutes ces formes de conversion de type XML. Conversion d’objets XML et XMLList en chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les classes XML et XMLList contiennent les méthodes toString() et toXMLString(). La méthode toXMLString() renvoie une chaîne qui comprend la totalité des balises, des attributs, des déclarations d’espace de nom et du contenu de l’objet XML. Pour les objets XML ayant un contenu complexe (éléments enfant), la méthode toString() procède exactement comme la méthode toXMLString(). Pour les objets XML ayant un contenu simple (ceux qui contiennent un seul élément de texte), la méthode toString() renvoie uniquement le contenu de texte de l’élément, comme indiqué dans l’exemple suivant : var myXML:XML = burger 3.95 ; trace(myXML.item[0].menuName.toXMLString()); // burger trace(myXML.item[0].menuName.toString()); // burger GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 116 Utilisation de XML Dernière mise à jour le 27/4/2013 Si vous utilisez la méthode trace() sans spécifier toString() ou toXMLString(), les données sont converties à l’aide de la méthode toString() par défaut, comme indiqué dans le code suivant : var myXML:XML = burger 3.95 ; trace(myXML.item[0].menuName); // burger Lorsque vous utilisez la méthode trace() pour déboguer un code, vous pouvez utiliser la méthode toXMLString() de façon à ce que la méthode trace() génère des données plus complètes. Conversion de chaînes en objets XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser le constructeur new XML() pour créer un objet XML à partir d’une chaîne, comme suit : var x:XML = new XML("test"); Si vous tentez de convertir une chaîne en XML à partir d’une chaîne qui représente un XML non valide ou un XML qui n’est pas formé correctement, une erreur d’exécution est renvoyée, comme suit : var x:XML = new XML("test"); // throws an error Conversion de valeurs d’attribut, de noms et de valeurs de texte à partir de chaînes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Toutes les valeurs d’attribut XML, les noms et les valeurs de texte sont des types de données String que vous pouvez convertir en d’autres types de données. Par exemple, le code suivant utilise la fonction Number() pour convertir des valeurs de texte en nombres : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 117 Utilisation de XML Dernière mise à jour le 27/4/2013 var myXML:XML = 3.95 1.00 ; var total:XML = 0; myXML.appendChild(total); for each (var item:XML in myXML.item) { myXML.total.children()[0] = Number(myXML.total.children()[0]) + Number(item.price.children()[0]); } trace(myXML.total); // 4.95; Si ce code n’utilisait pas la fonction Number(), il interpréterait l’opérateur + comme l’opérateur de concaténation de chaîne, et la méthode trace() de la dernière ligne générerait les éléments suivants : 01.003.95 Lecture de documents XML externes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser la classe URLLoader pour charger des données XML depuis une URL. Pour utiliser le code suivant dans vos applications, remplacez la valeur XML_URL dans l’exemple par une URL valide : import flash.events.Event; import flash.net.URLLoader; var myXML:XML = new XML(); var XML_URL:String = "http://www.example.com/Sample3.xml"; var myXMLURL:URLRequest = new URLRequest(XML_URL); var myLoader:URLLoader = new URLLoader(myXMLURL); myLoader.addEventListener(Event.COMPLETE, xmlLoaded); function xmlLoaded(event:Event):void { myXML = XML(myLoader.data); trace("Data loaded."); } Vous pouvez également utiliser la classe XMLSocket pour définir une connexion de socket XML asynchrone avec un serveur. Pour plus d’informations, voir le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 118 Utilisation de XML Dernière mise à jour le 27/4/2013 Utilisation de XML dans un exemple ActionScript : chargement de données RSS depuis Internet Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple d’application RSSViewer présente plusieurs fonctions d’utilisation d’XML dans ActionScript, notamment : • Utilisation de méthodes XML pour parcourir des données XML sous la forme d’un flux RSS. • Utilisation de méthodes XML pour assembler des données XML sous la forme HTML à utiliser dans un champ de texte. Le format RSS est largement utilisé pour diffuser des nouvelles via XML. Un fichier de données RSS simple peut avoir l’aspect suivant : Alaska - Weather http://www.nws.noaa.gov/alerts/ak.html Alaska - Watches, Warnings and Advisories Short Term Forecast - Taiya Inlet, Klondike Highway (Alaska) http://www.nws.noaa.gov/alerts/ak.html#A18.AJKNK.1900 Short Term Forecast Issued At: 2005-04-11T19:00:00 Expired At: 2005-04-12T01:00:00 Issuing Weather Forecast Office Homepage: http://pajk.arh.noaa.gov Short Term Forecast - Haines Borough (Alaska) http://www.nws.noaa.gov/alerts/ak.html#AKZ019.AJKNOWAJK.190000 Short Term Forecast Issued At: 2005-04-11T19:00:00 Expired At: 2005-04-12T01:00:00 Issuing Weather Forecast Office Homepage: http://pajk.arh.noaa.gov L’application SimpleRSS lit les données RSS depuis Internet, analyse les données à la recherche de titres, de liens et de descriptions et renvoie ces données. La classe SimpleRSSUI fournit l’IU et appelle la classe SimpleRSS qui effectue le traitement XML. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 119 Utilisation de XML Dernière mise à jour le 27/4/2013 Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application RSSViewer se trouvent dans le dossier Samples/RSSViewer. L’application se compose des fichiers suivants : Lecture et analyse de données XML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe RSSParser comprend une méthode xmlLoaded() qui convertit les données RSS d’entrée, stockées dans la variable rssXML, en une chaîne contenant une sortie formatée HTML, rssOutput. Vers le début de la méthode, le code définit l’espace de nom XML par défaut si les données RSS source comprennent un espace de nom par défaut : if (rssXML.namespace("") != undefined) { default xml namespace = rssXML.namespace(""); } Les lignes suivantes parcourent ensuite en boucle le contenu des données XML source, en examinant chaque propriété descendante appelée item : for each (var item:XML in rssXML..item) { var itemTitle:String = item.title.toString(); var itemDescription:String = item.description.toString(); var itemLink:String = item.link.toString(); outXML += buildItemHTML(itemTitle, itemDescription, itemLink); } Les trois premières lignes définissent simplement des variables de chaîne pour représenter les propriétés de titre, de description et de lien de la propriété item des données XML. La ligne suivante appelle la méthode buildItemHTML() pour obtenir des données HTML sous la forme d’un objet XMLList et utilise les trois nouvelles variables de chaîne en tant que paramètres. Fichier Description RSSViewer.mxml ou RSSViewer.fla Fichier d’application principal dans Flash (FLA) ou Flex (MXML). com/example/programmingas3/rssViewer/RSSParser.as Une classe qui contient des méthodes utilisant E4X pour parcourir des données (XML) RSS et générer une représentation HTML correspondante. RSSData/ak.rss Un exemple de fichier RSS. Cette application est définie pour lire des données RSS à partir du Web, sur un flux RSS Flex hébergé par Adobe. Néanmoins, vous pouvez facilement modifier l’application pour lire des données RSS depuis ce document qui utilise un schéma légèrement différent de celui du flux RSS Flex. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 120 Utilisation de XML Dernière mise à jour le 27/4/2013 Assemblage de données XMLList Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les données HTML (un objet XMLList) se présentent comme suit : itemTitle

    itemDescription
    More...

    Les premières lignes de la méthode effacent l’espace de noms xml par défaut : default xml namespace = new Namespace(); La directive default xml namespace a un domaine de niveau bloc de fonction. Cela signifie que le domaine de cette déclaration est la méthode buildItemHTML(). Les lignes qui suivent assemblent l’objet XMLList en fonction des arguments de chaîne transmis à la fonction : var body:XMLList = new XMLList(); body += new XML("" + itemTitle + ""); var p:XML = new XML("

    " + itemDescription + "

    "); var link:XML = ; link.@href = itemLink; // link.font.@color = "#008000"; // // 0x008000 = green link.font = "More..."; p.appendChild(
    ); p.appendChild(link); body += p; Cet objet XMLList représente des données de chaîne adaptées à un champ de texte HTML d’ActionScript. La méthode xmlLoaded() utilise la valeur de renvoi de la méthode buildItemHTML() et la convertit en une chaîne : XML.prettyPrinting = false; rssOutput = outXML.toXMLString(); Extraction du titre du flux RSS et envoi d’un événement personnalisé Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode xmlLoaded() définit une variable de chaîne rssTitle en fonction des informations contenues dans les données XML RSS source : rssTitle = rssXML.channel.title.toString(); Pour finir, la méthode xmlLoaded() génère un événement qui notifie l’application que les données sont analysées et disponibles : dataWritten = new Event("dataWritten", true); 121 Dernière mise à jour le 27/4/2013 Chapitre 7 : Utilisation de la fonctionnalité JSON native ActionScript 3.0 fournit une API native permettant de coder et de décoder des objets ActionScript à l’aide du format JavaScript Object Notation (JSON). La classe JSON et les fonctions membres associées suivent la spécification ECMA- 262 5e édition avec de légères variations. Le membre de la communauté Todd Anderson fournit une comparaison entre l’API JSON native et la classe JSON as3corelib tierce. Voir Working with Native JSON in Flash Player 11 (disponible en anglais uniquement). Voir aussi JSON Présentation de l’API JSON L’API JSON ActionScript est constituée de la classe JSON et des fonctions membres toJSON() sur quelques classes natives. Pour les applications nécessitant un codage JSON personnalisé pour une classe, la structure ActionScript propose diverses méthodes permettant de remplacer le codage par défaut. La classe JSON gère en interne l’importation et l’exportation des classes ActionScript qui ne fournissent pas de membre toJSON(). Dans ces cas, la classe JSON traverse les propriétés publiques de chaque objet qu’elle détecte. Si un objet contient d’autres objets, JSON parcourt les objets imbriqués et effectue la même traversée. Si un objet fournit une méthode toJSON(), JSON utilise cette méthode personnalisée plutôt que son algorithme interne. L’interface JSON est composée d’une méthode d’encodage, stringify(), et d’une méthode de décodage, parse(). Chacune de ces méthodes fournit un paramètre permettant d’insérer votre propre logique dans la procédure de codage et de décodage JSON. Pour stringify(), ce paramètre est appelé replacer ; pour parse(), il est appelé reviver. Ces paramètres prennent une définition de fonction avec deux arguments à l’aide de la signature suivante : function(k, v):* Méthodes toJSON() La signature des méthodes toJSON() est public function toJSON(k:String):* JSON.stringify() appelle la méthode toJSON(), si elle existe, pour chaque propriété publique qu’elle rencontre lorsqu’elle traverse un objet. Une propriété consiste en une paire clé-valeur. Lorsque stringify() appelle la méthode toJSON(), il transmet la clé, k, de la propriété qu’il examine actuellement. Une implémentation toJSON() standard évalue chaque nom de propriété et renvoie l’encodage souhaité de sa valeur. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 122 Utilisation de la fonctionnalité JSON native Dernière mise à jour le 27/4/2013 La méthode toJSON() peut renvoyer tout type de valeur (identifiée à l’aide du signe *) et pas uniquement une chaîne. Ce type de renvoi de variable permet à la méthode toJSON() de renvoyer un objet, le cas échéant. Par exemple, si une propriété de votre classe personnalisée contient un objet issu d’une autre bibliothèque tierce, vous pouvez renvoyer cet objet dès que la méthode toJSON() détecte votre propriété. JSON parcourt alors l’objet tiers. Le processus de codage est le suivant : • Si la méthode toJSON() renvoie un objet qui n’est pas évalué par rapport à une chaîne, stringify() parcourt cet objet. • Si la méthode toJSON() renvoie une chaîne, stringify() enveloppe la valeur dans une autre chaîne, renvoie la chaîne enveloppée et passe à la valeur suivante. Dans de nombreux cas, il est préférable de renvoyer un objet plutôt que de renvoyer une chaîne JSON créée par votre application. Le renvoi d’un objet implique l’utilisation de l’algorithme de codage JSON et permet à JSON de se répéter dans les objets imbriqués. La méthode toJSON() n’est pas définie dans la classe Object ou dans la plupart des autres classes natives. Son absence indique à JSON d’effectuer sa traversée standard sur les propriétés publiques de l’objet. Si vous préférez, vus pouvez également utiliser la méthode toJSON() pour exposer les propriétés privées de votre objet. Certaines classes natives posent néanmoins des problèmes que les bibliothèques ActionScript sont incapables de résoudre efficacement dans tous les cas d’utilisation. Pour ces classes, ActionScript fournit une implémentation triviale que le client peut à nouveau implémenter selon ses besoins. Les classes qui fournissent des membres toJSON() triviaux sont les suivantes : • ByteArray • Date • Dictionary • XML Vous pouvez intégrer la classe ByteArray dans une sous-classe pour remplacer sa méthode toJSON(), mais vous pouvez aussi redéfinir son prototype. Les classes Date et XML, qui sont déclarées comme étant finales, vous obligent à utiliser le prototype de classe pour redéfinir toJSON(). La classe Dictionary est déclarée comme étant dynamique, ce qui vous donne la liberté de remplacer la méthode toJSON(). Définition du comportement JSON personnalisé Vous disposez de plusieurs options pour implémenter vos propres codage et décodage JSON pour les classes natives : • Définir ou remplacer toJSON() sur la sous-classe personnalisée d’une classe native non finale • Définir et redéfinir toJSON() sur le prototype de la classe • Définir une propriété toJSON sur une classe dynamique • Utiliser les paramètres JSON.stringify() replacer et JSON.parser() reviver Voir aussi ECMA-262, 5e édition GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 123 Utilisation de la fonctionnalité JSON native Dernière mise à jour le 27/4/2013 Définition de la méthode toJSON() sur le prototype d’une classe intégrée L’implémentation JSON native dans ActionScript imite le mécanisme JSON ECMAScript défini dans ECMA-262, 5e édition. Etant donné qu’ECMAScript ne prend pas en charge les classes, ActionScript définit le comportement de JSON en termes de distribution basée sur les prototypes. Ancêtres des classes ActionScript 3.0, les prototypes permettent un héritage simulé, ainsi que les ajouts et redéfinitions de membres. ActionScript permet de définir ou de redéfinir toJSON() sur le prototype d’une classe. Ce privilège s’étend aux classes déclarées comme étant finales. Lorsque vous définissez toJSON() sur le prototype d’une classe, votre définition s’applique à toutes les occurrences de cette classe dans le cadre de votre application. Par exemple, voici comment vous pouvez définir une méthode toJSON() sur le prototype de la classe MovieClip : MovieClip.prototype.toJSON = function(k):* { trace("prototype.toJSON() called."); return "toJSON"; } Lorsque votre application appelle la méthode stringify() sur une occurrence de MovieClip, stringify()renvoie le résultat de votre méthode toJSON() : var mc:MovieClip = new MovieClip(); var js:String = JSON.stringify(mc); //"prototype toJSON() called." trace("js: " + js); //"js: toJSON" Vous pouvez en outre remplacer toJSON() dans les classes natives qui définissent cette méthode. Par exemple, le code suivant remplace Date.toJSON() : Date.prototype.toJSON = function (k):* { return "any date format you like via toJSON: "+ "this.time:"+this.time + " this.hours:"+this.hours; } var dt:Date = new Date(); trace(JSON.stringify(dt)); // "any date format you like via toJSON: this.time:1317244361947 this.hours:14" Définition ou remplacement de toJSON() au niveau de la classe Les applications n’ont pas toujours besoin d’utiliser des prototypes pour redéfinir toJSON(). Il est également possible de définir toJSON() en tant que membre d’une sous-classe si la classe parente n’est pas marquée comme finale. Vous pouvez par exemple étendre la classe ByteArray et définir une fonction toJSON() publique : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 124 Utilisation de la fonctionnalité JSON native Dernière mise à jour le 27/4/2013 package { import flash.utils.ByteArray; public class MyByteArray extends ByteArray { public function MyByteArray() { } public function toJSON(s:String):* { return "MyByteArray"; } } } var ba:ByteArray = new ByteArray(); trace(JSON.stringify(ba)); //"ByteArray" var mba:MyByteArray = new MyByteArray(); //"MyByteArray" trace(JSON.stringify(mba)); //"MyByteArray" Si un classe est dynamique, il est possible d’ajouter une propriété toJSON à un objet de cette classe et de lui attribuer une fonction de la façon suivante : var d:Dictionary = new Dictionary(); trace(JSON.stringify((d))); // "Dictionary" d.toJSON = function(){return {c : "toJSON override."};} // overrides existing function trace(JSON.stringify((d))); // {"c":"toJSON override."} Vous pouvez remplacer, définir ou redéfinir toJSON() sur n’importe quelle classe ActionScript. Néanmoins, la plupart des classes ActionScript intégrées ne définissent pas toJSON(). La classe Object ne définit pas la méthode toJSON dans son prototype par défaut ni ne la déclare en tant que membre de classe. Seule une poignée de classes natives définit la méthode comme fonction prototype. C’est pourquoi, dans la plupart des cas, vous ne pouvez pas remplacer toJSON() de façon traditionnelle. Les classes natives qui ne définissent pas toJSON() sont sérialisées sur JSON par l’implémentation JSON interne. Dans la mesure du possible, évitez de remplacer cette fonctionnalité intégrée. Si vous définissez un membre toJSON(), la classe JSON utilise votre logique plutôt que sa propre fonctionnalité. Utilisation du paramètre replacer de la méthode JSON.stringify() Il peut être utile de remplacer toJSON() sur le prototype en vue de modifier le comportement d’exportation JSON d’une classe dans une application. Néanmoins, votre logique d’exportation doit s’appliquer uniquement à des cas spéciaux sous des conditions provisoires. Pour prendre en compte ces modifications à petite échelle, vous pouvez utiliser le paramètre replacer de la méthode JSON.stringify(). La méthode stringify() applique la fonction transmise via le paramètre replacer à l’objet en cours de codage. La signature pour cette fonction est similaire à celle de toJSON() : function (k,v):* GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 125 Utilisation de la fonctionnalité JSON native Dernière mise à jour le 27/4/2013 Contrairement à la méthode toJSON(), la fonction replacer requiert la valeur v, ainsi que la clé k. Cette différence est nécessaire, car la méthode stringify() est définie sur l’objet JSON statique et non sur l’objet en cours de codage. Lorsque la méthode JSON.stringify() appelle replacer(k,v), elle traverse l’objet d’entrée d’origine. Le paramètre implicite this transmis à la fonction replacer fait référence à l’objet qui détient la clé et la valeur. Etant donné que la méthode JSON.stringify() ne modifie pas l’objet d’entrée d’origine, cet objet reste inchangé dans le conteneur actuellement traversé. Vous pouvez par conséquent utiliser le code this[k] pour interroger la clé sur l’objet d’origine. Le paramètre v renferme la valeur que toJSON() convertit. Tout comme toJSON(), la fonction replacer peut renvoyer tout type de valeur. Si replacer renvoie une chaîne, le moteur JSON convertit le contenu en séquence d’échappement entre guillemets et place ce contenu également entre guillemets. Cette structure garantit que stringify() reçoive un objet de chaîne JSON valide qui reste une chaîne dans un prochain appel de JSON.parse(). Le code suivant utilise le paramètre replacer et le paramètre this implicite pour renvoyer les valeurs time et hours d’un objet Date : JSON.stringify(d, function (k,v):* { return "any date format you like via replacer: "+ "holder[k].time:"+this[k].time + " holder[k].hours:"+this[k].hours; }); Utilisation du paramètre reviver de la méthode JSON.parse() Le paramètre reviver de la méthode JSON.parse() est l’opposé de la fonction replacer : il convertit une chaîne JSON en objet ActionScript utilisable. L’argument reviver est une fonction qui prend deux paramètres et renvoie tout type : function (k,v):* Dans cette fonction, k est une clé et v est la valeur de k. Tout comme stringify(), parse() traverse les paires clévaleur JSON et applique la fonctionreviver, si elle existe, à chaque paire. L’un des problèmes potentiels est que la classe JSON ne renvoie pas le nom de classe ActionScript d’un objet. Il peut par conséquent être difficile de savoir quel type d’objet ranimer. Ce problème peut en outre s’avérer particulièrement délicat lorsque les objets sont imbriqués. En désignant les fonctions toJSON(), replacer et reviver, vous pouvez trouver des moyens d’identifier les objets ActionScript exportés tout en gardant intacts les objets d’origine. Exemple d’analyse L’exemple suivant illustre une stratégie de ranimation d’objets analysés à partir de chaînes JSON. Cet exemple définit deux classes : JSONGenericDictExample et JSONDictionaryExtnExample. La classe JSONGenericDictExample est une classe Dictionary personnalisée. Chaque enregistrement contient le nom et la date de naissance d’une personne, ainsi qu’un ID unique. Chaque fois que le constructeur JSONGenericDictExample est appelé, il ajoute l’objet nouvellement créé à un tableau statique interne avec un entier augmentant statiquement comme son ID. La classe JSONGenericDictExample définit également une méthode revive() qui extrait uniquement l’entier du membre id le plus long. La méthode revive() utilise cet entier pour rechercher et renvoyer l’objet ranimable adéquat. La classe JSONDictionaryExtnExample étend la classe Dictionary ActionScript. Ses enregistrements n’ont pas de structure définie et peuvent contenir toutes sortes de données. Les données sont attribuées après la construction de l’objet JSONDictionaryExtnExample et non par les propriétés définies dans la classe. Les enregistrements de JSONDictionaryExtnExample utilisent les objets JSONGenericDictExample comme clés. Lorsqu’un objet JSONDictionaryExtnExample est ranimé, la fonction JSONGenericDictExample.revive() utilise l’ID associé à JSONDictionaryExtnExample pour récupérer l’objet de clé correct. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 126 Utilisation de la fonctionnalité JSON native Dernière mise à jour le 27/4/2013 Plus important encore, la méthode JSONDictionaryExtnExample.toJSON() renvoie une chaîne de marqueurs en plus de l’objet JSONDictionaryExtnExample. Cette chaîne identifie la sortie JSON comme appartenant à la classe JSONDictionaryExtnExample. Ce marqueur indique clairement le type d’objet en cours de traitement lors de l’exécution de JSON.parse(). package { // Generic dictionary example: public class JSONGenericDictExample { static var revivableObjects = []; static var nextId = 10000; public var id; public var dname:String; public var birthday; public function JSONGenericDictExample(name, birthday) { revivableObjects[nextId] = this; this.id = "id_class_JSONGenericDictExample_" + nextId; this.dname = name; this.birthday = birthday; nextId++; } public function toString():String { return this.dname; } public static function revive(id:String):JSONGenericDictExample { var r:RegExp = /^id_class_JSONGenericDictExample_([0-9]*)$/; var res = r.exec(id); return JSONGenericDictExample.revivableObjects[res[1]]; } } } package { import flash.utils.Dictionary; import flash.utils.ByteArray; // For this extension of dictionary, we serialize the contents of the // dictionary by using toJSON public final class JSONDictionaryExtnExample extends Dictionary { public function toJSON(k):* { var contents = {}; for (var a in this) { contents[a.id] = this[a]; } // We also wrap the contents in an object so that we can // identify it by looking for the marking property "class E" // while in the midst of JSON.parse. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 127 Utilisation de la fonctionnalité JSON native Dernière mise à jour le 27/4/2013 return {"class JSONDictionaryExtnExample": contents}; } // This is just here for debugging and for illustration public function toString():String { var retval = "[JSONDictionaryExtnExample <"; var printed_any = false; for (var k in this) { retval += k.toString() + "=" + "[e="+this[k].earnings + ",v="+this[k].violations + "], " printed_any = true; } if (printed_any) retval = retval.substring(0, retval.length-2); retval += ">]" return retval; } } } Lorsque le script d’exécution suivant appelle JSON.parse() sur un objet JSONDictionaryExtnExample, la fonction reviver appelle JSONGenericDictExample.revive() sur chaque objet dans JSONDictionaryExtnExample. Cet appel extrait l’ID qui représente la clé de l’objet. La fonction JSONGenericDictExample.revive() utilise cet ID pour récupérer et renvoyer l’objet JSONDictionaryExtnExample stocké à partir d’un tableau statique privé. import flash.display.MovieClip; import flash.text.TextField; var a_bob1:JSONGenericDictExample = new JSONGenericDictExample("Bob", new Date(Date.parse("01/02/1934"))); var a_bob2:JSONGenericDictExample = new JSONGenericDictExample("Bob", new Date(Date.parse("05/06/1978"))); var a_jen:JSONGenericDictExample = new JSONGenericDictExample("Jen", new Date(Date.parse("09/09/1999"))); var e = new JSONDictionaryExtnExample(); e[a_bob1] = {earnings: 40, violations: 2}; e[a_bob2] = {earnings: 10, violations: 1}; e[a_jen] = {earnings: 25, violations: 3}; trace("JSON.stringify(e): " + JSON.stringify(e)); // {"class JSONDictionaryExtnExample": //{"id_class_JSONGenericDictExample_10001": //{"earnings":10,"violations":1}, //"id_class_JSONGenericDictExample_10002": //{"earnings":25,"violations":3}, //"id_class_JSONGenericDictExample_10000": // {"earnings":40,"violations":2}}} var e_result = JSON.stringify(e); var e1 = new JSONDictionaryExtnExample(); var e2 = new JSONDictionaryExtnExample(); // It's somewhat easy to convert the string from JSON.stringify(e) back // into a dictionary (turn it into an object via JSON.parse, then loop // over that object's properties to construct a fresh dictionary). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 128 Utilisation de la fonctionnalité JSON native Dernière mise à jour le 27/4/2013 // // The harder exercise is to handle situations where the dictionaries // themselves are nested in the object passed to JSON.stringify and // thus does not occur at the topmost level of the resulting string. // // (For example: consider roundtripping something like // var tricky_array = [e1, [[4, e2, 6]], {table:e3}] // where e1, e2, e3 are all dictionaries. Furthermore, consider // dictionaries that contain references to dictionaries.) // // This parsing (or at least some instances of it) can be done via // JSON.parse, but it's not necessarily trivial. Careful consideration // of how toJSON, replacer, and reviver can work together is // necessary. var e_roundtrip = JSON.parse(e_result, / / This is a reviver that is focused on rebuilding JSONDictionaryExtnExample objects. function (k, v) { if ("class JSONDictionaryExtnExample" in v) { // special marker tag; //see JSONDictionaryExtnExample.toJSON(). var e = new JSONDictionaryExtnExample(); var contents = v["class JSONDictionaryExtnExample"]; for (var i in contents) { // Reviving JSONGenericDictExample objects from string // identifiers is also special; // see JSONGenericDictExample constructor and // JSONGenericDictExample's revive() method. e[JSONGenericDictExample.revive(i)] = contents[i]; } return e; } else { return v; } }); trace("// == Here is an extended Dictionary that has been round-tripped =="); trace("// == Note that we have revived Jen/Jan during the roundtrip. =="); trace("e: " + e); //[JSONDictionaryExtnExample ] trace("e_roundtrip: " + e_roundtrip); //[JSONDictionaryExtnExample ] trace("Is e_roundtrip a JSONDictionaryExtnExample? " + (e_roundtrip is JSONDictionaryExtnExample)); //true trace("Name change: Jen is now Jan"); a_jen.dname = "Jan" trace("e: " + e); //[JSONDictionaryExtnExample ] trace("e_roundtrip: " + e_roundtrip); //[JSONDictionaryExtnExample ] 129 Dernière mise à jour le 27/4/2013 Chapitre 8 : Gestion des événements Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un système de gestion des événements permet au programmeur de répondre aux actions de l’utilisateur et aux événements système de manière pratique. Le modèle d’événement ActionScript 3.0 n’est pas seulement pratique, il est conforme aux normes en vigueur et bien intégré à la liste d’affichage. Ce modèle repose sur la spécification d’événements Document Object Model (DOM) de niveau 3, une architecture de gestion d’événements normalisée. Il constitue donc pour les programmeurs ActionScript un outil puissant et parfaitement intuitif. Le système de gestion d’événements ActionScript 3.0 assure une interaction étroite avec la liste d’affichage. Pour comprendre les principes de base de la liste d’affichage, voir « Programmation de l’affichage » à la page 156. Voir aussi Package flash.events Spécification d’événements Document Object Model (DOM) niveau 3 Principes de base de la gestion des événements Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez concevoir un événement comme tout type d’action qui se produit dans votre fichier SWF et qui présente un intérêt pour vous en tant que programmeur. Par exemple, la plupart des fichiers SWF prennent en charge une certaine forme d’interaction, qu’il s’agisse d’une action aussi simple qu’un clic avec la souris ou d’une opération plus complexe, telle que l’acceptation et le traitement des données saisies dans un formulaire. Toute interaction de ce type dans le fichier SWF est considérée comme un événement. Des événements peuvent également se produire sans aucun interaction directe de l’utilisateur, par exemple lorsque le chargement des données depuis un serveur se termine ou qu’une caméra reliée devient active. Dans ActionScript 3.0, tout événement est représenté par un objet événement, qui correspond à une occurrence de la classe Event ou de l’une de ses sous-classes. Le rôle d’un objet événement est non seulement de stocker des informations relatives à un événement spécifique, mais aussi de contenir des méthodes qui favorisent la manipulation de cet objet. Par exemple, lorsque Flash Player ou AIR détecte un clic de la souris, il crée un objet événement (une occurrence de la classe MouseEvent) qui représente cet événement particulier. Après la création d’un objet événement, Flash Player ou AIR le distribue, ce qui signifie que l’objet événement est transmis à l’objet représentant la cible de l’événement. L’objet qui doit recevoir l’objet événement ainsi distribué est appelé cible d’événement. Par exemple, lorsqu’une caméra reliée devient active, Flash Player distribue un objet événement directement à la cible de l’événement, dans ce cas l’objet représentant la caméra. Toutefois, si la cible d’événement se trouve dans la liste d’affichage, l’objet événement est transmis tout au long de la hiérarchie de la liste d’affichage jusqu’à ce qu’il atteigne la cible en question. Dans certains cas, l’objet événement se « propage » ensuite vers le haut de la hiérarchie de la liste d’affichage, selon le même cheminement. Cette traversée de la hiérarchie de la liste d’affichage correspond au flux d’événements. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 130 Gestion des événements Dernière mise à jour le 27/4/2013 Vous pouvez « écouter » les objets événement de votre code grâce aux écouteurs d’événement. Les écouteurs d’événement sont des fonctions ou des méthodes que vous écrivez pour répondre aux différents événements. Pour garantir que le programme réagisse aux événements, vous devez ajouter des écouteurs d’événement soit à la cible d’événement, soit à l’un des objets de la liste d’affichage qui font partie du flux d’événements de l’objet événement. Chaque fois que vous écrivez un code d’écouteur d’événement, il suit cette structure de base (les éléments en gras sont des espaces réservés que vous rempliriez pour votre cas particulier) : function eventResponse(eventObject:EventType):void { // Actions performed in response to the event go here. } eventTarget.addEventListener(EventType.EVENT_NAME, eventResponse); Ce code a un double rôle. Tout d’abord, il définit une fonction, qui est une manière de spécifier les actions à exécuter en réponse à l’événement. Ensuite, il appelle la méthode addEventListener() de l’objet source, « inscrivant » ainsi la fonction auprès de l’événement spécifié de sorte que lorsque l’événement survient, les actions de la fonction ont lieu. Lorsque l’événement se produit, la cible de l’événement vérifie sa liste de toutes les fonctions et méthodes enregistrées en tant qu’écouteurs d’événement. Elle appelle ensuite chacune d’elles, transmettant l’objet événement à titre de paramètre. Vous devez apporter quatre modifications à ce code pour créer votre propre écouteur d’événement. Premièrement, vous devez remplacer le nom de la fonction par celui que vous souhaitez utiliser (ceci doit être modifié à deux endroits, là où le code indique eventResponse). Deuxièmement, vous devez spécifier le nom de la classe de l’objet événement qui est envoyé par l’événement que vous souhaitez écouter (EventType dans le code), et vous devez indiquer la constante pour l’événement en question (EVENT_NAME dans la liste). Troisièmement, vous devez appeler la méthode addEventListener() sur l’objet qui enverra l’événement (eventTarget dans ce code). Vous pouvez également modifier le nom de la variable utilisée comme paramètre de la fonction (eventObject dans ce code). Concepts importants et terminologie La liste de référence suivante contient des termes importants utilisés dans le cadre de la rédaction de routines de gestion des événements : Propagation Certains événements donnent lieu à une propagation afin de permettre à un objet d’affichage parent de réagir aux événements distribués par ses enfants. Phase de propagation Partie du flux d’événements dans laquelle un événement est propagé jusqu’aux objets d’affichage parent. La phase de propagation suit la phase de capture et la phase cible. Phase de capture Partie du flux d’événements dans laquelle un événement se propage de la cible la plus générale vers l’objet cible le plus spécifique. La phase de capture précède la phase cible et la phase de propagation. Comportement par défaut Certains événements sont liés à un comportement appelé comportement par défaut. Par exemple, lorsqu’un utilisateur tape du texte dans un champ, un événement de saisie de texte est déclenché. Le comportement par défaut de cet événement consiste à afficher le caractère tapé dans le champ de texte—mais vous pouvez annuler ce comportement par défaut (si vous ne souhaitez pas afficher le caractère tapé, par exemple). Distribuer Indiquer à des écouteurs d’événements qu’un événement a eu lieu. Evénement Opération subie par un objet et que ce dernier peut signaler à d’autres objets. Flux d’événements Lorsque des événements concernent un objet de la liste d’affichage (un objet affiché à l’écran), tous les objets qui contiennent cet objet sont informés de l’événement et avertissent à leur tour les écouteurs d’événements correspondants. Ce processus commence avec la scène et se poursuit à travers la liste d’affichage jusqu’à l’objet réel où s’est produit l’événement. Il recommence ensuite avec la scène. Ce processus est appelé flux d’événements. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 131 Gestion des événements Dernière mise à jour le 27/4/2013 Objet événement Objet contenant des informations sur l’occurrence d’un événement particulier, qui est envoyé à tous les écouteurs lorsqu’un événement est distribué. Cible d’événement Objet qui envoie un événement. Par exemple, si l’utilisateur clique sur un bouton situé dans un Sprite se trouvant dans la scène, tous ces objets envoient des événements mais c’est au niveau de la cible d’événement que se produit l’événement (le bouton cliqué, dans ce cas). Ecouteur Objet ou fonction qui s’est enregistré auprès d’un objet pour indiquer qu’il doit être averti lorsqu’un événement spécifique se produit. Phase cible Stade du flux d’événements où un événement atteint la cible la plus spécifique possible. La phase cible se produit entre la phase de capture et la phase de propagation. Variation de la gestion d’événements dans ActionScript 3.0 par rapport aux versions antérieures Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures En ce qui concerne la gestion des événements, la différence la plus évidente entre ActionScript 3.0 et les versions antérieures est qu’ActionScript 3.0 comprend un seul système de gestion des événements alors que les anciennes versions d’ActionScript en comptent plusieurs. Cette section commence par une présentation générale du fonctionnement de la gestion des événements dans les versions précédentes, puis étudie les nouveautés qu’apporte ActionScript 3.0 dans ce domaine. Gestion des événements dans les versions précédentes d’ActionScript Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Antérieurement à ActionScript 3.0, le langage ActionScript fournissait plusieurs méthodes de gestion des événements : • Les gestionnaires d’événement on(), qui peuvent se placer directement sur des occurrences Button et MovieClip • Les gestionnaires d’événement onClipEvent(), qui peuvent se placer directement sur des occurrences MovieClip • Des propriétés de fonction de rappel, telles que XML.onload et Camera.onActivity • Des écouteurs d’événement, que vous pouvez enregistrer à l’aide de la méthode addListener() • La classe UIEventDispatcher, qui implémentait partiellement le modèle d’événements DOM Chacun de ces mécanismes présente des avantages et des inconvénients. Les gestionnaires on() et onClipEvent() sont simples d’utilisation, mais compliquent la maintenance des projets car il peut s’avérer difficile de localiser le code placé directement sur les boutons ou les clips. Les fonctions de rappel sont également faciles à implémenter, mais imposent une limite d’une seule fonction de rappel par événement. L’implémentation des écouteurs d’événement est plus complexe : ils nécessitent non seulement la création d’un objet et d’une fonction d’écouteur, mais aussi l’enregistrement de l’écouteur auprès de l’objet qui génère l’événement. Bien qu’elle accroisse le temps système nécessaire, cette solution vous permet de créer plusieurs objets écouteur et de tous les enregistrer pour le même événement. Dans ActionScript 2.0, le développement des composants engendrait un modèle d’événements encore différent. Ce nouveau modèle, caractérisé par la classe UIEventDispatcher, reposait sur un sous-ensemble de la spécification d’événements DOM. Ainsi, pour les développeurs accoutumés à la gestion des événements de composant, le passage au nouveau modèle d’événements d’ActionScript 3.0 se fera sans trop de difficultés. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 132 Gestion des événements Dernière mise à jour le 27/4/2013 Malheureusement, si l’on constate des recoupements entre les divers modèles d’événements, il existe aussi des différences. Par exemple, dans ActionScript 2.0, certaines propriétés, telles que TextField.onChanged, peuvent s’utiliser soit comme fonction de rappel, soit comme écouteur d’événement. Toutefois, la syntaxe qui permet d’enregistrer les objets écouteurs varie selon que vous utilisez l’une des six classes qui prennent en charge les écouteurs ou la classe UIEventDispatcher. Pour les classes Key, Mouse, MovieClipLoader, Selection, Stage et TextField, vous utilisez la méthode addListener(), mais pour la gestion des événements de composant, vous utilisez une méthode appelée addEventListener(). La multiplicité des modèles de gestion d’événements a fait naître une autre complexité : l’étendue de la fonction de gestionnaire d’événement variait largement en fonction du mécanisme utilisé. En d’autres termes, la signification du mot-clé this n’était pas cohérente sur l’ensemble des systèmes de gestion d’événements. Gestion d’événements dans ActionScript 3.0 Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 3.0 utilise pour la première fois un modèle de gestion d’événements qui vient remplacer les nombreux mécanismes qui existaient dans les précédentes versions du langage. Le nouveau modèle d’événements repose sur la spécification d’événements de niveau 3 DOM (Document Object Model). Bien que le format de fichier SWF ne suive pas spécifiquement la norme DOM, il existe suffisamment de similitudes entre la liste d’affichage et la structure du DOM pour permettre l’implémentation de ce modèle d’événements. Un objet de la liste d’affichage est semblable à un noeud de la structure hiérarchique du DOM ; dans ce chapitre, les termes objet de liste d’affichage et noeud sont d’ailleurs utilisés de façon interchangeable. L’implémentation du modèle d’événements DOM dans Flash Player et AIR comprend un concept appelé « comportements par défaut ». Un comportement par défaut est une action que Flash Player ou AIR effectue comme conséquence normale de certains événements. Comportements par défaut Les développeurs se chargent normalement d’écrire le code qui permet de répondre aux événements. Dans certains cas, cependant, un comportement est si couramment associé à un événement que Flash Player ou AIR l’exécute automatiquement, sauf si le développeur ajoute du code pour annuler son exécution. Comme Flash Player ou AIR se livre automatiquement à cette opération, on parle de comportements par défaut. Par exemple, lorsqu’un utilisateur entre du texte dans un objet TextField, il est si courant de voir s’afficher la saisie dans l’objet TextField en question que ce comportement est prédéfini dans Flash Player ou AIR. Si vous ne souhaitez pas conserver ce comportement par défaut, vous pouvez l’annuler à l’aide du système de gestion des événements. Lorsqu’un utilisateur entre du texte dans un objet TextField, Flash Player ou AIR crée une occurrence de la classe TextEvent afin de représenter cette saisie. Pour éviter que Flash Player ou AIR n’affiche le texte dans l’objet TextField, vous devez accéder à cette occurrence de TextEvent spécifique et appeler sa méthode preventDefault(). Certains comportements par défaut ne peuvent pas être évités. Par exemple, Flash Player et AIR génèrent un objet MouseEvent lorsque l’utilisateur double-clique sur un mot dans un objet TextField. Le comportement par défaut, qui ne peut être évité, consiste à mettre en évidence le mot situé sous le curseur. De nombreux types d’objets événement ne sont associés à aucun comportement par défaut. Par exemple, l’objet événement Connect, que Flash Player distribue lorsqu’une connexion réseau est établie, n’est associé à aucun comportement par défaut. La documentation de l’API relative à la classe Event et ses sous-classes fait l’inventaire de chaque type d’événement, décrit le comportement par défaut qui lui est éventuellement associé et indique si ce dernier peut être évité. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 133 Gestion des événements Dernière mise à jour le 27/4/2013 Il est important de comprendre que les comportements par défaut sont uniquement associés à des objets événements distribués par Flash Player ou AIR ; il n’en existe aucun pour les objets événements distribués via ActionScript par programmation. Par exemple, vous pouvez utiliser les méthodes de la classe EventDispatcher pour distribuer un objet événement du type textInput, mais cet objet ne sera associé à aucun comportement par défaut. En d’autres termes, Flash Player et AIR n’affichent aucun caractère dans un objet TextField en réponse à un événement textInput que vous avez distribué par programmation. Nouveautés des écouteurs d’événement dans ActionScript 3.0 Pour les développeurs qui connaissent bien la méthode ActionScript 2.0 addListener(), il peut être utile de souligner les différences entre le modèle d’écouteur d’événement d’ActionScript 2.0 et le modèle d’événements d’ActionScript 3.0. La liste ci-après décrit les principales différences entre ces deux modèles d’événements : • Pour ajouter des écouteurs d’événement dans ActionScript 2.0, vous utilisez, selon le cas, addListener() ou addEventListener(). Dans ActionScript 3.0, il faut utiliser addEventListener() dans tous les cas. • ActionScript 2.0 ne propose aucun flux d’événements dans ActionScript 2.0, ce qui signifie que la méthode addListener() peut uniquement être appelée sur l’objet qui émet l’événement. Dans ActionScript 3.0, la méthode addEventListener() peut être appelée sur tout objet faisant partie du flux d’événements. • Dans ActionScript 2.0, les écouteurs d’événement peuvent être des fonctions, des méthodes ou des objets, alors que dans ActionScript 3.0, seules les fonctions et les méthodes peuvent agir comme écouteurs d’événement. Flux d’événements Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Flash Player ou AIR distribue des objets événements dès que survient un événement. Si la cible d’événement ne se trouve pas dans la liste d’affichage, Flash Player ou AIR distribue l’objet événement directement à la cible. Par exemple, Flash Player distribue l’objet événement Progress directement à un objet URLStream. Cependant, si la cible d’événement se trouve dans la liste d’affichage, Flash Player distribue l’objet événement à la liste d’affichage, dans laquelle l’objet chemine jusqu’à atteindre la cible d’événement. Le flux d’événements représente le parcours que suivra un objet événement dans la liste d’affichage. Cette liste s’organise de manière hiérarchique, pour constituer une arborescence. Au sommet de la liste d’affichage se trouve la scène, un conteneur d’objet d’affichage spécial qui lui sert de racine. La Scène, représentée par la classe flash.display.Stage, est uniquement accessible via un objet d’affichage. Chaque objet d’affichage présente une propriété appelée stage, qui renvoie à la scène de cette application. Lorsque Flash Player ou AIR distribue un objet d’événement pour un événement associé à une liste d’affichage, celuici effectue un aller-retour entre la Scène et le noeud cible. Selon la définition de la spécification d’événements DOM, le noeud cible est le noeud qui représente la cible d’événement. En d’autres termes, le noeud cible est l’objet de la liste d’affichage au niveau duquel est survenu l’événement. Par exemple, si l’utilisateur clique sur un objet de la liste d’affichage appelé child1, Flash Player ou AIR distribue un objet événement dont le noeud cible est child1. Le flux d’événements se décompose en trois phases. La première correspond à la phase de capture, qui comprend tous les noeuds de la Scène jusqu’au parent du noeud cible. La deuxième partie est appelée la phase cible, qui comprend uniquement le noeud cible. La troisième partie s’appelle la phase de propagation. Elle comprend les noeuds rencontrés lors du cheminement du parent du noeud cible jusqu’à la scène. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 134 Gestion des événements Dernière mise à jour le 27/4/2013 Le nom de ces phases prend tout son sens si vous envisagez la liste d’affichage comme une hiérarchie verticale dont le sommet est la Scène, comme illustré par le schéma suivant : Si un utilisateur clique sur Child1 Node, Flash Player ou AIR distribue un objet événement dans ce flux d’événements. Comme le montre l’illustration suivante, le parcours de l’objet commence à Scène. L’objet descend ensuite jusqu’à Noeud parent, puis vers Noeud enfant1. Il se propage alors vers le haut jusqu’à Scène, en repassant par Noeud parent pour rejoindre Scène. Dans cet exemple, la phase de capture comprend Scène et Noeud parent pendant le trajet descendant initial. La phase cible comprend le temps passé au noeud Noeud enfant1. La phase de propagation comprend les noeuds Noeud parent et Scène, qui se trouvent sur le chemin du retour vers le noeud racine. Le flux d’événements contribue au renforcement du système de gestion des événements par rapport aux versions précédentes d’ActionScript. Dans ces dernières, le flux d’événements est inexistant, ce qui signifie que les écouteurs d’événement s’ajoutent uniquement à l’objet qui génère l’événement. Dans ActionScript 3.0, vous pouvez ajouter des écouteurs d’événement aussi bien à un noeud cible qu’à tout autre noeud du flux d’événements. Cette possibilité d’ajouter des écouteurs d’événement tout au long du flux d’événements s’avère particulièrement utile lorsqu’un composant d’interface comprend plusieurs objets. Par exemple, un objet bouton contient souvent un objet texte qui sert de libellé au bouton. Sans la possibilité d’ajouter un écouteur au flux d’événements, il faudrait en ajouter un à l’objet bouton et un à l’objet texte pour être sûr d’être averti des événements de clic survenant à tout endroit du bouton. Le flux d’événements vous permet, au contraire, de placer un seul écouteur d’événement sur l’objet bouton afin de gérer les événements de clic, qu’ils se produisent sur l’objet texte ou sur des zones de l’objet bouton non couvertes par l’objet texte. Cependant, certains objets événements ne participent pas aux trois phases du flux d’événements. Certains types d’événements, tels que enterFrame et init, sont distribués directement au noeud cible et ne participent ni à la phase de capture, ni à la phase de propagation. D’autres événements peuvent cibler des objets qui ne font pas partie de la liste d’affichage, par exemple les événements distribués à une occurrence de la classe Socket. Ces objets événements aboutissent directement à l’objet cible, sans participer à la phase de capture et de propagation. Scène Noeud parent Noeud enfant1 Noeud enfant2 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 135 Gestion des événements Dernière mise à jour le 27/4/2013 Pour savoir comment se comporte un type d’événement particulier, vous pouvez consulter la documentation de l’API ou examiner les propriétés de l’objet événement. Cette dernière méthode est décrite à la section suivante. Objets événement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les objets événements jouent deux rôles essentiels dans le nouveau système de gestion des événements. Tout d’abord, ces objets représentent de véritables événements, puisqu’ils stockent dans un ensemble de propriétés des informations relatives à des événements précis. Ils contiennent en outre un jeu de méthodes qui vous permet de manipuler les objets événement et d’agir sur le comportement du système de gestion des événements. Pour faciliter l’accès à ces propriétés et ces méthodes, l’API Flash Player définit une classe Event qui constitue la classe de base de tous les objets événements. La classe Event définit un jeu fondamental de propriétés et de méthodes commun à tous les objets événement. Cette section commence par étudier les propriétés de la classe Event avant de décrire les méthodes de cette même classe, puis explique l’existence de sous-classes dans la classe Event. Présentation des propriétés de la classe Event Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Event définit plusieurs propriétés et constantes en lecture seule qui fournissent des informations essentielles sur l’objet événement. Les points suivants revêtent une importance particulière : • Les types d’objet événement sont représentés par des constantes et stockés dans la propriété Event.type. • La possibilité d’éviter le comportement par défaut d’un événement est représentée par une valeur booléenne, stockée dans la propriété Event.cancelable. • Les informations relatives au flux d’événements se trouvent dans les propriétés restantes. Types d’objets événement Chaque objet événement est associé à un type d’événement. Les types d’événements sont stockés dans la propriété Event.type sous forme de chaîne. Il est utile de connaître le type d’un objet événement car votre code peut alors distinguer les objets de types différents. Par exemple, le code suivant spécifie que la fonction clickHandler() doit répondre à tous les objets événements clic de souris transmis à myDisplayObject : myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler); La classe Event est elle-même associée à deux douzaines de types d’événement, représentés par des constantes de la classe Event. Dans cet extrait de la définition de la classe Event, certaines de ces constantes sont illustrées : package flash.events { public class Event { // class constants public static const ACTIVATE:String = "activate"; public static const ADDED:String= "added"; // remaining constants omitted for brevity } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 136 Gestion des événements Dernière mise à jour le 27/4/2013 Ces constantes permettent de faire facilement référence à des types d’événement précis. Vous devez utiliser ces constantes au lieu des chaînes qu’elles représentent. Si vous orthographiez de manière incorrecte un nom de constante dans votre code, le compilateur peut détecter l’erreur. Si vous utilisez les chaînes qu’elles représentent, une erreur de frappe ne sera pas forcément détectée lors de la compilation et pourrait provoquer un comportement inattendu, difficile à déboguer. Par exemple, utilisez le code suivant pour ajouter un écouteur d’événement : myDisplayObject.addEventListener(MouseEvent.CLICK, clickHandler); plutôt que : myDisplayObject.addEventListener("click", clickHandler); Informations relatives aux comportements par défaut Le code que vous écrivez est en mesure de vérifier si le comportement par défaut d’un objet événement donné peut être évité. Pour ce faire, il doit accéder à la propriété cancelable. La propriété cancelable contient une valeur booléenne qui indique si le comportement par défaut peut être évité ou non. Vous pouvez éviter, ou annuler, le comportement par défaut de quelques événements à l’aide de la méthode preventDefault(). Pour plus d’informations, voir Annulation d’un comportement associé par défaut à un événement sous « Présentation des méthodes de la classe Event » à la page 137. Informations de flux d’événements Les propriétés restantes de la classe Event contiennent des informations importantes sur l’objet événement et ses relations au flux d’événements, comme l’explique la liste suivante : • La propriété bubbles contient des informations sur les parties du flux d’événements auquel participe l’objet événement. • La propriété eventPhase indique la phase actuelle du flux d’événements. • La propriété target stocke une référence à la cible d’événement. • La propriété currentTarget stocke une référence de l’objet de liste d’affichage qui traite actuellement l’objet événement. La propriété bubbles On dit d’un événement qu’il se propage lorsqu’il participe à la phase de propagation du flux d’événements, c’est-à-dire quand l’objet événement est transmis du noeud cible via ses ascendants jusqu’à la Scène. La propriété Event.bubbles stocke une valeur booléenne qui indique si l’objet événement participe à la phase de propagation. Tous les événements qui se propagent vers le haut participent également aux phases de capture et cible ; de tels événements participent donc aux trois phases du flux d’événements. Si la valeur est true, l’objet événement participe aux trois phrases. Si la valeur est false, l’objet événement ne participe pas à la phase de propagation. La propriété eventPhase Vous pouvez déterminer la phase d’événement de tout objet événement grâce à sa propriété eventPhase. La propriété eventPhase a pour valeur un entier non signé qui représente l’une des trois phases du flux d’événements. L’API de Flash Player définit une classe EventPhase distincte qui contient trois constantes correspondant aux trois valeurs entières non signées, comme illustré par l’extrait de code suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 137 Gestion des événements Dernière mise à jour le 27/4/2013 package flash.events { public final class EventPhase { public static const CAPTURING_PHASE:uint = 1; public static const AT_TARGET:uint = 2; public static const BUBBLING_PHASE:uint= 3; } } Ces constantes correspondent aux trois valeurs valables pour la propriété eventPhase. Vous pouvez utiliser ces constantes pour améliorer la lisibilité de votre code. Supposons par exemple que vous souhaitiez être sûr qu’une fonction appelée myFunc() soit uniquement appelée lorsque la cible d’événement se trouve dans la scène cible. Le code suivant vous permet de tester cette condition : if (event.eventPhase == EventPhase.AT_TARGET) { myFunc(); } La propriété target La propriété target contient une référence à l’objet cible de l’événement. Dans certains cas, ce système est simple, par exemple, lorsqu’un micro devient actif, la cible de l’objet événement est l’objet Microphone. Toutefois, si la cible se trouve sur la liste d’affichage, il faut tenir compte de la hiérarchie de cette dernière. Par exemple, si un utilisateur clique avec la souris sur un point correspondant à plusieurs objets de la liste d’affichage qui se chevauchent, Flash Player et AIR choisissent toujours comme cible d’événement l’objet qui se trouve le plus loin de la Scène. Dans des fichiers SWF complexes, et particulièrement ceux dont les boutons sont régulièrement ornés d’objets enfant plus petits, la propriété target ne doit pas être utilisée fréquemment car elle pointera souvent vers l’objet enfant du bouton plutôt que vers le bouton lui-même. Dans de telles situations, il est courant d’ajouter des écouteurs d’événement au bouton et d’utiliser la propriété currentTarget. En effet, cette dernière pointe vers le bouton alors que la propriété target peut pointer vers l’un des enfants du bouton. La propriété currentTarget La propriété currentTarget contient une référence de l’objet de liste d’affichage qui traite actuellement l’objet événement. Même s’il peut paraître étrange de ne pas savoir quel noeud traite actuellement l’objet événement que vous étudiez, gardez à l’esprit que vous pouvez ajouter une fonction écouteur à n’importe quel objet d’affichage du flux d’événements de l’objet événement en question. En outre, cette fonction écouteur peut être placée à tout endroit. Par ailleurs, la même fonction écouteur peut être ajoutée à différents objets d’affichage. L’utilité de la propriété currentTarget augmente donc avec la taille et la complexité du projet. Présentation des méthodes de la classe Event Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Event contient trois catégories de méthodes : • Les méthodes d’utilitaire, qui peuvent créer des copies d’un objet événement ou le convertir en chaîne • Les méthodes de flux d’événements, qui suppriment les objets événements du flux d’événements • Les méthodes de comportement par défaut, qui annulent le comportement par défaut ou vérifient s’il a été annulé GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 138 Gestion des événements Dernière mise à jour le 27/4/2013 Méthodes d’utilitaire de la classe Event La classe Event compte deux méthodes d’utilitaire. La méthode clone() permet de créer des copies d’un objet événement. La méthode toString() permet de représenter sous forme de chaînes les propriétés d’un objet événement ainsi que leurs valeurs. Bien qu’utilisées en interne par le modèle d’événements, ces deux méthodes sont mises à la disposition des développeurs pour un usage générique. Pour les développeurs expérimentés qui souhaitent créer des sous-classes de la classe Event, il est nécessaire de redéfinir et d’implémenter des versions de ces deux méthodes d’utilitaires afin de garantir le bon fonctionnement de la sous-classe d’événement. Arrêt du flux d’événements La méthode Event.stopPropagation() ou Event.stopImmediatePropagation() vous permet d’arrêter le cheminement d’un objet événement dans le flux d’événements. Quasi identiques, ces deux méthodes diffèrent uniquement en ce que les autres écouteurs d’événement du noeud actuel sont autorisés ou non à s’exécuter : • La méthode Event.stopPropagation() empêche l’objet événement de passer au noeud suivant mais seulement après que tous les autres écouteurs du noeud actuel ont été autorisés à s’exécuter. • La méthode Event.stopImmediatePropagation() empêche l’objet événement de passer au noeud suivant sans autoriser les autres écouteurs du noeud actuel à s’exécuter. Quelle que soit la méthode appelée, elle n’a aucun effet sur la réalisation du comportement par défaut de l’événement. Utilisez les méthodes de comportement par défaut de la classe Event pour éviter le comportement par défaut. Annulation d’un comportement associé par défaut à un événement Deux méthodes sont associées à l’annulation du comportement par défaut : preventDefault() et isDefaultPrevented(). Appelez la méthode preventDefault() pour annuler le comportement associé par défaut à un événement. Pour vérifier si preventDefault() a déjà été appelée sur un objet événement, appelez la méthode isDefaultPrevented(), qui renvoie la valeur true si la méthode a déjà été appelée, false dans le cas contraire. La méthode preventDefault() fonctionne uniquement s’il est possible d’annuler le comportement par défaut de l’événement. Pour vérifier que c’est le cas, reportez-vous à la documentation de l’API de ce type d’événement ou examinez la propriété cancelable de l’objet événement à l’aide du code ActionScript. L’annulation du comportement par défaut n’a aucun effet sur la progression d’un objet événement dans le flux d’événements. Utilisez les méthodes de flux d’événements de la classe Event pour supprimer un objet événement du flux d’événements. Sous-classes de la classe Event Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour de nombreux événements, le jeu de propriétés commun, défini dans la classe Event est suffisant. Néanmoins, d’autres événements présentent des caractéristiques exclusives qui ne peuvent être capturées par les propriétés disponibles dans la classe Event. Pour ces événements, ActionScript 3.0 définit plusieurs sous-classes de la classe Evénement. Chaque sous-classe fournit d’autres propriétés et types d’événements propres à la catégorie d’événement considérée. Par exemple, les événements liés aux actions de la souris présentent plusieurs caractéristiques uniques, que les propriétés définies dans la classe Event ne peuvent capturer. La classe MouseEvent constitue une extension de la classe Event puisqu’elle ajoute dix propriétés contenant des informations telles que l’emplacement de l’événement de souris et les éventuelles touches actionnées en même temps. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 139 Gestion des événements Dernière mise à jour le 27/4/2013 Une sous-classe d’Event contient également des constantes qui représentent de types d’événement associés à la sousclasse. Par exemple, la classe MouseEvent définit des constantes pour plusieurs types d’événement de souris, notamment click, doubleClick, mouseDown et mouseUp. Comme le décrit la section consacrée aux méthodes d’utilitaire de la classe Event dans « Objets événement » à la page 135, lors de la création d’une sous-classe d’Event, vous devez bloquer les méthodes clone() et toString() pour fournir la fonctionnalité propre à la sous-classe. Ecouteurs d’événement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les écouteurs d’événement, également appelés gestionnaires d’événements, sont des fonctions que Flash Player et AIR exécutent en réponse à des événements déterminés. La procédure d’ajout d’un écouteur d’événement se déroule en deux temps. En premier lieu, vous créez une fonction ou méthode de classe que Flash Player ou AIR doit exécuter en réponse à l’événement. On parle parfois de fonction d’écouteur ou de fonction de gestionnaire d’événement. En second lieu, vous utilisez la méthode addEventListener() pour enregistrer la fonction d’écouteur auprès de la cible de l’événement ou tout autre objet de la liste d’affichage qui appartient au flux d’événements approprié. Création d’une fonction d’écouteur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La création d’une fonction d’écouteur est un domaine dans lequel le modèle d’événements ActionScript 3.0 diffère du modèle d’événements DOM. Dans le modèle d’événements DOM, on distingue clairement un écouteur d’événement et une fonction d’écouteur : un écouteur d’événement est une occurrence de classe qui implémente l’interface EventListener, tandis qu’une fonction d’écouteur est une méthode de cette classe appelée handleEvent(). Dans le modèle d’événements DOM, vous enregistrez l’occurrence de classe qui contient la fonction d’écouteur, plutôt que la fonction d’écouteur elle-même. Le modèle d’événements ActionScript ne fait aucune distinction entre l’écouteur d’événement et la fonction d’écouteur. L’interface EventListener est inexistante dans ActionScript 3.0 et les fonctions d’écouteur peuvent être définies en dehors de toute classe ou au sein d’une classe. Par ailleurs, il n’est pas nécessaire de nommer les fonctions d’écouteur handleEvent() ; vous pouvez utiliser tout identifiant valable. Dans ActionScript 3.0, vous enregistrez le nom de la fonction d’écouteur elle-même. Fonction d’écouteur définie en dehors de toute classe Le code suivant crée un fichier SWF simple qui affiche une forme carrée de couleur rouge. Une fonction d’écouteur appelée clickHandler(), qui n’appartient à aucune classe, écoute les événements de clic de souris dans le carré rouge. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 140 Gestion des événements Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; public class ClickExample extends Sprite { public function ClickExample() { var child:ChildSprite = new ChildSprite(); addChild(child); } } } import flash.display.Sprite; import flash.events.MouseEvent; class ChildSprite extends Sprite { public function ChildSprite() { graphics.beginFill(0xFF0000); graphics.drawRect(0,0,100,100); graphics.endFill(); addEventListener(MouseEvent.CLICK, clickHandler); } } function clickHandler(event:MouseEvent):void { trace("clickHandler detected an event of type: " + event.type); trace("the this keyword refers to: " + this); } Lorsqu’un utilisateur interagit avec le fichier SWF résultant, en cliquant sur le carré, Flash Player ou AIR génère la sortie de suivi ci-après : clickHandler detected an event of type: click the this keyword refers to: [object global] Notez que l’objet événement est transmis sous forme d’instruction à clickHandler(). Cela permet à votre fonction d’écouteur d’examiner l’objet événement. Dans cet exemple, vous utilisez la propriété type de l’objet événement pour vérifier que cet événement correspond à un clic. L’exemple vérifie aussi la valeur du mot-clé this. Dans ce cas, this représente l’objet global, ce qui est logique puisque la fonction est définie en dehors de toute classe ou objet personnalisé. Fonction d’écouteur définie comme méthode de classe L’exemple ci-dessous est identique au précédent, qui définit la classe ClickExample, sauf que la fonction clickHandler() est définie comme méthode de la classe ChildSprite : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 141 Gestion des événements Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; public class ClickExample extends Sprite { public function ClickExample() { var child:ChildSprite = new ChildSprite(); addChild(child); } } } import flash.display.Sprite; import flash.events.MouseEvent; class ChildSprite extends Sprite { public function ChildSprite() { graphics.beginFill(0xFF0000); graphics.drawRect(0,0,100,100); graphics.endFill(); addEventListener(MouseEvent.CLICK, clickHandler); } private function clickHandler(event:MouseEvent):void { trace("clickHandler detected an event of type: " + event.type); trace("the this keyword refers to: " + this); } } Lorsqu’un utilisateur interagit avec le fichier SWF résultant, en cliquant sur le carré rouge, Flash Player ou AIR génère la sortie de suivi ci-après : clickHandler detected an event of type: click the this keyword refers to: [object ChildSprite] Notez que le mot-clé this renvoie à l’occurrence de ChildSprite appelée child. Voici un changement de comportement par rapport à ActionScript 2.0. Si vous utilisiez des composants dans ActionScript 2.0, vous vous rappelez sans doute que lorsqu’une méthode de classe était transmise à UIEventDispatcher.addEventListener(), l’étendue de la méthode était liée au composant qui émettait l’événement, et non à la classe dans laquelle la méthode d’écouteur était définie. En d’autres termes, si vous utilisiez cette technique dans ActionScript 2.0, le mot-clé this renvoyait au composant émettant l’événement et non à l’occurrence de ChildSprite. Pour certains développeurs, il s’agissait d’un vrai problème car cela signifiait qu’ils ne pouvaient accéder à aucune autre méthode et propriété de la classe qui contenait la méthode d’écouteur. Pour le contourner, les programmeurs d’ActionScript 2.0 pouvaient utiliser la classe mx.util.Delegate pour modifier l’étendue de la méthode d’écouteur. Cette manipulation n’est plus nécessaire puisque ActionScript 3.0 crée une méthode liée lorsque addEventListener() est appelée. Par conséquent, le mot-clé this fait référence à l’occurrence de ChildSprite appelée child et le programmeur peut accéder aux autres méthodes et propriétés de la classe ChildSprite. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 142 Gestion des événements Dernière mise à jour le 27/4/2013 Ecouteur d’événement à ne pas utiliser Une troisième technique permet de créer un objet générique dont l’une des propriétés pointe vers une fonction d’écouteur affectée dynamiquement. Elle est cependant déconseillée. Nous l’évoquons ici en raison de son utilisation courante dans ActionScript 2.0 ; il n’est toutefois pas recommandé de l’utiliser dans ActionScript 3.0. Cette mise en garde tient au fait que le mot-clé this fera référence à l’objet global et non à l’objet écouteur. L’exemple ci-après est identique à l’exemple précédent de la classe ClickExample, sauf que la fonction d’écouteur est définie comme faisant partie d’un objet générique appelé myListenerObj : package { import flash.display.Sprite; public class ClickExample extends Sprite { public function ClickExample() { var child:ChildSprite = new ChildSprite(); addChild(child); } } } import flash.display.Sprite; import flash.events.MouseEvent; class ChildSprite extends Sprite { public function ChildSprite() { graphics.beginFill(0xFF0000); graphics.drawRect(0,0,100,100); graphics.endFill(); addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler); } } var myListenerObj:Object = new Object(); myListenerObj.clickHandler = function (event:MouseEvent):void { trace("clickHandler detected an event of type: " + event.type); trace("the this keyword refers to: " + this); } Les résultats de trace seront les suivants : clickHandler detected an event of type: click the this keyword refers to: [object global] On s’attendrait à ce que this fasse référence à myListenerObj et que la sortie de suivi soit [object Object], mais le mot-clé renvoie en fait à l’objet global. Lorsque vous transmettez un nom de propriété dynamique comme instruction à addEventListener(), Flash Player ou AIR est incapable de créer une méthode liée. En effet, ce que vous transmettez comme paramètre listener n’est rien de plus que l’adresse mémoire de votre fonction d’écouteur ; Flash Player et AIR n’ont aucun moyen de lier cette adresse à l’occurrence de myListenerObj. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 143 Gestion des événements Dernière mise à jour le 27/4/2013 Gestion des écouteurs d’événement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez gérer vos fonctions d’écouteur à l’aide des méthodes de l’interface IEventDispatcher. Cette interface est la version ActionScript 3.0 de l’interface EventTarget du modèle d’événements DOM. Bien que le nom IEventDispatcher semble impliquer que l’objet principal de la classe est l’envoi (ou la distribution) des objets événements, les méthodes qui lui correspondent servent en fait plus souvent à l’enregistrement, la vérification et la suppression des écouteurs d’événement. L’interface IEventDispatcher définit cinq méthodes, comme illustré dans le code suivant : package flash.events { public interface IEventDispatcher { function addEventListener(eventName:String, listener:Object, useCapture:Boolean=false, priority:Integer=0, useWeakReference:Boolean=false):Boolean; function removeEventListener(eventName:String, listener:Object, useCapture:Boolean=false):Boolean; function dispatchEvent(eventObject:Event):Boolean; function hasEventListener(eventName:String):Boolean; function willTrigger(eventName:String):Boolean; } } L’API de Flash Player implémente l’interface IEventDispatcher à l’aide de la classe Event Dispatcher. Cette dernière constitue la classe de base de toutes les classes pouvant servir de cibles d’événement ou faire partie d’un flux d’événements. Par exemple, la classe DisplayObject hérite de la classe EventDispatcher, par conséquent, tout objet de la liste d’affichage peut accéder aux méthodes de l’interface IEventDispatcher. Ajout des écouteurs d’événement La méthode addEventListener() est la clé de voûte de l’interface IEventDispatcher. Elle permet d’enregistrer les fonctions d’écouteurs. Les deux paramètres requis sont type et listener. Le paramètre type spécifie le type d’événement. Avec le paramètre listener, vous pouvez spécifier la fonction d’écouteur qui doit s’exécuter lorsque l’événement survient. Le paramètre listener peut être une référence à une fonction ou une méthode de classe. n’utilisez pas de parenthèses pour stipuler le paramètre listener. Par exemple, la fonction clickHandler() est spécifiée sans parenthèses dans l’appel suivant à la méthode addEventListener() : addEventListener(MouseEvent.CLICK, clickHandler) Le paramètre useCapture de la méthode addEventListener() vous permet de contrôler la phase du flux d’événements pendant laquelle votre écouteur sera actif. Si useCapture a la valeur true, votre écouteur sera actif pendant la phase de capture du flux d’événements. Si useCapture a la valeur false, votre écouteur sera actif pendant la phase cible et la phase de propagation du flux d’événements. Pour écouter un événement pendant toutes les phases du flux d’événements, vous devez appeler deux fois addEventListener() ; la première fois, useCapture prend la valeur true, la seconde fois, useCapture prend la valeur false. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 144 Gestion des événements Dernière mise à jour le 27/4/2013 Le paramètre priority de la méthode addEventListener() ne fait pas officiellement partie du modèle d’événements DOM de niveau 3. Il est inclus dans ActionScript 3.0 pour vous offrir une plus grande souplesse dans l’organisation de vos écouteurs d’événement. Lorsque vous appelez addEventListener(), vous pouvez définir la priorité de cet écouteur d’événement en transmettant une valeur entière comme paramètre priority. La valeur par défaut est 0. Vous pouvez toutefois utiliser une valeur entière négative ou positive. Plus le nombre est élevé, plus l’exécution de l’écouteur d’événement est rapide. Les écouteurs d’événement de priorité équivalente sont exécutés suivant l’ordre dans lequel ils ont été ajoutés : plus l’écouteur est ajouté tôt, plus il est exécuté rapidement. Le paramètre useWeakReference vous permet de spécifier si la référence à la fonction d’écouteur est faible ou normale. En lui attribuant la valeur true, vous évitez les situations dans lesquelles les fonctions d’écouteurs demeurent dans la mémoire alors qu’elles sont inutiles. Flash Player et AIR utilisent une technique appelée nettoyage pour effacer de la mémoire les objets qui ne servent plus. Un objet est considéré comme inutilisé lorsqu’il n’apparaît dans aucune référence. Le nettoyeur de mémoire ignore les références faibles, c’est-à-dire qu’une fonction d’écouteur vers laquelle pointe uniquement une référence faible est incluse dans le nettoyage. Suppression des écouteurs d’événement La méthode removeEventListener() permet de supprimer un écouteur d’événement dont vous n’avez plus besoin. Il est judicieux de supprimer tous les écouteurs qui ne seront plus utilisés. Les paramètres requis sont notamment eventName et listener, soit les mêmes que ceux requis pour la méthode addEventListener(). Rappel : pour écouter les événements pendant toutes les phases du flux d’événements, vous pouvez appeler addEventListener() deux fois, en attribuant à useCapture la valeur true la première, puis false la seconde. Pour supprimer les deux écouteurs d’événement, il serait nécessaire d’appeler removeEventListener() à deux reprises, la première fois en attribuant la valeur true à useCapture, la seconde fois en utilisant la valeur false. Distribution d’événements La méthode dispatchEvent() peut servir aux développeurs chevronnés pour distribuer un objet événement personnalisé dans le flux d’événements. Cette méthode accepte un seul paramètre, une référence à l’objet événement, qui doit être une occurrence de la classe Event ou de l’une de ces sous-classes. Après distribution, la propriété target de l’objet événement est définie avec l’objet sur lequel portait l’appel dispatchEvent(). Vérification des écouteurs d’événement existants Les deux dernières méthodes de l’interface IEventDispatcher fournissent des informations précieuses sur l’existence des écouteurs d’événement. La méthode hasEventListener() renvoie la valeur true si un écouteur d’événement est détecté pour un type d’événement spécifique sur un objet particulier de la liste d’affichage. La méthode willTrigger() renvoie également la valeur true si un écouteur est détecté pour un objet donné de la liste d’affichage. Cependant willTrigger() vérifie les écouteurs sur l’objet d’affichage en question mais également sur tous les ascendants de cet objet dans l’ensemble des phases du flux d’événements. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 145 Gestion des événements Dernière mise à jour le 27/4/2013 Evénements d’erreur sans écouteurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Plus que les événements, les exceptions constituent le mécanisme principal de gestion des erreurs dans ActionScript 3.0. Toutefois, la gestion des exceptions ne fonctionne pas sur les opérations asynchrones telles que les chargements de fichiers. Si une erreur survient pendant une opération asynchrone, Flash Player et AIR distribuent un objet événement d’erreur. Si vous ne créez pas d’écouteur pour l’événement d’erreur, les versions de débogage de Flash Player et AIR affichent une boîte de dialogue comportant des informations sur l’erreur en question. Par exemple, la version de débogage de Flash Player affiche la boîte de dialogue suivante, qui décrit l’erreur associée à une tentative de chargement d’un fichier par l’application à partir d’une URL non valide : La plupart des événements d’erreur reposent sur la classe ErrorEvent. Ils présentent donc une propriété appelée text, qui sert au stockage du message d’erreur que Flash Player ou AIR affiche. Il existe deux exceptions : les classes StatusEvent et NetStatusEvent. Ces deux classes possèdent une propriété level (StatusEvent.level et NetStatusEvent.info.level). Lorsque la valeur de la propriété level est error, ces types d’événement sont considérés comme des événements d’erreur. Un événement d’erreur n’interrompt pas l’exécution du fichier SWF. Il se traduit uniquement par l’affichage d’une boîte de dialogue dans les versions de débogage des navigateurs et des lecteurs autonomes, d’un message dans le panneau de sortie du lecteur de création et d’une entrée dans le fichier journal d’Adobe Flash Builder. Aucune manifestation n’est visible dans les autres versions de Flash Player ou AIR. Exemple de gestion des événements : Alarm Clock Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple Alarm Clock correspond à une horloge qui permet à l’utilisateur de déterminer l’heure à laquelle l’alarme doit se déclencher et d’afficher un message en même temps. Il repose sur l’application SimpleClock du chapitre « Utilisation des dates et des heures » à la page 1 et illustre de nombreux aspects de l’utilisation des événements dans ActionScript 3.0, notamment les suivants : • Ecoute des événements et réponse • Notification d’un événement aux écouteurs • Créer un type d’événement personnalisé GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 146 Gestion des événements Dernière mise à jour le 27/4/2013 Pour obtenir les fichiers d’application Flash Professional associés à cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Pour obtenir les fichiers d’application Flex associés à cet exemple, voir http://www.adobe.com/go/as3examples_fr. Les fichiers d’application Alarm Clock se trouvent dans le dossier Samples/AlarmClock. Il s’agit des fichiers suivants : Présentation du réveil Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans cet exemple, la principale fonctionnalité de l’horloge (dont la mesure du temps et l’affichage du cadran) réutilise le code de l’application SimpleClock, décrite à la section « Exemple de date et heure : horloge analogique simple » à la page 6. La classe AlarmClock étend la classe SimpleClock de cet exemple en y ajoutant la fonctionnalité de réveil requise : réglage de l’heure de déclenchement et avertissement une fois l’alarme déclenchée. Le rôle des événements est de fournir un avertissement lorsque se produit quelque chose. La classe AlarmClock expose l’événement Alarme, à l’écoute duquel d’autres objets peuvent être placés afin d’effectuer les actions voulues. En outre, la classe AlarmClock utilise une occurrence de la classe Timer pour déterminer à quel moment déclencher l’alarme. Comme la classe AlarmClock, la classe Timer fournit un événement pour avertir d’autres objets (une occurrence de AlarmClock dans ce cas) une fois un certain délai écoulé. Comme dans la plupart des applications ActionScript, les événements constituent une part importante de la fonctionnalité de l’exemple Alarm Clock. Déclenchement de l’alarme Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Comme mentionné plus haut, la seule fonctionnalité de la classe AlarmClock est liée à la définition et au déclenchement de l’alarme. La classe intégrée Timer (flash.utils.Timer) permet au développeur de définir du code qui sera exécuté après un délai spécifique. La classe AlarmClock utilise une occurrence de Timer pour déterminer le moment auquel déclencher l’alarme. Fichier Description AlarmClockApp.mxml ou AlarmClockApp.fla Fichier d’application principal dans Flash (FLA) ou Flex (MXML). com/example/programmingas3/clock/AlarmClock.as Classe permettant d’étendre la classe SimpleClock, qui ajoute la fonctionnalité de réveil. com/example/programmingas3/clock/AlarmEvent.as Une classe d’événement personnalisé (sous-classe de flash.events.Event), qui sert d’objet événement à l’événement alarm de la classe AlarmClock. com/example/programmingas3/clock/AnalogClockFace.as Dessine une horloge ronde et les aiguilles des heures, des minutes et des secondes en fonction de l’heure (décrit dans l’exemple SimpleClock). com/example/programmingas3/clock/SimpleClock.as Composant d’interface d’horloge doté d’une fonctionnalité simple de mesure temporelle (décrit dans l’exemple SimpleClock). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 147 Gestion des événements Dernière mise à jour le 27/4/2013 import flash.events.TimerEvent; import flash.utils.Timer; /** * The Timer that will be used for the alarm. */ public var alarmTimer:Timer; ... /** * Instantiates a new AlarmClock of a given size. */ public override function initClock(faceSize:Number = 200):void { super.initClock(faceSize); alarmTimer = new Timer(0, 1); alarmTimer.addEventListener(TimerEvent.TIMER, onAlarm); } L’occurrence de Timer définie dans la classe AlarmClock est appelée alarmTimer. La méthode initClock(), qui effectue les opérations de configuration nécessaires à l’occurrence de AlarmClock, exploite la variable alarmTimer de deux manières. Tout d’abord, la variable est instanciée avec les paramètres indiquant à l’occurrence de Timer d’attendre 0 milliseconde et de déclencher l’événement timer une seule fois. Après instanciation de alarmTimer, le code appelle la méthode addEventListener() de cette variable pour indiquer qu’il veut écouter l’événement timer de cette variable. Le fonctionnement d’une occurrence de Timer repose sur la distribution de l’événement timer après un certain délai. La classe AlarmClock doit savoir quand l’événement timer est distribué afin de déclencher sa propre alarme. En appelant addEventListener(), le code AlarmClock s’enregistre comme écouteur auprès de alarmTimer. Les deux paramètres indiquent que la classe AlarmClock souhaite écouter l’événement timer (indiqué par la constante TimerEvent.TIMER), et que lorsque l’événement survient, la méthode onAlarm() de la classe AlarmClock doit être appelée en réponse à l’événement. Pour effectivement définir l’alarme, la méthode setAlarm() de la classe AlarmClock est appelée, comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 148 Gestion des événements Dernière mise à jour le 27/4/2013 /** * Sets the time at which the alarm should go off. * @param hour The hour portion of the alarm time. * @param minutes The minutes portion of the alarm time. * @param message The message to display when the alarm goes off. * @return The time at which the alarm will go off. */ public function setAlarm(hour:Number = 0, minutes:Number = 0, message:String = "Alarm!"):Date { this.alarmMessage = message; var now:Date = new Date(); // Create this time on today's date. alarmTime = new Date(now.fullYear, now.month, now.date, hour, minutes); // Determine if the specified time has already passed today. if (alarmTime <= now) { alarmTime.setTime(alarmTime.time + MILLISECONDS_PER_DAY); } // Stop the alarm timer if it's currently set. alarmTimer.reset(); // Calculate how many milliseconds should pass before the alarm should // go off (the difference between the alarm time and now) and set that // value as the delay for the alarm timer. alarmTimer.delay = Math.max(1000, alarmTime.time - now.time); alarmTimer.start(); return alarmTime; } Cette méthode effectue plusieurs opérations, notamment le stockage du message d’alarme et la création d’un objet Date (alarmTime) représentant le moment réel où l’alarme se déclenchera. Point le plus important de cette étude, le minuteur de la variable alarmTimer, dans les dernières lignes la méthode, est défini et activé. Tout d’abord, la méthode reset() est appelée, qui arrête le minuteur et le remet à zéro s’il est déjà reparti. Ensuite, l’heure actuelle (représentée par la variable now) est soustraite à la valeur de la variable alarmTime afin de déterminer combien de millisecondes doivent s’écouler avant le déclenchement de l’alarme. La classe Timer ne déclenche pas l’événement timer à une heure absolue ; c’est ce décalage relatif qui est attribué à la propriété delay d’alarmTimer. Enfin, la méthode start() est appelée pour lancer le minuteur. Une fois le délai spécifié écoulé, alarmTimer distribue l’événement timer. Comme la classe AlarmClock s’est enregistrée comme écouteur auprès de sa méthode onAlarm() pour l’événement timer, lorsque celui-ci survient, onAlarm() est appelée. /** * Called when the timer event is dispatched. */ public function onAlarm(event:TimerEvent):void { trace("Alarm!"); var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage); this.dispatchEvent(alarm); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 149 Gestion des événements Dernière mise à jour le 27/4/2013 Lorsqu’une méthode est enregistrée comme écouteur d’événement, elle doit être définie avec la signature adaptée (c’est-à-dire le jeu de paramètres et le type de renvoi de la méthode). Pour écouter l’événement timer de la classe Timer, une méthode doit comporter un paramètre dont le type de données est TimerEvent (flash.event.TimerEvent), une sous-classe de la classe Event. Lorsque l’occurrence de Timer appelle ses écouteurs d’événement, elle transmet une occurrence de TimerEvent à l’objet événement. Notification de l’alarme à d’autres composants Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures De même que la classe Timer, la classe AlarmClock fournit un événement qui permet de transmettre des notifications à d’autres éléments de code lorsque l’alarme se déclenche. Pour qu’une classe puisse utiliser le système de gestion des événements intégré à ActionScript, elle doit implémenter l’interface flash.events.IEventDispatcher. La plupart du temps, cela se fait par extension de la classe flash.events.EventDispatcher, qui assure une implémentation standard de IEventDispatcher (ou par extension de l’une des sous-classes de EventDispatcher). Comme décrit précédemment, la classe AlarmClock étend la classe SimpleClock, qui (par le biais d’une chaîne d’héritage) étend la classe EventDispatcher. Ainsi, la classe AlarmClock intègre déjà une fonctionnalité lui permettant de fournir ses propres événements. D’autres éléments de code peuvent s’enregistrer pour être notifiés de l’événement alarm de la classe AlarmClock en appelant la méthode addEventListener(), héritée de EventDispatcher. Lorsqu’une occurrence de AlarmClock est prête à notifier à d’autres éléments de code le déclenchement de l’événement alarm, elle le fait en appelant la méthode dispatchEvent(), également héritée de EventDispatcher. var alarm:AlarmEvent = new AlarmEvent(this.alarmMessage); this.dispatchEvent(alarm); Ces lignes de code sont extraites de la méthode onAlarm() de la classe AlarmClock (présentée plus haut dans son intégralité). La méthode dispatchEvent() de l’occurrence de AlarmClock est appelée, puis elle notifie à tous les écouteurs enregistrés le déclenchement de l’événement alarm de l’occurrence de AlarmClock. Le paramètre transmis à dispatchEvent() est l’objet événement qui sera ensuite passé aux méthodes d’écouteur. Dans ce cas, il s’agit d’une occurrence de la classe AlarmEvent, une sous-classe de Event créée spécialement pour cet exemple. Elaboration d’un événement d’alarme personnalisé Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Tous les écouteurs d’événement reçoivent un paramètre d’objet événement avec des informations sur l’événement qui a été déclenché. Dans bien des cas, l’objet événement est une occurrence de la classe Event. Dans d’autres cas néanmoins, il s’avère utile de fournir des informations complémentaires aux écouteurs d’événement. Il suffit pour cela de définir une nouvelle classe, sous-classe de la classe Event, et d’utiliser une occurrence de cette classe comme objet événement. Dans cet exemple, une occurrence de AlarmEvent est utilisée comme objet événement lorsque l’événement alarm de la classe AlarmClock est distribué. La classe AlarmEvent, présentée ici, fournit des informations complémentaires sur l’événement alarm, à savoir le message d’alarme : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 150 Gestion des événements Dernière mise à jour le 27/4/2013 import flash.events.Event; /** * This custom Event class adds a message property to a basic Event. */ public class AlarmEvent extends Event { /** * The name of the new AlarmEvent type. */ public static const ALARM:String = "alarm"; /** * A text message that can be passed to an event handler * with this event object. */ public var message:String; /** *Constructor. *@param message The text to display when the alarm goes off. */ public function AlarmEvent(message:String = "ALARM!") { super(ALARM); this.message = message; } ... } Le meilleur moyen de créer une classe d’objet événement personnalisée est de définir une classe qui étend la classEvent, comme illustré dans l’exemple précédent. Pour compléter la fonctionnalité héritée, la classe AlarmEvent définit une propriété message qui contient le texte du message d’alarme associé à l’événement. La valeur message est transmise sous forme de paramètre au constructeur AlarmEvent. La classe AlarmEvent définit également la constante ALARM qui peut servir à référencer l’événement (alarm) lors de l’appel de la méthode addEventListener() de la classe AlarmClock. Outre l’ajout de fonctionnalité, chaque sous-classe Event doit redéfinir la méthode clone() héritée dans le cadre de la gestion des événements ActionScript. Les sous-classes Event peuvent éventuellement redéfinir la méthode toString() afin d’inclure les propriétés de l’événement personnalisé dans la valeur renvoyée par l’appel de la méthode toString(). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 151 Gestion des événements Dernière mise à jour le 27/4/2013 /** * Creates and returns a copy of the current instance. * @return A copy of the current instance. */ public override function clone():Event { return new AlarmEvent(message); } /** * Returns a String containing all the properties of the current * instance. * @return A string representation of the current instance. */ public override function toString():String { return formatToString("AlarmEvent", "type", "bubbles", "cancelable", "eventPhase", "message"); } La méthode clone() redéfinie doit renvoyer une nouvelle occurrence de la sous-classe Event personnalisée, avec toutes les propriétés personnalisées définies pour correspondre à l’occurrence actuelle. Dans la méthode toString() redéfinie, la méthode d’utilitaire formatToString() (héritée de Event) sert à fournir une chaîne comportant le nom du type personnalisé, ainsi que les noms et valeurs de toutes ses propriétés. 152 Dernière mise à jour le 27/4/2013 Chapitre 9 : Utilisation de domaines d’application Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le rôle de la classe ApplicationDomain est de stocker un tableau des définitions ActionScript 3.0. L’ensemble du code d’un fichier SWF est défini de sorte à exister dans un domaine d’application. Les domaines d’application servent à partitionner les classes qui se trouvent dans un même domaine de sécurité. Ainsi, plusieurs définitions de la même classe peuvent exister et les enfants peuvent réutiliser les définitions des parents. Vous pouvez faire appel aux domaines d’application lors du chargement, au moyen de l’API de la classe Loader, d’un fichier SWF externe écrit en ActionScript 3.0 (Notez que vous ne pouvez pas utiliser les domaines d’application lorsque vous chargez une image ou un fichier SWF écrit en ActionScript 1.0 ou 2.0.) Toutes les définitions ActionScript 3.0 contenues dans la classe chargée sont stockées dans le domaine d’application. Lorsque vous chargez un fichier SWF, vous devez indiquer que le fichier doit être inclus dans le même domaine d’application que l’objet Loader en attribuant au paramètre applicationDomain de l’objet LoaderContext la valeur ApplicationDomain.currentDomain. Si vous placez le fichier SWF chargé dans le même domaine d’application, vous pourrez accéder directement à ses classes, Cela s’avère pratique si vous chargez un fichier SWF qui contient des médias incorporés auxquels vous pouvez accéder via les noms de classe associés, ou si vous voulez accéder aux méthodes du fichier SWF chargé. L’exemple suivant présuppose l’accès à un fichier Greeter.swf distinct définissant une méthode publique nommée welcome() : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 153 Utilisation de domaines d’application Dernière mise à jour le 27/4/2013 package { import flash.display.Loader; import flash.display.Sprite; import flash.events.*; import flash.net.URLRequest; import flash.system.ApplicationDomain; import flash.system.LoaderContext; public class ApplicationDomainExample extends Sprite { private var ldr:Loader; public function ApplicationDomainExample() { ldr = new Loader(); var req:URLRequest = new URLRequest("Greeter.swf"); var ldrContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain); ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler); ldr.load(req, ldrContext); } private function completeHandler(event:Event):void { var myGreeter:Class = ApplicationDomain.currentDomain.getDefinition("Greeter") as Class; var myGreeter:Greeter = Greeter(event.target.content); var message:String = myGreeter.welcome("Tommy"); trace(message); // Hello, Tommy } } } Voir aussi l’exemple de classe ApplicationDomain dans le manuel Guide de référence ActionScript 3.0 pour la plateforme Adobe Flash. Voici d’autres points à garder à l’esprit lorsque vous utilisez les domaines d’application : • L’ensemble du code d’un fichier SWF est défini de sorte à exister dans un domaine d’application. L’application principale s’exécute dans le domaine d’application actif. Le domaine du système contient tous les domaines d’application, y compris le domaine actif ; il contient donc toutes les classes Flash Player. • A l’exception du domaine du système, tous les domaines d’application sont associés à un domaine parent. Le domaine parent du domaine de l’application principale est le domaine du système. Les classes chargées ne sont définies que si leur parent ne les définit pas encore. Vous ne pouvez pas remplacer une définition de classe chargée par une définition plus récente. Le schéma suivant illustre une application qui charge du contenu à partir de divers fichiers SWF au sein d’un domaine unique, domain1.com. Selon le contenu chargé, différents domaines d’application peuvent être utilisés. Le texte suivant décrit la logique utilisée pour définir le domaine d’application approprié pour chaque fichier SWF de l’application. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 154 Utilisation de domaines d’application Dernière mise à jour le 27/4/2013 A. Utilisation A B. Utilisation B C. Utilisation C Le fichier principal d’application est application1.swf. Il contient des objets Loader qui chargent du contenu à partir d’autres fichiers SWF. Dans ce scénario, le domaine d’application 1 est actif. Utilisation A, Utilisation B et Utilisation C illustrent les différentes techniques permettant de définir le domaine d’application approprié pour chaque fichier SWF de l’application. Utilisation A Partitionnez le fichier SWF enfant en créant un enfant du domaine du système. Dans le schéma, le domaine d’application 2 est créé en tant qu’enfant du domaine du système. Le fichier application2.swf est chargé dans le domaine d’application 2 et ses définitions de classe sont ainsi partitionnées à partir des classes définies dans application1.swf. Cette technique s’appliquera par exemple lorsqu’une ancienne application doit charger dynamiquement une nouvelle version de la même application sans créer de conflits. Les conflits sont éliminés parce que même si les noms de classe sont les mêmes, ils sont répartis dans différents domaines d’application. Le code suivant crée un domaine d’application qui est un enfant du domaine du système, puis commence à charger un fichier SWF à l’aide de ce domaine d’application : var appDomainA:ApplicationDomain = new ApplicationDomain(); var contextA:LoaderContext = new LoaderContext(false, appDomainA); var loaderA:Loader = new Loader(); loaderA.load(new URLRequest("application2.swf"), contextA); Utilisation B Ajoutez de nouvelles définitions de classe aux définitions actuelles. Le domaine d’application de module1.swf est défini sur le domaine actif (Domaine d’application 1). Vous pouvez alors ajouter au jeu actuel de définitions de classe de l’application de nouvelles définitions de classe. Cela pourrait servir pour une bibliothèque d’exécution partagée appartenant à l’application principale. Le fichier SWF est traité comme une bibliothèque partagée distante (RSL, remote shared library). Utilisez cette technique pour charger des RSL à l’aide d’un fichier de préchargement avant le lancement de l’application. Le code suivant charge un fichier SWF, en définissant son domaine d’application sur le domaine actif : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 155 Utilisation de domaines d’application Dernière mise à jour le 27/4/2013 var appDomainB:ApplicationDomain = ApplicationDomain.currentDomain; var contextB:LoaderContext = new LoaderContext(false, appDomainB); var loaderB:Loader = new Loader(); loaderB.load(new URLRequest("module1.swf"), contextB); Utilisation C Utilisez les définitions de classe du parent en ajoutant un nouveau domaine enfant au domaine actif. Le domaine d’application de module3.swf est un enfant du domaine actif, qui utilise pour toutes les classes les versions du parent. Cette technique peut s’appliquer à un module d’une application Internet riche (RIA, Rich Internet Application) à plusieurs écrans, qui serait chargé comme enfant de l’application principale et utiliserait les types de cette dernière. Si vous pouvez garantir que toutes les classes sont toujours mises à jour pour rester compatibles avec les anciennes versions et que l’application de chargement est toujours plus récente que les contenus qu’elle charge, les enfants utiliseront les versions des parents. L’utilisation d’un nouveau domaine d’application permet également de décharger toutes les définitions de classe en vue du nettoyage, à condition de veiller à ce qu’il ne subsiste aucune référence au fichier SWF enfant. Cette technique autorise les modules chargés à partager les objets Singleton et les membres de classe statiques de l’objet Loader. Le code suivant crée un domaine enfant dans le domaine actif et commence à charger un fichier SWF à l’aide de ce domaine d’application : var appDomainC:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain); var contextC:LoaderContext = new LoaderContext(false, appDomainC); var loaderC:Loader = new Loader(); loaderC.load(new URLRequest("module3.swf"), contextC); 156 Dernière mise à jour le 27/4/2013 Chapitre 10 : Programmation de l’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La programmation des éléments visuels dans Adobe® ActionScript® 3.0 repose sur l’utilisation des objets d’affichage sur la scène. Vous pouvez, par exemple, ajouter, déplacer, supprimer et trier les objets d’affichage, appliquer des filtres et des masques, dessiner des vecteurs et des graphiques bitmap, et exécuter des transformations en trois dimensions par le biais de l’API de programmation de l’affichage ActionScript. Les classes principales permettant de programmer l’affichage font partie du package flash.display. Remarque : Adobe® AIR™ fournit l’objet HTMLoader pour rendre et afficher un contenu HTML. L’objet HTMLLoader effectue le rendu des éléments visuels du DOM HTML en tant qu’objet d’affichage unique. Il est impossible d’accéder directement à chaque élément du DOM par le biais de la hiérarchie de la liste d’affichage ActionScript. Vous accédez aux éléments du DOM à l’aide de l’API DOM distincte proposée par l’objet HTMLLoader. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 157 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Concepts fondamentaux de la programmation de l’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Chaque application créée par le biais d’ActionScript 3.0 possède une hiérarchie d’objets d’affichage appelée liste d’affichage, comme l’indique l’illustration ci-dessous. La liste d’affichage contient tous les éléments visibles de l’application. Comme le montre cette illustration, les éléments d’affichage se rangent dans un ou plusieurs groupes suivants : • Scène La scène constitue le conteneur de base des objets d’affichage. Chaque application comporte un objet Stage, qui contient tous les objets d’affichage à l’écran. La scène correspond au conteneur de plus haut niveau et domine la hiérarchie de la liste d’affichage : Chaque fichier SWF est associé à une classe ActionScript, appelée classe principale du fichier SWF. Lorsqu’un fichier SWF s’ouvre dans Flash Player ou Adobe AIR, Flash Player ou AIR appelle la fonction constructeur correspondant à la classe et l’occurrence créée (systématiquement un type d’objet d’affichage) est ajoutée en tant qu’enfant de l’objet Stage. La classe principale d’un fichier SWF étend systématiquement la classe Sprite (pour plus d’informations, voir « Avantages de l’utilisation de la liste d’affichage » à la page 162). Vous pouvez accéder à la scène via la propriété stage de toute occurrence de DisplayObject. Pour plus d’informations, voir « Définition des propriétés de la scène » à la page 171. • Objets d’affichage GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 158 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Dans ActionScript 3.0, tous les éléments qui apparaissent à l’écran dans une application sont des types d’objets d’affichage. Le package flash.display comprend une classe DisplayObject, qui correspond à une classe de base étendue par diverses autres classes. Ces autres classes représentent divers types d’objets d’affichage, tels que les formes vectorielles, les clips et les champs de texte, pour n’en citer que quelques-uns. Pour une présentation de ces classes, voir « Avantages de l’utilisation de la liste d’affichage » à la page 162. • Conteneurs d’objets d’affichage Les conteneurs d’objets d’affichage sont des types spéciaux d’objets d’affichage qui, outre leur propre représentation visuelle, peuvent également comporter des objets enfant qui sont aussi des objets d’affichage. La classe DisplayObjectContainer est une sous-classe de la classe DisplayObject. Un objet DisplayObjectContainer peut contenir plusieurs objets d’affichage dans la liste d’enfants correspondante. Par exemple, l’illustration suivante contient un type d’objet DisplayObjectContainer appelé Sprite qui comporte divers objets d’affichage : A. Objet SimpleButton. Ce type d’objet d’affichage possède des états « up », « down » et « over ». B. Objet Bitmap. Dans ce cas de figure, l’objet Bitmap a été chargé à partir d’un JPEG externe via un objet Loader. C. Objet Shape. Le « cadre d’image » contient un rectangle arrondi dessiné dans ActionScript. Un filtre Ombre portée est appliqué à cet objet Shape. D. Objet TextField. Dans le contexte des objets d’affichage, les objets DisplayObjectContainer portent également le nom de conteneurs d’objets d’affichage voire, tout simplement, de conteneurs. Comme indiqué précédemment, la scène est un conteneur d’objets d’affichage. Bien que tous les objets d’affichage visibles héritent leurs caractéristiques de la classe DisplayObject, le type de chacun d’eux correspond à une sous-classe déterminée de la classe DisplayObject. Il existe, par exemple, une fonction constructeur associée à la classe Shape ou à la classe Video, mais aucune fonction constructeur pour la classe DisplayObject. Concepts importants et terminologie La liste de référence suivante contient des termes importants utilisés dans le cadre de la programmation des graphiques ActionScript : Alpha Valeur colorimétrique représentant le montant de transparence (ou, plus précisément, le montant d’opacité) d’une couleur. Ainsi, une couleur dotée d’une valeur de canal alpha de 60 % n’affiche que 60 % de son intensité totale et est transparente à 40 %. Graphique bitmap Graphique défini en termes informatiques sous forme de grille (lignes et colonnes) de pixels de couleur. Les exemples courants de graphiques bitmap incluent les photos numériques et images similaires. A B C D GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 159 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Mode de fondu Indique l’interaction requise du contenu de deux images qui se chevauchent. En règle générale, une image opaque superposée à une autre image se contente de bloquer l’image placée sous elle, qui est donc totalement invisible. Toutefois, divers modes de fondu entraînent le mélange des couleurs de diverses façons de sorte que le résultat corresponde à une combinaison des deux images. Liste d’affichage Hiérarchie des objets d’affichage rendus sous forme de contenu visible à l’écran par Flash Player et AIR. La scène correspond à la racine de la liste d’affichage et tous les objets d’affichage associés à la scène ou à l’un de ses enfants composent la liste d’affichage (même si l’objet n’est pas à proprement parler rendu, parce qu’il réside en dehors de la scène, par exemple). Objet d’affichage Objet représentant un type de contenu visuel dans Flash Player ou AIR. La liste d’affichage ne contient que des objets d’affichage et toutes les classes d’objets d’affichage sont des sous-classes de la classe DisplayObject. Conteneur d’objet d’affichage Type spécial d’objet d’affichage qui, outre (généralement) sa propre représentation visuelle, peut comporter des objets d’affichage enfant. Classe principale du fichier SWF Classe qui définit le comportement de l’objet d’affichage de plus haut niveau d’un fichier SWF, soit, fondamentalement, la classe associée au fichier SWF en tant que tel. Ainsi, dans un fichier SWF généré dans un outil de création Flash, la classe principale correspond à la classe du document. Elle possède un « scénario principal » qui intègre tous les autres scénarios. La classe principale du fichier SWF correspond à la classe dont le scénario principal est une occurrence. Masquage Technique consistant à ne pas afficher certaines parties d’une image (ou, à l’inverse, à n’afficher que certaines parties d’une image). Les sections de l’image masque deviennent transparentes, afin d’assurer la visibilité du contenu sous-jacent. Ce terme se réfère à la bande utilisée par un peintre en bâtiment pour empêcher la peinture d’être appliquée à certaines sections. Scène Conteneur visuel correspondant à la base ou à l’arrière-plan de tout contenu visuel dans un fichier SWF. Transformation Modification des caractéristiques visuelles d’un graphique (rotation de l’objet, modification de son échelle, désalignement, déformation ou altération de sa couleur). Graphique vectoriel Graphique défini en termes informatiques par des lignes et des formes dessinées en fonction de caractéristiques déterminées (épaisseur, longueur, taille, angle et position, par exemple). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 160 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Classes d’affichage de base Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le package flash.display ActionScript 3.0 contient des classes destinées aux objets visuels susceptibles d’apparaître dans Flash Player ou AIR. L’illustration suivante identifie les relations entre les sous-classes de ces classes d’objets d’affichage de base. L’illustration indique ce dont héritent les classes d’objets d’affichage. Notez que certaines de ces classes, en particulier StaticText, TextField et Video, ne figurent pas dans le package flash.display, mais héritent toutefois des caractéristiques de la classe DisplayObject. Toutes les classes qui étendent la classe DisplayObject héritent de ses méthodes et propriétés. Pour plus d’informations, voir « Propriétés et méthodes de la classe DisplayObject » à la page 165. Vous pouvez créer une occurrence d’un objet des classes suivantes, qui figurent dans le package flash.display : • Bitmap : la classe Bitmap permet de définir des objets bitmap, qu’ils soient chargés à partir de fichiers externes ou rendus via ActionScript. Vous pouvez charger des bitmaps à partir de fichiers externes par le biais de la classe Loader. Libre à vous de charger des fichiers GIF, JPG ou PNG. Vous pouvez également créer un objet BitmapData à partir de données personnalisées, puis créer un objet Bitmap qui utilise ces données. Les méthodes de la classe BitmapData permettent de modifier les bitmaps, qu’ils soient chargés ou créés dans ActionScript. Pour plus d’informations, voir « Chargement d’objets d’affichage » à la page 206 et le chapitre « Utilisation des images bitmap » à la page 251. • Loader : la classe Loader permet de charger des ressources externes (fichiers SWF ou graphiques). Pour plus d’informations, voir « Chargement dynamique du contenu d’affichage » à la page 205. • Shape : la classe Shape permet de créer des graphiques vectoriels, tels que des rectangles, des lignes, des cercles, etc. Pour plus d’informations, voir « Utilisation de l’API de dessin » à la page 230. • SimpleButton : un objet SimpleButton est une représentation ActionScript d’un symbole de bouton créé dans l’outil de programmation Flash. Une occurrence de SimpleButton est dotée de quatre états de bouton : « up », « down », « over » et « hit test » (zone qui réagit aux événements souris et clavier). MorphShape DisplayObject AVM1Movie Shape StaticText Video DisplayObjectContainer TextField Bitmap InteractiveObject SimpleButton Loader Stage MovieClip Sprite GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 161 Programmation de l’affichage Dernière mise à jour le 27/4/2013 • Sprite : un objet Sprite peut contenir des graphiques qui lui sont propres, ainsi que des objets d’affichage enfant (la classe Sprite étend la classe DisplayObjectContainer). Pour plus d’informations, voir « Utilisation de conteneurs d’objets d’affichage » à la page 165 et « Utilisation de l’API de dessin » à la page 230. • MovieClip : un objet MovieClip est la forme ActionScript d’un symbole de clip créé dans l’outil de programmation Flash. En pratique, un objet MovieClip est similaire à un objet Sprite, à une exception près : il possède également un scénario. Pour plus d’informations, voir « Utilisation des clips » à la page 333. Les classes suivantes, qui ne figurent pas dans le package flash.display, sont des sous-classes de la classe DisplayObject : • La classe TextField, qui figure dans le package flash.text, est un objet d’affichage destiné à l’affichage et à la saisie de texte. Pour plus d’informations, voir « Principes de base de l’utilisation du texte » à la page 383. • La classe TextLine, qui figure dans le package flash.text.engine, correspond à l’objet d’affichage permettant d’afficher des lignes de texte composées par Flash Text Engine et Text Layout Framework. Pour plus d’informations, voir « Utilisation de Flash Text Engine » à la page 410 et « Utilisation de Text Layout Framework » à la page 440. • La classe Video, qui figure dans le package flash.media, correspond à l’objet d’affichage utilisé pour afficher des fichiers vidéo. Pour plus d’informations, voir « Utilisation de la vidéo » à la page 489. Les classes suivantes du package flash.display étendent la classe DisplayObject, mais il est impossible d’en créer une occurrence. Parce qu’elles combinent des fonctionnalités communes en une classe unique, elles servent plutôt de classes parent à d’autres objets d’affichage. • AVM1Movie : la classe AVM1Movie permet de représenter des fichiers SWF chargés créés dans ActionScript 1.0 et 2.0. • DisplayObjectContainer : les classes Loader, Stage, Sprite et MovieClip étendent chacune la classe DisplayObjectContainer. Pour plus d’informations, voir « Utilisation de conteneurs d’objets d’affichage » à la page 165. • InteractiveObject : classe de base de tous les objets utilisés pour interagir avec la souris et le clavier. Les objets SimpleButton, TextField, Loader, Sprite, Stage et MovieClip sont tous des sous-classes de la classe InteractiveObject. Pour plus d’informations sur la création d'une interaction de souris ou de clavier, voir « Principes de base de l’interaction utilisateur » à la page 574. • MorphShape : ces objets sont générés lors de la création d’une interpolation de forme dans l’outil de programmation Flash. Il est impossible d’en créer des occurrences par le biais d’ActionScript, mais vous pouvez y accéder dans la liste d’affichage. • Scène : la classe Stage étend la classe DisplayObjectContainer. Il n’existe qu’une seule occurrence de scène par application, et elle figure au sommet de la hiérarchie de la liste d’affichage. Vous pouvez accéder à la scène via la propriété stage de toute occurrence de DisplayObject. Pour plus d’informations, voir « Définition des propriétés de la scène » à la page 171. Par ailleurs, la classe StaticText, qui figure dans le package flash.text, étend la classe DisplayObject, mais il est impossible d’en créer une occurrence dans du code. Les champs de texte statique sont créés dans Flash uniquement. Les classes suivantes ne sont ni des objets d’affichage, ni des conteneurs d’objets d’affichage et n’apparaissent pas dans la liste d’affichage, mais affichent des graphiques sur la scène. Elles dessinent des éléments dans un rectangle, appelé fenêtre d’affichage, positionné relativement à la scène. • StageVideo : la classe StageVideo affiche le contenu vidéo en faisant appel, dans la mesure du possible, à l’accélération matérielle. Cette classe est disponible à partir de Flash Player 10.2. Pour plus d’informations, voir « Présentation à accélération matérielle par le biais de la classe StageVideo » à la page 528. • StageWebView : la classe StageWebView affiche le contenu HTML. Elle est prise en charge depuis la version 2.5 d’AIR. Pour plus d’informations, voir « Objets StageWebView » à la page 1068. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 162 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Les classes fl.display suivantes proposent des fonctionnalités équivalentes à celles des classes flash.display.Loader et LoaderInfo. Utilisez-les au lieu des classes flash.display équivalentes en cas de développement dans l’environnement Flash Professional (CS5.5 ou ultérieur). Dans cet environnement, ces classes permettent de résoudre les problèmes liés à TLF avec préchargement RSL. Pour plus d’informations, voir « Utilisation des classes ProLoader et ProLoaderInfo » à la page 210. • fl.display.ProLoader : équivalente à flash.display.Loader • fl.display.ProLoaderInfo : équivalente à flash.display.LoaderInfo Avantages de l’utilisation de la liste d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans ActionScript 3.0, des classes distinctes sont réservées aux différents types d’objets d’affichage. Dans ActionScript 1.0 et 2.0, un grand nombre de types d’objets identiques sont inclus dans une même classe : MovieClip. Cette individualisation des classes et la structure hiérarchique des listes d’affichage présentent les avantages suivants : • Rendu plus efficace et utilisation réduite de la mémoire • Gestion optimisée de la profondeur • Parcours entier de la liste d’affichage • Objets d’affichage absents de la liste • Classement simplifié en sous-classes des objets d’affichage Rendu plus efficace et taille réduite des fichiers Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans ActionScript 1.0 et 2.0, vous ne pouvez dessiner des formes que dans un objet MovieClip. ActionScript 3.0 intègre des classes d’objets d’affichage plus simples, dans lesquelles vous pouvez dessiner des formes. Parce que ces classes d’objets d’affichage ActionScript 3.0 ne contiennent pas le jeu complet de méthodes et propriétés associées à un objet MovieClip, elles mobilisent moins de ressources en mémoire et processeur. Par exemple, à l’encontre d’un objet Shape, chaque objet MovieClip comporte des propriétés associées au scénario du clip. Les propriétés de gestion du scénario font parfois appel à un volume considérable de ressources en mémoire et processeur. Dans ActionScript 3.0, l’utilisation de l’objet Shape se traduit par une amélioration des performances. L’objet Shape nécessite moins de ressources que l’objet MovieClip, plus complexe. Flash Player et AIR n’ont pas besoin de gérer les propriétés MovieClip inutilisées, optimisant ainsi la vitesse et réduisant les besoins de mémoire de l’objet. Gestion optimisée de la profondeur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans ActionScript 1.0 et 2.0, la profondeur était gérée par un système et des méthodes de gestion linéaire de la profondeur, tels que getNextHighestDepth(). ActionScript 3.0 comprend la classe DisplayObjectContainer, dont les méthodes et propriétés sont mieux adaptées à la gestion de la profondeur des objets d’affichage. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 163 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Dans ActionScript 3.0, lorsque vous déplacez un objet d’affichage au sein de la liste des enfants d’une occurrence de DisplayObjectContainer, les autres enfants du conteneur d’objets d’affichage sont automatiquement repositionnés et des positions d’index enfant appropriées leur sont affectées dans le conteneur d’objets d’affichage. Par ailleurs, ActionScript 3.0 permet systématiquement de détecter tous les objets enfant de tout conteneur d’objets d’affichage. Chaque occurrence de DisplayObjectContainer possède une propriété numChildren, qui indique le nombre d’enfants figurant dans le conteneur d’objets d’affichage. Puisque la liste des enfants d’un conteneur d’objets d’affichage correspond systématiquement à une liste indexée, vous pouvez examiner chaque objet de la liste de la position d’index 0 à la dernière position d’index (numChildren - 1). Cette technique n’était pas proposée par les méthodes et propriétés d’un objet MovieClip dans ActionScript 1.0 et 2.0. ActionScript 3.0 permet de parcourir aisément et séquentiellement la liste d’affichage, car les numéros d’index de la liste des enfants d’un conteneur d’objets d’affichage se suivent. Parcourir la liste d’affichage et gérer la profondeur des objets est désormais beaucoup plus simple que dans ActionScript 1.0 et 2.0. Dans ActionScript 1.0 et 2.0, un clip pouvait en effet contenir des objets dont l’ordre de profondeur n’était pas séquentiel, ce qui rendait parfois le parcours de la liste d’objets difficile. Dans ActionScript 3.0, chaque liste d’enfants d’un conteneur d’objets d’affichage est mise en cache en interne sous forme de tableau, ce qui permet des recherches extrêmement rapides (par index). Passer en boucle sur tous les enfants d’un conteneur d’objets d’affichage s’avère également très rapide. Dans ActionScript 3.0, vous pouvez également accéder aux enfants d’un conteneur d’objets d’affichage par le biais de la méthode getChildByName() de la classe DisplayObjectContainer. Parcours entier de la liste d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 1.0 et 2.0 ne vous permettaient pas d’accéder à certains objets, telles les formes vectorielles, dessinées dans l’outil de programmation Flash. Dans ActionScript 3.0, vous pouvez accéder à tous les objets de la liste d’affichage, qu’ils aient été créés en ActionScript ou dans l’outil de programmation Flash. Pour plus d’informations, voir « Parcours de la liste d’affichage » à la page 169. Objets d’affichage absents de la liste Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 3.0 permet de créer des objets d’affichage qui ne figurent pas dans la liste d’affichage visible. Ils portent le nom d’objets d’affichage hors liste. Un objet d’affichage n’est ajouté à la liste d’affichage visible que lorsque vous appelez la méthode addChild() ou addChildAt() d’une occurrence de DisplayObjectContainer qui a déjà été intégrée à la liste d’affichage. Les objets d’affichage hors liste permettent d’assembler des objets d’affichage complexes, tels que ceux qui possèdent plusieurs conteneurs d’objets d’affichage comportant plusieurs objets d’affichage. En n’intégrant pas à la liste des objets d’affichage, vous pouvez assembler des objets complexes sans avoir à effectuer leur rendu. Vous économisez ainsi le temps de traitement correspondant. Vous pouvez alors ajouter un objet hors liste à la liste d’affichage au moment voulu. Il est également possible d’intégrer un enfant d’un conteneur d’objets d’affichage à la liste d’affichage, puis de l’en extraire ou d’en modifier la position dans cette dernière, le cas échéant. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 164 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Classement simplifié en sous-classes des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans ActionScript 1.0 et 2.0, il était souvent nécessaire d’ajouter de nouveaux objets MovieClip à un fichier SWF pour créer des formes de base ou afficher des bitmaps. Dans ActionScript 3.0, la classe DisplayObject comprend un grand nombre de sous-classes intégrées, telles que Shape et Bitmap. Parce que les classes d’ActionScript 3.0 sont plus spécialisées pour des types spécifiques d’objets, il est plus simple de créer des sous-classes de base des classes intégrées. Par exemple, pour dessiner un cercle dans ActionScript 2.0, vous pourriez créer une classe CustomCircle qui étend la classe MovieClip lors de la création d’une occurrence d’un objet de la classe personnalisée. Néanmoins, cette classe comprendrait également diverses propriétés et méthodes émanant de la classe MovieClip (telles que totalFrames) qui ne s’appliquent pas à elle. Dans ActionScript 3.0, vous pouvez toutefois créer une classe CustomCircle qui étend l’objet Shape et, de ce fait, ne comprend pas les propriétés et méthodes sans rapport contenues dans la classe MovieClip. Le code suivant illustre un exemple de classe CustomCircle : import flash.display.*; public class CustomCircle extends Shape { var xPos:Number; var yPos:Number; var radius:Number; var color:uint; public function CustomCircle(xInput:Number, yInput:Number, rInput:Number, colorInput:uint) { xPos = xInput; yPos = yInput; radius = rInput; color = colorInput; this.graphics.beginFill(color); this.graphics.drawCircle(xPos, yPos, radius); } } Utilisation des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Maintenant que vous maîtrisez les bases de la scène, des objets d’affichage, des conteneurs d’objets d’affichage et de la liste d’affichage, cette section contient des informations plus détaillées relatives à l’utilisation des objets d’affichage dans ActionScript 3.0. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 165 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Propriétés et méthodes de la classe DisplayObject Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Tous les objets d’affichage sont des sous-classes de la classe DisplayObject et, de ce fait, héritent des propriétés et méthodes de cette dernière. Les propriétés dont ils héritent correspondent aux propriétés de base qui s’appliquent à tous les objets d’affichage. Par exemple, chaque objet d’affichage possède une propriété x et une propriété y qui indiquent sa position dans son conteneur d’objets d’affichage. Il est impossible de créer une occurrence de DisplayObject à l’aide du constructeur de la classe DisplayObject. Vous devez créer un autre type d’objet (un objet qui est une sous-classe de la classe DisplayObject), tel Sprite, pour créer une occurrence d’objet par le biais de l’opérateur new. Par ailleurs, pour créer une classe d’objet d’affichage personnalisée, vous devez créer une sous-classe de l’une des sous-classes d’objets d’affichage ayant une fonction constructeur utilisable (telle que la classe Shape ou la classe Sprite). Pour plus d’informations, voir la description de la classe DisplayObject dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Ajout d’objets d’affichage à la liste d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous créez une occurrence d’un objet d’affichage, elle n’apparaît pas à l’écran (sur la scène) tant que vous ne l’avez pas ajoutée à un conteneur d’objets d’affichage figurant dans la liste d’affichage. Par exemple, dans le code suivant, l’objet myText TextField n’est pas visible si vous omettez la dernière ligne de code. Dans la dernière ligne de code, le mot-clé this doit se référer à un conteneur d’objets d’affichage figurant déjà dans la liste d’affichage. import flash.display.*; import flash.text.TextField; var myText:TextField = new TextField(); myText.text = "Buenos dias."; this.addChild(myText); Lorsque vous ajoutez un élément visuel à la scène, il devient un enfant de cette dernière. Le premier fichier SWF chargé dans une application (tel celui intégré à une page HTML) est automatiquement ajouté en tant qu’enfant de la scène. Il peut s’agir de n’importe quel type d’objet qui étend la classe Sprite. Tout objet d’affichage créé sans utiliser ActionScript (par exemple en ajoutant une balise MXML dans un fichier MXML Flex ou en plaçant un élément sur la scène dans Flash Professional) est ajouté à la liste d’affichage. Bien que vous n’ajoutiez pas ces objets d’affichage par le biais d’ActionScript, vous pouvez y accéder via ActionScript. Par exemple, le code suivant règle la largeur d’un objet appelé button1, qui a été ajouté dans l’outil de programmation (et non via ActionScript) : button1.width = 200; Utilisation de conteneurs d’objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si un objet DisplayObjectContainer est supprimé de la liste d’affichage ou s’il est transféré ou transformé d’une autre façon, chaque objet d’affichage de DisplayObjectContainer est également supprimé, transféré ou transformé. Un conteneur d’objets d’affichage correspond à un type d’objet d’affichage et peut être ajouté à un autre conteneur d’objets d’affichage. Par exemple, l’image suivante illustre un conteneur d’objets d’affichage, pictureScreen, qui comporte une forme de contour et quatre autres conteneurs d’objets d’affichage (de type PictureFrame) : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 166 Programmation de l’affichage Dernière mise à jour le 27/4/2013 A. Forme définissant la bordure du conteneur d’objets d’affichage pictureScreen B. Quatre conteneurs d’objets d’affichage, qui sont des enfants de l’objet pictureScreen Pour qu’un objet d’affichage apparaisse dans la liste d’affichage, vous devez l’ajouter à un conteneur d’objets d’affichage figurant dans la liste d’affichage. A cet effet, vous utilisez la méthode addChild() ou la méthode addChildAt() de l’objet conteneur. Par exemple, sans la dernière ligne du code suivant, l’objet myTextField ne s’afficherait pas : var myTextField:TextField = new TextField(); myTextField.text = "hello"; this.root.addChild(myTextField); Dans cet exemple de code, this.root pointe vers le conteneur d’objets d’affichage MovieClip qui comporte le code. Dans votre propre code, vous pouvez stipuler un autre conteneur. A B GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 167 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Utilisez la méthode addChildAt() pour ajouter l’enfant à une position déterminée de la liste des enfants du conteneur d’objets d’affichage. Ces positions d’index basées sur zéro dans la liste des enfants se réfèrent à l’ordre d’apparition (de l’avant à l’arrière) des objets d’affichage. Considérons par exemple les trois objets d’affichage suivants. Chaque objet a été créé à partir d’une classe personnalisée appelée Ball. L’ordre d’apparition de ces objets d’affichage dans leur conteneur peut être modifié par le biais de la méthode addChildAt(). Considérons par exemple le code qui suit : ball_A = new Ball(0xFFCC00, "a"); ball_A.name = "ball_A"; ball_A.x = 20; ball_A.y = 20; container.addChild(ball_A); ball_B = new Ball(0xFFCC00, "b"); ball_B.name = "ball_B"; ball_B.x = 70; ball_B.y = 20; container.addChild(ball_B); ball_C = new Ball(0xFFCC00, "c"); ball_C.name = "ball_C"; ball_C.x = 40; ball_C.y = 60; container.addChildAt(ball_C, 1); Une fois ce code exécuté, les objets d’affichage sont placés comme suit dans l’objet DisplayObjectContainer container. Notez l’ordre d’apparition des objets. Pour placer un objet en tête de la liste d’affichage, il suffit de l’ajouter à nouveau à celle-ci. Par exemple, après le code précédent, utilisez la ligne de code suivante pour placer ball_A en première position dans la pile : container.addChild(ball_A); Ce code supprime ball_A de son emplacement actuel dans la liste d’affichage de container, et l’ajoute ensuite au sommet de la liste, ce qui a pour effet de le placer en haut de l’empilement d’objets. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 168 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Vous disposez de la méthode getChildAt() pour vérifier l’ordre d’apparition des objets d’affichage. La méthode getChildAt() renvoie les objets enfant d’un conteneur en fonction du numéro d’index transmis. Par exemple, le code suivant révèle le nom des objets d’affichage placés à des positions diverses dans la liste des enfants de l’objet DisplayObjectContainer container : trace(container.getChildAt(0).name); // ball_A trace(container.getChildAt(1).name); // ball_C trace(container.getChildAt(2).name); // ball_B Si vous supprimez un objet d’affichage de la liste des enfants de son conteneur parent, les éléments de la liste ayant un indice plus élevé descendent tous d’une position dans l’index des enfants. Ainsi, si nous reprenons l’exemple précédent, le code ci-après illustre le transfert de l’objet d’affichage qui occupait la position 2 dans l’objet DisplayObjectContainer container vers la position 1 suite à la suppression d’un objet d’affichage occupant une position inférieure dans la liste d’enfants : container.removeChild(ball_C); trace(container.getChildAt(0).name); // ball_A trace(container.getChildAt(1).name); // ball_B Les méthodes removeChild() et removeChildAt() ne suppriment pas entièrement une occurrence d’objet d’affichage. Elles se contentent de la supprimer de la liste des enfants du conteneur. Une autre variable peut continuer à faire référence à l’occurrence (utilisez l’opérateur delete pour supprimer totalement un objet). Un objet d’affichage ne possédant qu’un seul conteneur parent, vous ne pouvez ajouter une occurrence d’objet d’affichage qu’à un seul conteneur d’objets d’affichage. Par exemple, le code suivant indique que l’objet d’affichage tf1 ne peut figurer que dans un seul conteneur (soit, dans ce cas, un Sprite, qui étend la classe DisplayObjectContainer) : tf1:TextField = new TextField(); tf2:TextField = new TextField(); tf1.name = "text 1"; tf2.name = "text 2"; container1:Sprite = new Sprite(); container2:Sprite = new Sprite(); container1.addChild(tf1); container1.addChild(tf2); container2.addChild(tf1); trace(container1.numChildren); // 1 trace(container1.getChildAt(0).name); // text 2 trace(container2.numChildren); // 1 trace(container2.getChildAt(0).name); // text 1 Si vous ajoutez à un conteneur d’objets d’affichage un objet qui est déjà contenu dans un autre conteneur d’objets d’affichage, l’objet sera supprimé de la liste des enfants de ce dernier. Outre les méthodes décrites précédemment, la classe DisplayObjectContainer définit plusieurs méthodes d’utilisation des objets d’affichage enfant, notamment : • contains() : détermine si un objet d’affichage est un enfant d’un objet DisplayObjectContainer. • getChildByName() : extrait un objet d’affichage en fonction de son nom. • getChildIndex() : renvoie la position d’index d’un objet d’affichage. • setChildIndex() : modifie la position d’un objet d’affichage enfant. • removeChildren() : supprime plusieurs objets d’affichage enfants. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 169 Programmation de l’affichage Dernière mise à jour le 27/4/2013 • swapChildren() : permute l’ordre de deux objets d’affichage. • swapChildrenAt() : permute l’ordre de deux objets d’affichage définis en fonction de leur valeur d’index. Pour plus d’informations, voir les entrées pertinentes du manuel Guide de référence ActionScript 3.0 pour la plateforme Adobe Flash. N’oubliez pas qu’un objet d’affichage qui ne figure pas dans la liste d’affichage (donc, qui ne se trouve pas dans un conteneur d’objets d’affichage enfant de la scène) est appelé objet d’affichage hors liste. Parcours de la liste d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Comme nous l’avons vu, la liste d’affichage est une structure en arborescence. Au sommet de l’arborescence figure la scène, qui peut comporter plusieurs objets d’affichage. Les objets d’affichage qui sont eux-mêmes des conteneurs d’objets d’affichage peuvent contenir d’autres objets d’affichage, voire des conteneurs d’objets d’affichage. La classe DisplayObjectContainer comporte des propriétés et méthodes de parcours de la liste d’affichage, par le biais des listes d’enfants des conteneurs d’objets d’affichage. Considérons par exemple le code suivant, qui ajoute deux objets d’affichage, title et pict, à l’objet container (qui est un Sprite, et la classe Sprite étend la classe DisplayObjectContainer) : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 170 Programmation de l’affichage Dernière mise à jour le 27/4/2013 var container:Sprite = new Sprite(); var title:TextField = new TextField(); title.text = "Hello"; var pict:Loader = new Loader(); var url:URLRequest = new URLRequest("banana.jpg"); pict.load(url); pict.name = "banana loader"; container.addChild(title); container.addChild(pict); La méthode getChildAt() renvoie l’enfant de la liste d’affichage à une position d’index déterminée : trace(container.getChildAt(0) is TextField); // true Vous pouvez également accéder aux objets enfant en indiquant leur nom. Chaque objet d’affichage possède un nom, qui est attribué par défaut par Flash Player ou AIR (tel « instance1 ») si vous ne l’attribuez pas vous-même. Par exemple, le code suivant indique comment utiliser la méthode getChildByName() pour accéder à un objet d’affichage enfant portant le nom « banana loader » : trace(container.getChildByName("banana loader") is Loader); // true L’utilisation de la méthode getChildByName() entraîne parfois un ralentissement des performances par rapport à la méthode getChildAt(). Puisque la liste d’affichage d’un conteneur d’objets d’affichage peut contenir d’autres conteneurs d’objets d’affichage en tant qu’objets enfant, vous pouvez parcourir la liste d’affichage complète de l’application sous forme d’arborescence. Par exemple, dans l’extrait de code illustré précédemment, une fois l’opération de chargement de l’objet Loader pict terminée, un objet d’affichage enfant (l’image bitmap) de l’objet pict est chargé. Pour accéder à cet objet d’affichage bitmap, vous pouvez écrire pict.getChildAt(0). Vous pouvez également écrire container.getChildAt(0).getChildAt(0) (puisque container.getChildAt(0) == pict). La fonction suivante génère un extrait trace() en retrait de la liste d’affichage d’un conteneur d’objets d’affichage : function traceDisplayList(container:DisplayObjectContainer,indentString:String = ""):void { var child:DisplayObject; for (var i:uint=0; i < container.numChildren; i++) { child = container.getChildAt(i); trace(indentString, child, child.name); if (container.getChildAt(i) is DisplayObjectContainer) { traceDisplayList(DisplayObjectContainer(child), indentString + "") } } } Adobe Flex Si vous utilisez Flex, notez que cette application définit un grand nombre de classes d’objets d’affichage de composant et que celles-ci priment sur les méthodes d’accès à la liste d’affichage de la classe DisplayObjectContainer. Par exemple, la classe Container du package mx.core prime sur la méthode addChild() et autres méthodes de la classe DisplayObjectContainer (étendue par la classe Container). Dans le cas de la méthode addChild(), la classe primant sur la méthode, vous ne pouvez pas ajouter tous les types d’objets d’affichage à une occurrence de Container dans Flex. La méthode remplacée demande dans ce cas que l’objet enfant ajouté soit de type mx.core.UIComponent. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 171 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Définition des propriétés de la scène Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Stage annule la plupart des propriétés et méthodes de la classe DisplayObject. Si vous appelez l’une de ces propriétés ou méthodes annulées, Flash Player et AIR renvoient une exception. Par exemple, l’objet Stage ne possède pas de propriété x ou y car, en tant que conteneur principal de l’application, sa position est fixe. Or, les propriétés x et y indiquent la position d’un objet d’affichage par rapport à son conteneur, et puisque la scène ne se trouve pas dans un autre conteneur d’objets d’affichage, ces propriétés seraient inapplicables. Remarque : certaines propriétés et méthodes de la classe Stage sont réservées aux objets d’affichage appartenant au même sandbox de sécurité que le premier fichier SWF chargé. Pour plus d’informations, voir « Sécurité de la scène » à la page 1109. Contrôle de la cadence de lecture Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La propriété framerate de la classe Stage permet de définir la cadence de tous les fichiers SWF chargés dans l’application. Pour plus d’informations, voir le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Contrôle de la mise à l’échelle de la scène Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque la portion de l’écran qui représente Flash Player ou AIR est redimensionnée, le moteur d’exécution ajuste automatiquement le contenu de la scène en conséquence. La propriété scaleMode de la classe Stage détermine comment le contenu de la scène est ajusté. Cette propriété peut être réglée sur quatre valeurs distinctes, définies en tant que constantes dans la classe flash.display.StageScaleMode : • StageScaleMode.EXACT_FIT met à l’échelle le fichier SWF de sorte à occuper les nouvelles dimensions de la scène sans tenir compte du format d’origine du contenu. Etant donné que les facteurs d’échelle ne sont pas nécessairement identiques en largeur et en hauteur, le contenu risque de sembler écrasé ou étiré en cas de modification du format de la scène. • StageScaleMode.SHOW_ALL met à l’échelle le fichier SWF de sorte à occuper les nouvelles dimensions de la scène sans modifier le format du contenu. Ce mode de mise à l’échelle affiche la totalité du contenu, mais risque de donner lieu à des bordures de type « boîte aux lettres » similaires aux barres noires qui entourent un film grand écran sur une télévision standard. • StageScaleMode.NO_BORDER met à l’échelle le fichier SWF de sorte à occuper totalement les nouvelles dimensions de la scène sans modifier le format du contenu. Ce mode de mise à l’échelle exploite pleinement la zone d’affichage de la scène, mais risque d’engendrer un recadrage. • StageScaleMode.NO_SCALE : ne met pas à l’échelle le fichier SWF. Si les nouvelles dimensions de la scène sont inférieures aux dimensions d’origine, le contenu est recadré. Si elles leur sont supérieures, l’espace ajouté est vide. Dans le mode de mise à l’échelle StageScaleMode.NO_SCALE uniquement, les propriétés stageWidth et stageHeight de la classe Stage permettent de déterminer les dimensions réelles de la scène redimensionnée, exprimées en pixels. (Dans les autres modes, les propriétés stageWidth et stageHeight renvoient toujours la largeur et la hauteur d’origine du fichier SWF.) De plus, lorsque la propriété scaleMode est définie sur StageScaleMode.NO_SCALE et que le fichier SWF est redimensionné, l’événement resize de la classe Stage est distribué, ce qui vous permet d’effectuer des ajustements en conséquence. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 172 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Définir scaleMode sur StageScaleMode.NO_SCALE permet donc de mieux contrôler l’ajustement du contenu en cas de redimensionnement de la fenêtre. Par exemple, si un fichier SWF contient une vidéo et une barre de contrôle, il peut s’avérer utile de conserver la taille de la barre de contrôle en cas de redimensionnement de la scène et de ne modifier que la taille de la fenêtre de vidéo en fonction du changement de taille de la scène. Ce cas de figure est illustré dans l’exemple suivant : // mainContent is a display object containing the main content; // it is positioned at the top-left corner of the Stage, and // it should resize when the SWF resizes. // controlBar is a display object (e.g. a Sprite) containing several // buttons; it should stay positioned at the bottom-left corner of the // Stage (below mainContent) and it should not resize when the SWF // resizes. import flash.display.Stage; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; var swfStage:Stage = mainContent.stage; swfStage.scaleMode = StageScaleMode.NO_SCALE; swfStage.align = StageAlign.TOP_LEFT; swfStage.addEventListener(Event.RESIZE, resizeDisplay); function resizeDisplay(event:Event):void { var swfWidth:int = swfStage.stageWidth; var swfHeight:int = swfStage.stageHeight; // Resize the main content area var newContentHeight:Number = swfHeight - controlBar.height; mainContent.height = newContentHeight; mainContent.scaleX = mainContent.scaleY; // Reposition the control bar. controlBar.y = newContentHeight; } Définition du mode de mise à l’échelle de la scène pour les fenêtres AIR La propriété scaleMode de la scène indique comment celle-ci met à l’échelle et écrête les objets d’affichage enfant lors d’un redimensionnement de fenêtre. N’utilisez que le mode noScale dans AIR. Lorsque ce mode est activé, la scène n’est pas mise à l’échelle. La taille de la scène est modifiée directement en fonction des limites de la fenêtre. Les objets risquent d’être écrêtés si la taille de la fenêtre est inférieure à sa taille initiale. Les modes de mise à l’échelle de la scène sont adaptés aux environnements tels qu’un navigateur Web qui ne permet pas nécessairement de contrôler la taille ou le format de la scène. Grâce aux modes, vous pouvez sélectionner le cas de figure le moins inadapté lorsque la scène ne correspond pas à la taille ou au format idéal défini par l’application. Dans AIR, vous contrôlez toujours la scène. Par conséquent, modifier la disposition du contenu ou redimensionner la fenêtre assure un meilleur résultat que l’activation de la mise à l’échelle de la scène. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 173 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Dans le navigateur et la fenêtre AIR initiale, la relation entre la taille de fenêtre et le facteur d’échelle initial est extraite du fichier SWF chargé. Toutefois, lorsque vous créez un objet NativeWindow, AIR choisit une relation arbitraire définie sur 72:1 entre la taille de fenêtre et le facteur d’échelle. Par conséquent, si la fenêtre mesure 72x72 pixels, un rectangle de 10x10 pixels ajouté à la fenêtre est dessiné à la taille correcte (soit 10x10 pixels). Par contre, si la fenêtre mesure 144x144 pixels, un rectangle de 10x10 pixels est mis à l’échelle (soit 20x20 pixels). Si vous préférez utiliser une propriété scaleMode autre que noScale pour une scène de fenêtre, vous pouvez compenser le résultat en définissant le facteur d’échelle de tout objet d’affichage de la fenêtre sur le rapport 72 pixels/largeur et hauteur actuelles de la scène. Le code suivant calcule par exemple le facteur d’échelle requis de l’objet d’affichage client : if(newWindow.stage.scaleMode != StageScaleMode.NO_SCALE){ client.scaleX = 72/newWindow.stage.stageWidth; client.scaleY = 72/newWindow.stage.stageHeight; } Remarque : les fenêtres Flex et HTML définissent automatiquement la propriété scaleMode de la scène sur noScale. Modifier la propriété scaleMode entrave le fonctionnement des mécanismes de mise en forme automatique utilisés dans ces types de fenêtres. Utilisation du mode Plein écran Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le mode plein écran permet de définir la scène d’un film de sorte à remplir totalement le moniteur sans bordure ou menu. La propriété displayState de la classe Stage permet d’activer ou désactiver ce mode pour un fichier SWF. La propriété displayState peut être réglée sur l’une des valeurs définies par les constantes de la classe flash.display.StageDisplayState. Pour activer le mode plein écran, définissez la propriété displayState sur StageDisplayState.FULL_SCREEN : stage.displayState = StageDisplayState.FULL_SCREEN; Pour activer le mode interactif plein écran (nouveauté dans Flash Player 11.3), définissez la propriété displayState sur StageDisplayState.FULL_SCREEN_INTERACTIVE : stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE; Dans Flash Player, le mode plein écran ne peut être activé que via ActionScript en réponse à un clic de souris (clic de bouton droit inclus) ou une frappe de touche. Le contenu AIR qui s’exécute dans le sandbox de sécurité de l’application ne nécessite pas que le mode plein écran soit activé en réponse à une action de l’utilisateur. Pour quitter le mode plein écran, définissez la propriété displayState sur StageDisplayState.NORMAL. stage.displayState = StageDisplayState.NORMAL; Un utilisateur peut également désactiver le mode plein écran en plaçant le focus sur une autre fenêtre ou en utilisant l’une des combinaisons de touches suivantes : la touche Echap (toutes les plates-formes), Contrôle-W (Windows), Commande-W (Mac) ou Alt-F4 (Windows). Activation du mode plein écran dans Flash Player Pour activer le mode plein écran d’un fichier SWF intégré à une page HTML, le code HTML requis pour intégrer Flash Player doit comprendre une balise param et un attribut embed, associés au nom allowFullScreen et à la valeur true, comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 174 Programmation de l’affichage Dernière mise à jour le 27/4/2013 ... Dans l’outil de programmation Flash, choisissez Fichier -> Paramètres de publication, puis dans la boîte de dialogue Paramètres de publication, cliquez sur l’onglet HTML et sélectionnez le modèle Flash seulement - Autorisation du Plein écran. Dans Flex, assurez-vous que le modèle HTML inclut les balises et qui prennent en charge le plein écran. Si vous utilisez JavaScript dans une page Web pour générer les balises d’intégration de SWF, vous devez modifier le code JavaScript pour ajouter la balise et l’attribut allowFullScreen param. Par exemple, si votre page HTML fait appel à la fonction AC_FL_RunContent() (utilisée par les pages HTML générées par Flash Professional et Flash Builder), vous devez ajouter le paramètre allowFullScreen à cet appel de fonction, comme suit : AC_FL_RunContent( ... 'allowFullScreen','true', ... ); //end AC code Ce cas de figure ne s’applique pas aux fichiers SWF qui s’exécutent dans la version autonome de Flash Player. Remarque : si vous définissez le Mode fenêtre (wmode dans le code HTML) sur Opaque sans fenêtre (opaque) ou Transparent sans fenêtre (transparent), la fenêtre plein écran est toujours opaque. Il existe également des restrictions liées à la sécurité lors de l’utilisation du mode plein écran avec Flash Player dans un navigateur. Ces restrictions sont décrites dans le chapitre « Sécurité » à la page 1085. Activation du mode interactif plein écran dans Flash Player 11.3 et les versions ultérieures Flash Player 11.3 et les versions ultérieures prennent en charge le mode interactif plein écran, qui permet une prise en charge totale de toutes les touches du clavier (à l’exception de la touche Echap, qui permet de quitter le mode interactif plein écran). Le mode interactif plein écran est utile pour les jeux (par exemple pour activer la fonction de dialogue en ligne dans un jeu multijoueurs ou les commandes du clavier WASD dans un jeu de tir subjectif.) Pour activer le mode interactif plein écran d’un fichier SWF intégré à une page HTML, le code HTML requis pour intégrer Flash Player doit comprendre une balise param et un attribut embed, associés au nom allowFullScreenInteractive et à la valeur true, comme suit : ... Dans l’outil de création de Flash, cliquez sur Fichier -> Paramètres de publication, puis, dans l’onglet HTML de la boîte de dialogue Paramètres de publication, sélectionnez le modèle Flash seulement - Autorisation du Plein écran interactif. Dans Flash Builder et Flex, vérifiez que les modèles HTML incluent les balises et qui prennent en charge le mode interactif plein écran. Si vous utilisez JavaScript dans une page Web pour générer les balises d’intégration de SWF, vous devez modifier le code JavaScript pour ajouter la balise et l’attribut allowFullScreenInteractive param. Par exemple, si votre page HTML fait appel à la fonction AC_FL_RunContent() (utilisée par les pages HTML générées par Flash Professional et Flash Builder), vous devez ajouter le paramètre allowFullScreenInteractive à cet appel de fonction, comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 175 Programmation de l’affichage Dernière mise à jour le 27/4/2013 AC_FL_RunContent( ... 'allowFullScreenInteractive','true', ... ); //end AC code Ce cas de figure ne s’applique pas aux fichiers SWF qui s’exécutent dans la version autonome de Flash Player. Mise à l’échelle et taille de la scène en mode plein écran Les propriétés Stage.fullScreenHeight et Stage.fullScreenWidth renvoient la hauteur et la largeur de l’écran utilisé lors de l’activation du mode plein écran, lorsque le passage à cet état est immédiat. Ces valeurs risquent d’être incorrectes si l’utilisateur déplace le navigateur d’un écran à un autre après avoir récupéré ces valeurs, mais avant de passer au mode plein écran. Si l’utilisateur récupère ces valeurs dans le gestionnaire d’événement dans lequel il a défini la propriété Stage.displayState sur StageDisplayState.FULL_SCREEN, celles-ci sont correctes. Pour les utilisateurs qui utilisent plusieurs écrans, le contenu du fichier SWF s’étend pour n’occuper qu’un seul écran. Flash Player et AIR utilisent une mesure pour identifier le moniteur contenant la portion la plus élevée du fichier SWF et activent le mode plein écran sur celui-ci. Les propriétés fullScreenHeight et fullScreenWidth ne reflètent que la taille du moniteur utilisé en mode plein écran. Pour plus d’informations, voir Stage.fullScreenHeight et Stage.fullScreenWidth dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. En mode plein écran, le comportement de mise à l’échelle de la scène est identique à celui du mode normal. Cette mise à l’échelle est contrôlée par la propriété scaleMode de la classe Stage. Si la propriété scaleMode est définie sur StageScaleMode.NO_SCALE, les propriétés stageWidth et stageHeight de la classe Stage sont modifiées pour répercuter la taille de la zone de l’écran occupée par le fichier SWF (soit, dans ce cas, l’écran entier). Dans un navigateur, le paramètre HTML correspondant contrôle le réglage. L’événement fullScreen de la classe Stage permet de détecter et répondre à l’activation ou à la désactivation du mode plein écran. Par exemple, il peut être nécessaire de repositionner, d’ajouter ou de supprimer des éléments lors d’un changement d’état du mode plein écran, comme illustré par cet exemple : import flash.events.FullScreenEvent; function fullScreenRedraw(event:FullScreenEvent):void { if (event.fullScreen) { // Remove input text fields. // Add a button that closes full-screen mode. } else { // Re-add input text fields. // Remove the button that closes full-screen mode. } } mySprite.stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullScreenRedraw); Comme l’indique ce code, l’objet associé à l’événement fullScreen est une occurrence de la classe flash.events.FullScreenEvent, dont la propriété fullScreen indique si le mode plein écran est activé (true) ou non (false). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 176 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Prise en charge du clavier en mode plein écran Lorsque Flash Player est exécuté dans un navigateur, l’ensemble du code ActionScript lié au clavier (événements de clavier et saisie de texte dans des occurrences de TextField, entre autres), est désactivé en mode plein écran. Les exceptions (c’est-à-dire les touches qui restent actives) sont les suivantes : • Les touches hors impression sélectionnées, notamment les touches fléchées, la barre d’espacement et la touche de tabulation • Les raccourcis clavier qui désactivent le mode plein écran : touche Echap (Windows et Mac), Contrôle-W (Windows), Commande-W (Mac) et Alt-F4 Ces restrictions ne sont pas présentes pour le contenu SWF s’exécutant dans l’application Flash Player autonome ou dans AIR. AIR prend en charge un mode plein écran interactif qui permet la saisie clavier. Prise en charge de la souris en mode plein écran Par défaut, les événements de souris fonctionnent de la même façon en mode plein écran que dans un autre mode d’affichage. Néanmoins, le mode plein écran permet également de définir la propriété Stage.mouseLock en vue de verrouiller la souris. Le verrouillage de la souris désactive le curseur et permet de déplacer la souris sans aucune limite. Remarque : vous pouvez verrouiller la souris uniquement sur des applications de bureau en mode plein écran. Le verrouillage de la souris sur des applications dans un autre mode d’affichage ou sur des applications mobiles renvoie une exception. Le verrouillage de la souris est automatiquement désactivé et le curseur de la souris est à nouveau visible lorsque : • l’utilisateur quitte le mode plein écran en appuyant sur la touche Echap (toutes les plates-formes), ou sur les touches Ctrl-W (Windows), Cmd-W (Mac) ou Alt-F4 (Windows) ; • la fenêtre de l’application perd le focus ; • une interface de paramétrage est visible, notamment une boîte de dialogue de confidentialité ; • une boîte de dialogue native s’affiche, notamment une boîte de dialogue de téléchargement d’un fichier. Les événements associés au mouvement de la souris, tels que l’événement mouseMove, font appel à la classe MouseEvent pour représenter l’objet de l’événement. Lorsque le verrouillage de la souris est désactivé, utilisez les propriétés MouseEvent.localX et MouseEvent.localY pour déterminer l’emplacement de la souris. Lorsque le verrouillage de la souris est activé, utilisez les propriétés MouseEvent.movementX et MouseEvent.movementY pour déterminer l’emplacement de la souris. Les propriétés movementX et movementY contiennent les changements de position de la souris depuis le dernier événement plutôt que les coordonnées absolues de l’emplacement de la souris. Mise à l’échelle matérielle en mode plein écran La propriété fullScreenSourceRect de la classe Stage permet d’utiliser Flash Player ou AIR pour mettre à l’échelle une zone déterminée de la scène en mode plein écran. Dans Flash Player et AIR, la mise à l’échelle matérielle, si elle est disponible, s’effectue à l’aide de la carte graphique et de la carte vidéo de l’ordinateur, et permet généralement d’afficher le contenu plus rapidement que la mise à l’échelle logicielle. Pour tirer parti de la mise à l’échelle matérielle, définissez l’ensemble ou une partie de la scène sur le mode plein écran. Le code suivant ActionScript 3.0 définit l’ensemble de la scène en mode plein écran : import flash.geom.*; { stage.fullScreenSourceRect = new Rectangle(0,0,320,240); stage.displayState = StageDisplayState.FULL_SCREEN; } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 177 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Lorsque cette propriété est définie sur un rectangle valide et la propriété displayState sur le mode plein écran, Flash Player et AIR redimensionnent la zone spécifiée. La taille réelle de la scène en pixels dans ActionScript ne change pas. Flash Player et AIR imposent une taille limite au rectangle en fonction de la taille du message standard « Appuyez sur la touche Echap pour quitter le mode plein écran ». Cette limite est généralement d’environ 260 sur 30 pixels, mais peut varier en fonction de la plate-forme et de la version de Flash Player. La propriété fullScreenSourceRect ne peut être définie que lorsque Flash Player ou AIR ne sont pas en mode plein écran. Pour utiliser correctement cette propriété, vous devez tout d’abord la définir, puis définir la propriété displayState sur le mode plein écran. Pour activer la mise à l’échelle, définissez la propriété fullScreenSourceRect sur un objet rectangle. stage.fullScreenSourceRect = new Rectangle(0,0,320,240); Pour désactiver la mise à l’échelle, définissez la propriété fullScreenSourceRect sur null. stage.fullScreenSourceRect = null; Pour tirer parti de toutes les fonctions d’accélération matérielle avec Flash Player, activez cette fonction dans la boîte de dialogue des paramètres de Flash Player. Pour afficher cette boîte de dialogue, cliquez avec le bouton droit de la souris (Windows) ou cliquez tout en appuyant sur la touche Ctrl (Mac) dans le contenu Flash Player dans votre navigateur. Cliquez sur le premier onglet, Affichage, puis cochez la case Activer l’accélération matérielle. Modes Fenêtre direct et composition GPU Flash Player 10 propose deux modes de fenêtre, direct et composition GPU, que vous pouvez activer dans les paramètres de publication de l’outil de programmation Flash. Ces modes ne sont pas pris en charge par AIR. Pour tirer parti de ces modes, vous devez activer l’accélération matérielle pour Flash Player. Le mode direct utilise le chemin le plus rapide et le plus direct pour placer des graphismes sur l’écran, ce qui est pratique pour la lecture vidéo. La composition GPU utilise l’unité de traitement graphique sur la carte vidéo pour accélérer la composition. La composition vidéo consiste à créer des images multi-couches pour aboutir à une seule image vidéo. Lorsque la composition est accélérée par la GPU, les performances de la conversion YUV, la correction des couleurs, la rotation, le redimensionnement et le fondu sont nettement améliorés. La conversion YUV se réfère à la conversion des couleurs de signaux analogiques composites, qui sont utilisées pour la transmission, au modèle de couleurs RVB (rouge-vertbleu) que les caméras vidéo et les écrans utilisent. Le recours à la GPU pour accélérer la composition réduit la demande en mémoire et en puissance de calcul qui affectera les performances de l’unité centrale. Il en résulte une lecture vidéo plus régulière en définition standard. Soyez vigilant lorsque vous implémentez ces modes Fenêtre. Fenêtre L’utilisation de la composition GPU peut s’avérer coûteuse en mémoire et en ressources de l’unité centrale. Si certaines opérations (comme les modes fondu, le filtrage, l’écrêtage ou le masquage) ne peuvent pas être exécutées dans la GPU, c’est le logiciel qui s’en charge. Adobe vous recommande de vous limiter à un fichier SWF par page HTML lorsque vous utilisez ces modes. Il ne faudrait pas les utiliser pour des bandeaux. La Flash Test Movie facility ne fait pas appel à l’accélération matérielle mais vous pouvez l’utiliser par le biais de l’option Aperçu avant publication. Il est inutile de fixer une cadence supérieure à 60 (c’est la fréquence de régénération d’écran maximale) dans votre fichier SWF. Une cadence entre 50 et 55 débouche sur des images perdues, ce qui peut se produire de temps à autre pour des raisons diverses. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 178 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Le mode direct requiert Microsoft DirectX 9 avec une mémoire virtuelle RAM de 128 Mo sous Windows et OpenGL pour Apple Macintosh, Mac OS X version 10.2 ou ultérieure. La composition GPU requiert Microsoft DirectX 9 et la prise en charge de Pixel Shader 2.0 sous Windows avec une mémoire virtuelle RAM de 128 Mo. Sous Mac OS X et Linux, la composition GPU requiert OpenGL 1.5 et plusieurs extensions d’OpenGL (objet framebuffer, objets multitexture et shader, langage d’ombrage, shader de fragments). Vous pouvez activer les modes d’accélération direct et gpu pour chaque SWF par le biais de la boîte de dialogue Paramètres de publication de Flash, à l’aide du menu d’accélération matérielle sur l’onglet Flash. Si vous choisissez Aucun, le mode Fenêtre revient à défaut, transparent ou opaque, selon le paramètre du Mode Fenêtre de l’onglet HTML. Manipulation des événements associés aux objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe DisplayObject hérite de la classe EventDispatcher. Cela signifie que chaque objet d’affichage peut être pleinement impliqué dans le modèle d’événement (décrit dans le chapitre « Gestion des événements » à la page 129). Chaque objet d’affichage peut utiliser sa méthode addEventListener() (héritée de la classe EventDispatcher) pour attendre un événement particulier, mais ceci uniquement si l’objet écouteur fait partie du flux d’événement de l’événement considéré. Lorsque Flash Player ou AIR distribue un objet événement, celui-ci effectue un aller-retour à partir de la scène via l’objet d’affichage où s’est produit l’événement. Par exemple, si un utilisateur clique sur un objet d’affichage appelé child1, Flash Player distribue un objet événement à partir de la scène via la hiérarchie de la liste d’affichage jusqu’à l’objet d’affichage child1. D’un point de vue conceptuel, le flux d’événement est divisé en trois phases, comme illustré par le diagramme suivant : Pour plus d’informations, voir « Gestion des événements » à la page 129. Lors de la gestion des événements liés aux objets d’affichage, il est important de ne pas oublier l’effet potentiel des objets écouteurs d’événement sur l’éventuelle suppression automatique des objets d’affichage de la mémoire (garbage collection) lorsqu’ils sont supprimés de la liste d’affichage. Si des objets d’un objet d’affichage sont enregistrés en tant qu’écouteurs d’événement, ce dernier n’est pas supprimé de la mémoire même s’il est supprimé de la liste d’affichage, car il continue à posséder des références à ces objets écouteur. Pour plus d’informations, voir « Gestion des écouteurs d’événement » à la page 143. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 179 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Sélection d’une sous-classe de DisplayObject Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Plusieurs options étant disponibles, l’une des décisions importantes à prendre lors de l’utilisation d’objets d’affichage est le choix de l’objet à utiliser dans un but précis. Les directives suivantes vous aideront à choisir l’option appropriée. Ces suggestions sont valides que vous créiez une occurrence de classe ou que vous choisissiez une classe de base pour une classe en cours de création : • Si vous n’avez pas besoin d’un objet pouvant contenir d’autres objets d’affichage (autrement dit, si vous avez simplement besoin d’un objet à utiliser comme élément isolé), choisissez l’une des sous-classes suivantes de DisplayObject ou d’InteractiveObject, selon l’utilisation prévue : • Bitmap, pour afficher une image bitmap. • TextField, pour ajouter du texte. • Video, pour afficher une vidéo. • Shape, pour disposer d’une « toile » destinée au tracé d’un contenu à l’écran. En particulier si vous souhaitez créer une occurrence pour dessiner des formes à l’écran et qu’elle ne contient pas d’autres objets d’affichage, vous obtiendrez des performances nettement supérieures en utilisant Shape plutôt que Sprite ou MovieClip. • MorphShape, StaticText ou SimpleButton pour des éléments créés par l’outil de programmation Flash. Il est impossible de créer par programmation des occurrences de ces classes, mais vous pouvez créer des variables avec ces types de données pour pointer sur des éléments créés dans l’outil de programmation Flash. • Si vous devez disposer d’une variable qui se réfère à la scène principale, utilisez la classe Stage en tant que type de données. • Si vous devez disposer d’un conteneur pour charger un fichier SWF ou fichier image externe, utilisez une occurrence de Loader. Le contenu chargé sera ajouté à la liste d’affichage en tant qu’enfant de l’occurrence de Loader. Son type de données variera selon la nature du contenu chargé, comme suit : • Une image chargée est une occurrence de Bitmap. • Un fichier SWF chargé écrit dans ActionScript 3.0 est une occurrence de Sprite ou MovieClip (ou une occurrence d’une sous-classe de ces classes, comme indiqué par le créateur du contenu). • Un fichier SWF chargé écrit dans ActionScript 1.0 ou ActionScript 2.0 est une occurrence d’AVM1Movie. • Si vous avez besoin d’un objet qui sera le conteneur d’autres objets d’affichage (que vous ayez ou non l’intention de dessiner en ActionScript dans cet objet), choisissez l’une des sous-classes de DisplayObjectContainer : • Sprite, si l’objet est créé en ActionScript uniquement ou en tant que classe de base d’un objet d’affichage personnalisé créé et manipulé en ActionScript uniquement. • MovieClip, si vous créez une variable pointant vers un symbole de clip créé dans l’outil de programmation Flash. • Si vous créez une classe qui sera associée à un symbole de clip de la bibliothèque de Flash, choisissez l’une des sousclasses de DisplayObjectContainer comme classe de base de votre future classe : • MovieClip, si le symbole de clip associé possède un contenu sur plusieurs images. • Sprite, si le symbole de clip associé ne possède un contenu que sur la première image. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 180 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Manipulation des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Quel que soit l’objet d’affichage utilisé, tous les éléments affichés à l’écran partagent diverses techniques de manipulations. Par exemple, ils peuvent tous être positionnés à l’écran, avancer ou reculer dans l’ordre d’empilement des objets d’affichage, mis à l’échelle, pivotés, et ainsi de suite. Dans la mesure où tous les objets d’affichage héritent ces fonctionnalités de leur classe de base commune (DisplayObject), lesdites fonctionnalités ont le même comportement pour une occurrence d’un objet TextField, Video, Shape ou tout autre objet d’affichage. Les sections suivantes passent en revue plusieurs de ces manipulations appliquées à tous les objets d’affichage. Modification de la position Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La manipulation la plus fondamentale de tout objet d’affichage consiste à le positionner à l’écran. Pour définir la position d’un objet d’affichage, changez ses propriétés x et y. myShape.x = 17; myShape.y = 212; Le système de positionnement d’un objet d’affichage assimile la scène à un système de coordonnées cartésiennes (système de grille standard doté d’un axe horizontal x et d’un axe vertical y). L’origine du système de coordonnées (coordonnée 0,0 correspondant à l’intersection des axes x et y) figure dans le coin supérieur gauche de la scène. A partir de l’origine, les valeurs x sont positives vers la droite et négatives vers la gauche, tandis que, contrairement aux systèmes de graphes standard, les valeurs y sont positives vers le bas et négatives vers le haut. Par exemple, les lignes précédentes de code déplacent l’objet myShape vers la coordonnée x 17 (17 pixels sur la droite de l’origine) et la coordonnée y 212 (212 pixels sous l’origine). Par défaut, lorsqu’un objet d’affichage est créé dans ActionScript, les propriétés x et y sont toutes deux définies sur 0, plaçant ainsi l’objet dans le coin supérieur gauche de son contenu parent. Modification de la position relativement à la scène Il est important de se rappeler que les propriétés x et y se réfèrent toujours à la position de l’objet d’affichage par rapport aux coordonnées 0,0 des axes de son objet d’affichage parent. Ainsi, pour une occurrence de Shape (par exemple un cercle) contenue dans une occurrence de Sprite, mettre à zéro les propriétés x et y de l’objet Shape revient à placer le cercle dans le coin supérieur gauche de l’objet Sprite, qui n’est pas forcément le coin supérieur gauche de la scène. Pour positionner un objet par rapport aux coordonnées globales de la scène, utilisez la méthode globalToLocal() de tout objet d’affichage afin de convertir les coordonnées globales (scène) en coordonnées locales (conteneur de l’objet d’affichage), comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 181 Programmation de l’affichage Dernière mise à jour le 27/4/2013 // Position the shape at the top-left corner of the Stage, // regardless of where its parent is located. // Create a Sprite, positioned at x:200 and y:200. var mySprite:Sprite = new Sprite(); mySprite.x = 200; mySprite.y = 200; this.addChild(mySprite); // Draw a dot at the Sprite's 0,0 coordinate, for reference. mySprite.graphics.lineStyle(1, 0x000000); mySprite.graphics.beginFill(0x000000); mySprite.graphics.moveTo(0, 0); mySprite.graphics.lineTo(1, 0); mySprite.graphics.lineTo(1, 1); mySprite.graphics.lineTo(0, 1); mySprite.graphics.endFill(); // Create the circle Shape instance. var circle:Shape = new Shape(); mySprite.addChild(circle); // Draw a circle with radius 50 and center point at x:50, y:50 in the Shape. circle.graphics.lineStyle(1, 0x000000); circle.graphics.beginFill(0xff0000); circle.graphics.drawCircle(50, 50, 50); circle.graphics.endFill(); // Move the Shape so its top-left corner is at the Stage's 0, 0 coordinate. var stagePoint:Point = new Point(0, 0); var targetPoint:Point = mySprite.globalToLocal(stagePoint); circle.x = targetPoint.x; circle.y = targetPoint.y; Vous pouvez également utiliser la méthode localToGlobal() de la classe DisplayObject pour convertir les coordonnées locales en coordonnées de la scène. Déplacement des objets d’affichage à l’aide de la souris Vous pouvez autoriser un utilisateur à déplacer les objets d’affichage à l’aide de la souris par le biais de deux techniques distinctes dans ActionScript. Dans les deux cas, deux événements de souris sont utilisés : lorsque l’utilisateur appuie sur le bouton de gauche (l’objet reçoit alors l’instruction de suivre le curseur de la souris) et lorsqu’il le relâche (l’objet reçoit alors l’instruction de cesser de suivre le curseur de la souris). Remarque : Flash Player 11.3 et les versions ultérieures et AIR 3.3 et les versions ultérieures : vous pouvez également utiliser l’événement MouseEvent.RELEASE_OUTSIDE dans le cas d’un utilisateur qui relâche le bouton de la souris en dehors des limites du Sprite conteneur. La première technique, basée sur la méthode startDrag(), est plus simple, mais plus limitée. Lorsque l’utilisateur appuie sur le bouton de la souris, la méthode startDrag() de l’objet d’affichage à faire glisser est appelée. Lorsque l’utilisateur relâche le bouton de la souris, la méthode stopDrag() est appelée. Puisque la classe Sprite définit ces deux fonctions, l’objet déplacé doit être un Sprite ou l’une de ses sous-classes. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 182 Programmation de l’affichage Dernière mise à jour le 27/4/2013 // This code creates a mouse drag interaction using the startDrag() // technique. // square is a MovieClip or Sprite instance). import flash.events.MouseEvent; // This function is called when the mouse button is pressed. function startDragging(event:MouseEvent):void { square.startDrag(); } // This function is called when the mouse button is released. function stopDragging(event:MouseEvent):void { square.stopDrag(); } square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); square.addEventListener(MouseEvent.MOUSE_UP, stopDragging); Cette technique présente un désavantage relativement important : l’utilisation de startDrag() ne permet de faire glisser qu’un seul élément à la fois. Si un objet d’affichage est en cours de glissement et que la méthode startDrag() est appelée sur un autre objet d’affichage, le premier objet cesse immédiatement de suivre la souris. Par exemple, si la fonction startDragging() est modifiée comme indiqué, seul l’objet circle est déplacé par glissement, bien que la méthode square.startDrag() ait été appelée : function startDragging(event:MouseEvent):void { square.startDrag(); circle.startDrag(); } Puisqu’un seul objet à la fois peut être déplacé par glissement par le biais de startDrag(), la méthode stopDrag() peut être appelée sur n’importe quel objet d’affichage et arrête tout objet en cours de glissement. Pour déplacer plusieurs objets d’affichage, ou pour éviter tout risque de conflit au cas où plusieurs objets seraient susceptibles d’utiliser startDrag(), il est préférable d’utiliser la technique de suivi de la souris pour créer l’effet de glisser-déposer. Avec cette technique, lorsque l’utilisateur appuie sur le bouton de la souris, une fonction est enregistrée en tant qu’écouteur de l’événement mouseMove de la scène. Cette fonction, qui est alors appelée à chaque déplacement de la souris, entraîne le saut de l’objet déplacé vers la coordonnée x, y de la souris. Une fois le bouton de la souris relâché, la fonction n’est plus enregistrée en tant qu’écouteur. Elle n’est donc plus appelée lorsque la souris est déplacée et l’objet cesse de suivre le curseur. Le code suivant illustre cette technique : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 183 Programmation de l’affichage Dernière mise à jour le 27/4/2013 // This code moves display objects using the mouse-following // technique. // circle is a DisplayObject (e.g. a MovieClip or Sprite instance). import flash.events.MouseEvent; var offsetX:Number; var offsetY:Number; // This function is called when the mouse button is pressed. function startDragging(event:MouseEvent):void { // Record the difference (offset) between where // the cursor was when the mouse button was pressed and the x, y // coordinate of the circle when the mouse button was pressed. offsetX = event.stageX - circle.x; offsetY = event.stageY - circle.y; // tell Flash Player to start listening for the mouseMove event stage.addEventListener(MouseEvent.MOUSE_MOVE, dragCircle); } // This function is called when the mouse button is released. function stopDragging(event:MouseEvent):void { // Tell Flash Player to stop listening for the mouseMove event. stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragCircle); } // This function is called every time the mouse moves, // as long as the mouse button is pressed down. function dragCircle(event:MouseEvent):void { // Move the circle to the location of the cursor, maintaining // the offset between the cursor's location and the // location of the dragged object. circle.x = event.stageX - offsetX; circle.y = event.stageY - offsetY; // Instruct Flash Player to refresh the screen after this event. event.updateAfterEvent(); } circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging); Outre le suivi du curseur par un objet d’affichage, il est souvent préférable de positionner l’objet déplacé à l’avant de l’affichage, créant ainsi une impression de flottement au-dessus de tous les autres objets. Supposons, par exemple, que deux objets, un cercle et un carré, puissent tous deux être déplacés à l’aide de la souris. Si le cercle figure sous le carré sur la liste d’affichage et que vous cliquez et faites glisser le cercle pour placer le curseur au-dessus du carré, il semble glisser derrière le carré, brisant ainsi l’illusion du glisser-déposer. Vous pouvez procéder de sorte que lorsque vous cliquez sur le cercle, il passe en première position dans la liste d’affichage et s’affiche ainsi par-dessus tout autre contenu. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 184 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Le code suivant (adapté de l’exemple précédent) permet de déplacer deux objets d’affichage, un cercle et un carré, à l’aide de la souris. Lorsque le bouton de la souris est pressé au-dessus de l’un d’eux, cet élément est amené en haut de la liste d’affichage de la scène, afin que l’élément déplacé passe toujours devant les autres. (Tout nouveau code ou code modifié extrait du code précédent est imprimé en gras.) // This code creates a drag-and-drop interaction using the mouse-following // technique. // circle and square are DisplayObjects (e.g. MovieClip or Sprite // instances). import flash.display.DisplayObject; import flash.events.MouseEvent; var offsetX:Number; var offsetY:Number; var draggedObject:DisplayObject; // This function is called when the mouse button is pressed. function startDragging(event:MouseEvent):void { // remember which object is being dragged draggedObject = DisplayObject(event.target); // Record the difference (offset) between where the cursor was when // the mouse button was pressed and the x, y coordinate of the // dragged object when the mouse button was pressed. offsetX = event.stageX - draggedObject.x; offsetY = event.stageY - draggedObject.y; // move the selected object to the top of the display list stage.addChild(draggedObject); // Tell Flash Player to start listening for the mouseMove event. stage.addEventListener(MouseEvent.MOUSE_MOVE, dragObject); } // This function is called when the mouse button is released. function stopDragging(event:MouseEvent):void { // Tell Flash Player to stop listening for the mouseMove event. stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragObject); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 185 Programmation de l’affichage Dernière mise à jour le 27/4/2013 // This function is called every time the mouse moves, // as long as the mouse button is pressed down. function dragObject(event:MouseEvent):void { // Move the dragged object to the location of the cursor, maintaining // the offset between the cursor's location and the location // of the dragged object. draggedObject.x = event.stageX - offsetX; draggedObject.y = event.stageY - offsetY; // Instruct Flash Player to refresh the screen after this event. event.updateAfterEvent(); } circle.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); circle.addEventListener(MouseEvent.MOUSE_UP, stopDragging); square.addEventListener(MouseEvent.MOUSE_DOWN, startDragging); square.addEventListener(MouseEvent.MOUSE_UP, stopDragging); Pour créer un effet plus sophistiqué, par exemple pour un jeu où des jetons ou des cartes passent d’une pile à l’autre, il est possible d’ajouter l’objet déplacé à la liste d’affichage de la scène lorsqu’il est « pris », puis de l’ajouter à une autre liste d’affichage (la « pile » sur laquelle il est déposé) lors du relâchement du bouton de souris. Enfin, pour optimiser l’effet, vous pourriez appliquer un filtre Ombre portée à l’objet d’affichage lorsque vous cliquez dessus (en début de glissement) et supprimer l’ombre portée lorsque vous relâchez l’objet. Pour plus d’informations sur le filtre Ombre portée et tout autre filtre appliqué aux objets d’affichage en ActionScript, voir « Filtrage des objets d’affichage » à la page 276. Défilement horizontal ou vertical des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si la taille d’un objet d’affichage est trop élevée pour la zone où vous souhaitez l’afficher, vous disposez de la propriété scrollRect pour définir la zone visible de l’objet d’affichage. Par ailleurs, en modifiant la propriété scrollRect en réponse à une action de l’utilisateur, vous pouvez entraîner un défilement vers la gauche ou la droite ou vers le haut ou le bas. La propriété scrollRect est une occurrence de la classe Rectangle, qui combine les valeurs requises pour définir une zone rectangulaire en tant qu’objet unique. Pour définir initialement la zone visible de l’objet d’affichage, créez une occurrence de Rectangle et affectez-la à la propriété scrollRect de l’objet. Par la suite, pour obtenir un défilement horizontal ou vertical, il suffit de lire la propriété scrollRect dans une variable Rectangle séparée et de changer la propriété voulue (par exemple, modifier la propriété x de l’occurrence de Rectangle pour un défilement horizontal, ou sa propriété y pour un défilement vertical). Vous réaffectez ensuite cette occurrence de Rectangle à la propriété scrollRect pour avertir l’objet d’affichage du changement de valeur. Par exemple, le code suivant définit la zone visible d’un objet TextField nommé bigText dont la hauteur est trop importante pour les dimensions du fichier SWF. Lorsque l’utilisateur clique sur les deux boutons nommés up et down, les fonctions appelées entraînent le défilement vertical du contenu de l’objet TextField en modifiant la propriété y de l’occurrence de Rectangle scrollRect. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 186 Programmation de l’affichage Dernière mise à jour le 27/4/2013 import flash.events.MouseEvent; import flash.geom.Rectangle; // Define the initial viewable area of the TextField instance: // left: 0, top: 0, width: TextField's width, height: 350 pixels. bigText.scrollRect = new Rectangle(0, 0, bigText.width, 350); // Cache the TextField as a bitmap to improve performance. bigText.cacheAsBitmap = true; // called when the "up" button is clicked function scrollUp(event:MouseEvent):void { // Get access to the current scroll rectangle. var rect:Rectangle = bigText.scrollRect; // Decrease the y value of the rectangle by 20, effectively // shifting the rectangle down by 20 pixels. rect.y -= 20; // Reassign the rectangle to the TextField to "apply" the change. bigText.scrollRect = rect; } // called when the "down" button is clicked function scrollDown(event:MouseEvent):void { // Get access to the current scroll rectangle. var rect:Rectangle = bigText.scrollRect; // Increase the y value of the rectangle by 20, effectively // shifting the rectangle up by 20 pixels. rect.y += 20; // Reassign the rectangle to the TextField to "apply" the change. bigText.scrollRect = rect; } up.addEventListener(MouseEvent.CLICK, scrollUp); down.addEventListener(MouseEvent.CLICK, scrollDown); Comme le montre cet exemple, lorsque vous utilisez la propriété scrollRect d’un objet d’affichage, il est préférable de spécifier que Flash ou AIR doit mettre en cache le contenu de l’objet sous forme de bitmap, à l’aide de la propriété cacheAsBitmap. Ainsi, Flash Player et AIR n’ont pas à redessiner le contenu complet de l’objet d’affichage à chaque défilement de celui-ci, et peuvent utiliser le bitmap mis en cache pour afficher la portion concernée directement à l’écran. Pour plus d’informations, voir « Mise en cache des objets d’affichage » à la page 189. Manipulation de la taille et de l’échelle des objets Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La taille d’un objet d’affichage peut être obtenue et modifiée de deux façons, en utilisant soit les propriétés de dimensions (width et height), soit les propriétés d’échelle (scaleX et scaleY). Chaque objet d’affichage possède une propriété width et une propriété height, qui sont initialement définies sur la taille de l’objet en pixels. Vous pouvez lire les valeurs de ces propriétés pour mesurer la taille de l’objet d’affichage. Vous pouvez également stipuler de nouvelles valeurs pour modifier la taille de l’objet, comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 187 Programmation de l’affichage Dernière mise à jour le 27/4/2013 // Resize a display object. square.width = 420; square.height = 420; // Determine the radius of a circle display object. var radius:Number = circle.width / 2; Modifier les propriétés height ou width d’un objet d’affichage modifie l’échelle de ce dernier. En d’autres termes, son contenu est étiré ou comprimé en fonction de la taille de la nouvelle zone. Si l’objet d’affichage ne contient que des formes vectorielles, elles sont redessinées à la nouvelle échelle, sans perte de qualité. Tout élément graphique bitmap de l’objet d’affichage est mis à l’échelle au lieu d’être redessiné. Ainsi, une photo numérique dont la largeur et la hauteur augmentent de sorte à dépasser les dimensions réelles des informations relatives aux pixels de l’image est pixellisée, ce qui lui donne un aspect irrégulier. Lorsque vous modifiez les propriétés width ou height d’un objet d’affichage, Flash Player et AIR mettent également à jour les propriétés scaleX ou scaleY de l’objet. Remarque : les objets TextField ne respectent pas ce comportement de mise à l’échelle. Les champs de texte doivent se redimensionner automatiquement pour gérer le retour à la ligne automatique et les tailles de police. Leurs valeurs scaleX et scaleY sont donc réinitialisées à 1 au terme du redimensionnement. Toutefois, si vous ajustez la valeur scaleX ou scaleY d’un objet TextField, les valeurs de largeur et de hauteur sont modifiées en fonction des valeurs de mise à l’échelle que vous indiquez. Ces propriétés représentent la taille relative de l’objet d’affichage par rapport à sa taille d’origine. Les propriétés scaleX et scaleY utilisent des valeurs exprimées sous forme de fractions (décimales) pour représenter le pourcentage. Par exemple, si la propriété width d’un objet d’affichage a été réduite à la moitié de sa largeur originale, la propriété scaleX de cet objet prendra la valeur 0,5, soit 50 %. Si sa hauteur a doublé, sa propriété scaleY prendra la valeur 2, soit 200 %. // circle is a display object whose width and height are 150 pixels. // At original size, scaleX and scaleY are 1 (100%). trace(circle.scaleX); // output: 1 trace(circle.scaleY); // output: 1 // When you change the width and height properties, // Flash Player changes the scaleX and scaleY properties accordingly. circle.width = 100; circle.height = 75; trace(circle.scaleX); // output: 0.6622516556291391 trace(circle.scaleY); // output: 0.4966887417218543 Les changements de taille ne sont pas proportionnels. En d’autres termes, si vous modifiez la hauteur d’un carré, mais non sa largeur, ses proportions ne sont plus identiques et il devient un rectangle au lieu d’un carré. Si vous souhaitez modifier relativement la taille d’un objet d’affichage, vous pouvez définir les valeurs des propriétés scaleX et scaleY pour redimensionner l’objet, plutôt que définir les propriétés width ou height. Par exemple, ce code modifie la propriété width de l’objet d’affichage appelé square, puis modifie l’échelle verticale (scaleY) en fonction de l’échelle horizontale, afin que la taille du carré demeure proportionnelle. // Change the width directly. square.width = 150; // Change the vertical scale to match the horizontal scale, // to keep the size proportional. square.scaleY = square.scaleX; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 188 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Contrôle de la distorsion lors de la mise à l’échelle Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures En règle générale, lorsqu’un objet d’affichage est mis à l’échelle (s’il est étiré horizontalement, par exemple), la distorsion résultante est répartie équitablement dans l’objet, de sorte que chaque partie soit soumise à un étirement identique. Pour les graphiques et éléments de conception, cette technique correspond probablement au résultat escompté. Toutefois, il est parfois préférable de garder le contrôle sur les parties de l’objet qui seront étirées et celles qui ne le seront pas. Un exemple courant est celui d’un bouton représenté par un rectangle aux angles arrondis. Lors d’une mise à l’échelle normale, les angles du bouton sont étirés, entraînant ainsi la modification de leur rayon lorsque le bouton est redimensionné. Mais dans ce cas précis, il serait préférable de contrôler la mise à l’échelle, c’est-à-dire de pouvoir désigner certaines zones qui seront mises à l’échelle (les côtés) et celles qui ne le seront pas (les angles), afin que le changement d’échelle ne provoque pas de distorsion visible. Vous disposez de la mise à l’échelle à 9 découpes (Echelle-9) pour créer des objets d’affichage dont vous contrôlez le mode de mise à l’échelle. La mise à l’échelle à 9 découpes permet de diviser l’objet d’affichage en neuf rectangles distincts (grille de 3 sur 3). Ces rectangles ne sont pas obligatoirement de la même taille, car l’utilisateur choisit l’emplacement des lignes de séparation. Tout contenu placé dans les quatre rectangles de coin (tels que les angles arrondis d’un bouton) n’est ni étiré, ni comprimé lors de la mise à l’échelle de l’objet d’affichage. Les rectangles placés en haut au centre et en bas au centre sont mis à l’échelle horizontalement, mais non verticalement, tandis que les rectangles centraux de gauche et de droite sont mis à l’échelle verticalement, mais non horizontalement. Le rectangle central est mis à l’échelle horizontalement et verticalement. Ainsi, si vous créez un objet d’affichage et souhaitez qu’une partie du contenu ne subisse jamais de mise à l’échelle, il vous suffit de placer les lignes de séparation de la grille de mise à l’échelle à 9 découpes de telle sorte que ce contenu se trouve dans l’un des rectangles des angles. En ActionScript, il suffit de définir une valeur pour la propriété scale9Grid d’un objet d’affichage pour activer la mise à l’échelle à 9 découpes pour cet objet et définir la taille des rectangles de la grille. Vous utilisez une occurrence de la classe Rectangle en tant que valeur de la propriété scale9Grid, comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 189 Programmation de l’affichage Dernière mise à jour le 27/4/2013 myButton.scale9Grid = new Rectangle(32, 27, 71, 64); Les quatre paramètres du constructeur Rectangle sont la coordonnée x, la coordonnée y, la largeur et la hauteur. Dans cet exemple, l’angle supérieur gauche du rectangle est placé au point x : 32, y : 27 sur l’objet d’affichage appelé myButton. Le rectangle mesure 71 pixels de large et 64 pixels de haut (son bord droit correspond à la coordonnée x 103 sur l’objet d’affichage et son bord inférieur à la coordonnée y 92 sur l’objet d’affichage). La zone figurant dans la région définie par l’occurrence de Rectangle représente le rectangle central de la grille Echelle- 9. Les autres rectangles sont calculés par Flash Player et AIR en prolongeant les côtés de l’occurrence de Rectangle, comme indiqué : Dans ce cas de figure, lorsque la mise à l’échelle du bouton augmente ou diminue, les angles arrondis ne sont ni étirés, ni comprimés, mais les autres zones sont ajustées en conséquence. A. myButton.width = 131;myButton.height = 106; B. myButton.width = 73;myButton.height = 69; C. myButton.width = 54;myButton.height = 141; Mise en cache des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Que vous créiez une application ou des animations scriptées complexes, vous devez considérer la performance et l’optimisation, à mesure que la taille de vos conceptions Flash augmente. Lorsque votre contenu demeure statique (par exemple une occurrence de Shape rectangulaire), Flash et AIR ne l’optimisent pas. Par conséquent, lorsque vous modifiez la position du rectangle, Flash Player ou AIR redessine la totalité de l’occurrence de Shape. Vous pouvez mettre en cache des objets d’affichage spécifiques pour améliorer les performances de votre fichier SWF. L’objet d’affichage est essentiellement une surface, c’est-à-dire une version bitmap des données vectorielles de l’occurrence, données non destinées à être considérablement modifiées tout au long de la vie de votre fichier SWF. Ainsi, les occurrences pour lesquelles la mise en cache est activée ne sont pas continuellement redessinées pendant la lecture du fichier SWF, et le rendu de ce dernier est plus rapide. Remarque : vous pouvez mettre à jour les données vectorielles au moment de la recréation de la surface. Ainsi, les données vectorielles mises en cache dans la surface ne doivent pas nécessairement être les mêmes pour l’ensemble du fichier SWF. A B C GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 190 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Pour qu’un objet d’affichage mette en cache sa représentation sous forme de bitmap, il suffit d’activer sa propriété cacheAsBitmap (true). Flash Player ou AIR crée un objet de surface pour l’occurrence, correspondant à une image bitmap mise en cache et non à des données vectorielles. Si vous modifiez les limites de l’objet d’affichage, la surface est recréée et non redimensionnée. Les surfaces peuvent s’imbriquer dans d’autres surfaces. La surface copiera l’image bitmap sur sa surface parent. Pour plus d’informations, voir « Activation de la mise en cache sous forme de bitmap » à la page 192. Les propriétés opaqueBackground et scrollRect de la classe DisplayObject sont liées à la mise en cache sous forme de bitmap par le biais de la propriété cacheAsBitmap. Bien que ces trois propriétés soient indépendantes l’une de l’autre, opaqueBackground et scrollRect ne sont utiles que lorsqu’un objet est mis en cache sous forme de bitmap. Les avantages des propriétés opaqueBackground et scrollRect en termes de performances ne sont visibles que si cacheAsBitmap est définie sur true. Pour plus d’informations sur le défilement du contenu des objets d’affichage, voir « Défilement horizontal ou vertical des objets d’affichage » à la page 185. Pour plus d’informations sur la définition d’un arrière-plan opaque, voir « Définition d’un arrière-plan opaque » à la page 192. Pour plus d’informations sur le masquage du canal alpha, qui demande que vous définissiez la propriété cacheAsBitmap sur true, voir « Masquage des objets d’affichage » à la page 197. Quand activer la mise en cache Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’activation de la mise en cache d’un objet d’affichage crée une surface dont les avantages sont multiples, par exemple pour accélérer le rendu des animations vectorielles complexes. Lorsque vous souhaitez activer la mise en cache, plusieurs scénarios sont disponibles. Il pourrait sembler avantageux de toujours activer la mise en cache pour améliorer les performances de votre fichier SWF. Cependant, dans certains cas, cette opération n’a aucun effet bénéfique et risque même parfois de ralentir le fichier. Cette section présente des cas où la mise en cache s’avère bénéfique, et d’autres où il est préférable d’utiliser les objets de façon normale. Les performances générales des données mises en cache dépendent de la complexité des données vectorielles de vos occurrences, de la quantité de modifications et de la définition, ou non, de la propriété opaqueBackground. Si vous modifiez de petites zones, la différence entre l’utilisation d’une surface et celle de données vectorielles sera négligeable. Vous pouvez dans ce cas tester les deux scénarios avant de déployer votre application. Quand utiliser la mise en cache sous forme de bitmap Ce qui suit est une série de scénarios dans lesquels vous pouvez voir les bénéfices significatifs qui résultent de la mise en cache sous forme de bitmap. • Image complexe d’arrière-plan : application qui contient une image d’arrière-plan complexe de données vectorielles (peut-être une image à laquelle vous avez appliqué la commande de traçage de bitmap ou illustration créée dans Adobe Illustrator®). Vous pouvez animer les caractères sur l’arrière-plan, ce qui ralentit l’animation parce que l’arrière-plan a besoin de continuellement régénérer les données vectorielles. Pour améliorer les performances, vous pouvez définir la propriété opaqueBackground de l’objet d’affichage d’arrière-plan sur true. L’arrière-plan est rendu en tant que bitmap et peut être redessiné rapidement pour que l’animation soit lue beaucoup plus vite. • Champ de texte de défilement : application qui affiche une grande quantité de texte dans un champ de texte de défilement. Vous pouvez placer le champ de texte dans un objet d’affichage que vous définissez comme déroulant à l’aide de bornes de déroulement (propriété scrollRect). Ceci permet un déroulement de pixels rapide pour l’occurrence indiquée. Quand un utilisateur déroule l’occurrence d’objet d’affichage, Flash Player ou AIR fait défiler les pixels déroulés vers le haut et génère la zone nouvellement exposée au lieu de régénérer tout le champ de texte. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 191 Programmation de l’affichage Dernière mise à jour le 27/4/2013 • Système de fenêtres : application comportant un système complexe de chevauchement de fenêtres. Chaque fenêtre peut être ouverte ou fermée (par exemple, les fenêtres du navigateur Web). Si vous marquez chaque fenêtre en tant que surface (en définissant la propriété cacheAsBitmap sur true), chaque fenêtre est isolée et mise en cache. Les utilisateurs peuvent faire glisser les fenêtres de manière à ce qu’elles se chevauchent. Chaque fenêtre n’a pas besoin de régénérer le contenu vectoriel. • Masquage du canal alpha : si vous utilisez le masquage du canal alpha, vous devez définir la propriété cacheAsBitmap sur true. Pour plus d’informations, voir « Masquage des objets d’affichage » à la page 197. Activer la mise en cache sous forme de bitmap dans tous ces scénarios améliore la réactivité et l’interactivité de l’application en optimisant les graphiques vectoriels. Par ailleurs, lorsque vous appliquez un filtre à un objet d’affichage, cacheAsBitmap est automatiquement définie sur true, même si vous l’avez explicitement définie sur false. Si vous supprimez tous les filtres appliqués à l’objet d’affichage, la propriété cacheAsBitmap retrouve la valeur précédemment définie. Quand éviter d’utiliser la mise en cache sous forme de bitmap L’utilisation à mauvais escient de cette fonction risque d’affecter les performances du fichier SWF. Avant d’utiliser la mise en cache sous forme de bitmap, tenez compte des considérations suivantes : • N’abusez pas des surfaces (objets d’affichage avec mise en cache activée). Chaque surface utilise plus de mémoire qu’un objet d’affichage standard, ce qui signifie que vous ne devez activer les surfaces que lorsqu’il est nécessaire d’améliorer les performances de rendu. Un bitmap caché utilise beaucoup plus de mémoire qu’un objet d’affichage standard. Par exemple, si la taille d’une occurrence de Sprite sur la scène correspond à 250 pixels sur 250 pixels, elle est susceptible d’utiliser en cache 250 Ko au lieu d’1 Ko pour une occurrence de Sprite standard (non en cache). • Evitez de zoomer dans les surfaces cachées. Si vous abusez de la mise en cache sous forme de bitmap, une grande quantité de mémoire sera occupée (voir la puce précédente), surtout si vous zoomez sur le contenu. • Utilisez des surfaces essentiellement non statiques (sans animation) pour les occurrences d’objets d’affichage. Vous pouvez faire glisser ou déplacer l’occurrence, mais son contenu ne doit pas être animé ni subir de nombreuses modifications (les animations ou les contenus qui changent sont plus fréquents lorsqu’une occurrence de MovieClip contient une animation ou une occurrence de Video). Par exemple, si vous faites pivoter ou transformez une occurrence, la différence entre la surface et les données vectorielles rend le traitement difficile et affecte le fichier SWF. • Panacher des surfaces avec des données vectorielles accroît la charge de traitement de Flash Player et AIR (et quelquefois de l’ordinateur). Dans la mesure du possible, regroupez les surfaces, en particulier lorsque vous créez des applications à fenêtres. • Ne mettez pas en cache les objets dont les graphiques sont fréquemment modifiés. A chaque fois que vous exécutez une mise à l’échelle, inclinaison ou rotation de l’objet d’affichage, modifiez l’alpha ou la transformation de couleur, déplacez des objets d’affichage enfant ou tracez à l’aide de la propriété graphique, la mémoire cache des bitmaps est régénérée. Si cette opération se produit à chaque image, le moteur d’exécution doit tracer l’objet dans une image bitmap, puis copier celle-ci sur la scène, d’où une charge de travail accrue par rapport au simple tracé de l’objet non mis en cache sur la scène. L’impact sur les performances de la mise en cache par rapport à la fréquence de mise à jour varie selon la complexité et la taille de l’objet d’affichage et ne peut être déterminé qu’en testant le contenu concerné. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 192 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Activation de la mise en cache sous forme de bitmap Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour activer la mise en cache d’un objet d’affichage sous forme de bitmap, définissez sa propriété cacheAsBitmap sur true : mySprite.cacheAsBitmap = true; Après avoir défini la propriété cacheAsBitmap sur true, vous remarquerez que l’objet d’affichage accroche automatiquement les pixels sur les coordonnées entières. Lorsque vous testez le fichier SWF, vous devriez remarquer que le rendu d’une animation associée à une image vectorielle complexe est bien plus rapide. Une surface (bitmap en cache) n’est pas créée même quand cacheAsBitmap est défini sur true s’il se produit l’un ou l’autre des événements suivants : • Le bitmap fait plus de 2 880 pixels en hauteur ou en largeur. • Il est impossible d’allouer de la mémoire pour l’image bitmap. Matrices de transformation des images bitmap mises en cache Adobe AIR 2.0 et les versions ultérieures (profil mobile) Dans les applications AIR pour périphériques mobiles, vous devriez définir la propriété cacheAsBitmapMatrix à chaque fois que vous définissez la propriété cacheAsBitmap. Définir cette propriété permet d’appliquer un large éventail de transformations à l’objet d’affichage sans déclencher un nouveau rendu. mySprite.cacheAsBitmap = true; mySprite.cacheAsBitmapMatrix = new Matrix(); Lorsque vous définissez cette propriété, vous pouvez appliquer la transformation complémentaire suivante à l’objet d’affichage sans mettre à nouveau l’objet en cache : • Déplacement ou translation sans accrochage de pixel • Rotation • Mise à l’échelle • Inclinaison • Modification de l’alpha (transparence comprise entre 0 et 100 %) Ces transformations sont appliquées directement à l’image bitmap mise en cache. Définition d’un arrière-plan opaque Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez définir un arrière-plan opaque pour un objet d’affichage. Par exemple, si l’arrière-plan de votre fichier SWF contient une illustration vectorielle complexe, vous pouvez définir la propriété opaqueBackground sur une couleur donnée (en général la même couleur que la scène). La couleur est stipulée sous forme de nombre (généralement une valeur hexadécimale). L’arrière-plan est alors considéré comme un bitmap, ce qui permet d’optimiser les performances. Lorsque vous définissez cacheAsBitmap sur true et la propriété opaqueBackground sur une couleur donnée, la propriété opaqueBackground assure l’opacité du bitmap interne et un rendu plus rapide. Si vous ne définissez pas cacheAsBitmap sur true, la propriété opaqueBackground ajoute une forme carrée vectorielle opaque à l’arrière-plan de l’objet d’affichage. Elle ne crée pas automatiquement un bitmap. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 193 Programmation de l’affichage Dernière mise à jour le 27/4/2013 L’exemple suivant décrit comment définir l’arrière-plan d’un objet d’affichage pour optimiser les performances : myShape.cacheAsBitmap = true; myShape.opaqueBackground = 0xFF0000; Dans ce cas, la couleur d’arrière-plan de l’objet Shape appelé myShape est définie sur rouge (0xFF0000). Si l’on suppose que l’occurrence de Shape contient un triangle vert, sur une scène dotée d’un fond blanc le résultat sera un triangle vert sur le fond rouge défini par le cadre de sélection de l’occurrence de Shape (le rectangle qui entoure entièrement Shape). Ce code serait bien entendu plus logique s’il était utilisé avec une scène dotée d’un arrière-plan rouge uni. Si l’arrièreplan était d’une autre couleur, celle-ci remplacerait le rouge. Par exemple, dans un fichier SWF doté d’un arrière-plan blanc, la propriété opaqueBackground serait probablement définie sur 0xFFFFFF, soit un blanc pur. Application de modes de fondu Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les modes de fondu supposent d’associer les couleurs d’une image (l’image de base) à celles d’une autre image (l’image mélangée) afin de produire une troisième image, qui est celle qui sera en fait affichée à l’écran. Chaque valeur de pixels d’une image est traitée avec la valeur de pixels correspondante de l’autre image afin d’obtenir un résultat présentant une valeur de pixels de position identique. Tous les objets d’affichage possèdent une propriété blendMode qui peut être définie sur l’un des modes de fondu cidessous. Les valeurs ci-dessous sont des constantes définies dans la classe BlendMode. Vous pouvez également utiliser les valeurs String (entre parenthèses) correspondant aux valeurs réelles des constantes. • BlendMode.ADD ("add") : s’utilise couramment pour créer un effet de dissolution animée entre deux images en éclaircissant progressivement leurs couleurs. • BlendMode.ALPHA ("alpha") : fréquemment utilisé pour appliquer la transparence de l’avant-plan à l’arrière-plan. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.DARKEN ("darken") : s’utilise couramment pour superposer un type. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.DIFFERENCE ("difference") : s’utilise couramment pour créer des couleurs plus vives. • BlendMode.ERASE ("erase") : s’utilise couramment pour découper (effacer) une partie de l’arrière-plan à l’aide de l’alpha d’avant-plan. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.HARDLIGHT ("hardlight") : s’utilise couramment pour créer des effets d’ombrage. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.INVERT ("invert") : permet d’inverser l’arrière-plan. • BlendMode.LAYER ("layer") : permet d’imposer la création d’un tampon provisoire en vue de la précomposition d’un objet d’affichage spécifique. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.LIGHTEN ("lighten") : s’utilise couramment pour superposer un type. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.MULTIPLY ("multiply") : s’utilise couramment pour créer des ombres et des effets de profondeur. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 194 Programmation de l’affichage Dernière mise à jour le 27/4/2013 • BlendMode.NORMAL ("normal") : permet aux valeurs des pixels de l’image mélangée de supplanter celles de l’image de base. • BlendMode.OVERLAY ("overlay") : s’utilise couramment pour créer des effets d’ombrage. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.SCREEN ("screen") : s’utilise couramment pour créer des mises en surbrillance et des halos. • BlendMode.SHADER ("shader") : permet d’indiquer l’utilisation d’un shader de Pixel Bender pour créer un effet de mélange personnalisé. Pour plus d’informations sur l’utilisation des shaders, voir « Utilisation des shaders de Pixel Bender » à la page 310. (Pas de prise en charge en cas de rendu par processeur graphique.) • BlendMode.SUBTRACT ("subtract") : s’utilise couramment pour créer un effet de dissolution animée entre deux images en assombrissant progressivement leurs couleurs. Réglage des couleurs DisplayObject Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser les méthodes de la classe ColorTransform (flash.geom.ColorTransform) pour régler la couleur d’un objet d’affichage. Chaque objet d’affichage possède une propriété transform, qui est une occurrence de la classe Transform et contient des informations relatives aux diverses transformations appliquées à l’objet d’affichage (rotation, changements d’échelle ou de position, etc.). Outre ces informations sur les transformations géométriques, la classe Transform comprend également une propriété colorTransform, qui est une occurrence de la classe ColorTransform et permet de régler les couleurs de l’objet d’affichage Pour accéder aux informations de transformation d’un objet d’affichage, utilisez le code suivant : var colorInfo:ColorTransform = myDisplayObject.transform.colorTransform; Après avoir créé une occurrence de ColorTransform, vous pouvez lire les valeurs de ses propriétés pour connaître les transformations de couleur qui lui ont déjà été appliquées, et vous pouvez modifier ces valeurs pour changer les couleurs de l’objet. Pour mettre à jour l’objet d’affichage après toute modification, vous devez réaffecter l’occurrence de ColorTransform à la propriété transform.colorTransform. var colorInfo:ColorTransform = myDisplayObject.transform.colorTransform; // Make some color transformations here. // Commit the change. myDisplayObject.transform.colorTransform = colorInfo; Définition des valeurs de couleur à l’aide du code Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La propriété color de la classe ColorTransform permet d’affecter une valeur de couleur rouge, vert, bleu (RVB) déterminée à l’objet d’affichage. L’exemple suivant utilise la propriété color pour changer en bleu la couleur de l’objet d’affichage square lorsque l’utilisateur clique sur le bouton blueBtn : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 195 Programmation de l’affichage Dernière mise à jour le 27/4/2013 // square is a display object on the Stage. // blueBtn, redBtn, greenBtn, and blackBtn are buttons on the Stage. import flash.events.MouseEvent; import flash.geom.ColorTransform; // Get access to the ColorTransform instance associated with square. var colorInfo:ColorTransform = square.transform.colorTransform; // This function is called when blueBtn is clicked. function makeBlue(event:MouseEvent):void { // Set the color of the ColorTransform object. colorInfo.color = 0x003399; // apply the change to the display object square.transform.colorTransform = colorInfo; } blueBtn.addEventListener(MouseEvent.CLICK, makeBlue); Notez que si vous changez la couleur d’un objet d’affichage à l’aide de la propriété color, c’est la couleur de l’objet entier qui est modifiée, même s’il comportait plusieurs couleurs à l’origine. Par exemple, si un objet d’affichage contient un cercle vert en arrière-plan d’un texte noir, le choix du rouge pour la propriété color de l’occurrence de ColorTransform associée à cet objet transformera intégralement l’objet en rouge, cercle et texte compris (le texte ne sera donc plus lisible sur le fond de la même couleur). Modification des effets de couleur et de luminosité à l’aide du code Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Supposons qu’un objet d’affichage comporte plusieurs couleurs (par exemple une photo numérique) et que vous n’ayez pas l’intention de modifier la couleur de l’ensemble de l’objet, mais uniquement celle d’un de ses éléments sur la base des couleurs existantes. Dans ce scénario, la classe ColorTransform comprend une série de propriétés de multiplication et de dominante permettant d’effectuer ce type de réglage. Les propriétés de multiplication, appelées redMultiplier, greenMultiplier, blueMultiplier et alphaMultiplier, fonctionnent comme des filtres photographiques de couleur (ou des lunettes à verres de couleur) et amplifient ou diminuent certaines couleurs de l’objet d’affichage. Les propriétés de dominante (redOffset, greenOffset, blueOffset et alphaOffset) permettent d’ajouter à l’objet une quantité supplémentaire d’une certaine couleur, ou d’indiquer la valeur minimale que peut avoir une couleur particulière. Ces propriétés de multiplication et de dominante sont identiques aux réglages de couleurs avancés relatifs aux symboles de clips dans l’outil de programmation Flash lorsque vous sélectionnez Paramètres avancés dans le menu déroulant Couleur de l’Inspecteur des propriétés. Le code suivant charge une image JPEG et lui applique une transformation de couleur, qui ajuste les canaux rouge et vert lorsque le pointeur de la classe se déplace le long des axes x et y. Dans ce cas précis, comme aucune valeur de dominante n’est spécifiée, les valeurs de chaque canal colorimétrique seront un pourcentage de la valeur de couleur originale de l’image, c’est-à-dire que la valeur maximale de rouge ou de vert d’un pixel donné sera la quantité originale de vert ou de rouge de ce pixel. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 196 Programmation de l’affichage Dernière mise à jour le 27/4/2013 import flash.display.Loader; import flash.events.MouseEvent; import flash.geom.Transform; import flash.geom.ColorTransform; import flash.net.URLRequest; // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); // This function is called when the mouse moves over the loaded image. function adjustColor(event:MouseEvent):void { // Access the ColorTransform object for the Loader (containing the image) var colorTransformer:ColorTransform = loader.transform.colorTransform; // Set the red and green multipliers according to the mouse position. // The red value ranges from 0% (no red) when the cursor is at the left // to 100% red (normal image appearance) when the cursor is at the right. // The same applies to the green channel, except it's controlled by the // position of the mouse in the y axis. colorTransformer.redMultiplier = (loader.mouseX / loader.width) * 1; colorTransformer.greenMultiplier = (loader.mouseY / loader.height) * 1; // Apply the changes to the display object. loader.transform.colorTransform = colorTransformer; } loader.addEventListener(MouseEvent.MOUSE_MOVE, adjustColor); Rotation des objets Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La propriété rotation permet de faire pivoter les objets d’affichage. Vous pouvez lire cette valeur pour savoir si un objet a été soumis à une rotation. Vous pouvez également la définir sur un nombre (exprimé en degrés) représentant le montant de rotation à appliquer à l’objet. Par exemple, cette ligne de code fait pivoter l’objet square de 45 degrés (un huitième de tour complet) : square.rotation = 45; Vous pouvez également faire pivoter un objet d’affichage par le biais d’une matrice de transformation, décrite dans « Utilisation de la géométrie » à la page 218. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 197 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Application d’effets de fondu à des objets Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez contrôler la transparence d’un objet d’affichage de sorte à le rendre partiellement (ou totalement) transparent, ou modifier la transparence pour créer une impression d’apparition ou de disparition en fondu de l’objet. La propriété alpha de la classe DisplayObject définit la transparence (ou plus précisément l’opacité) d’un objet d’affichage. La propriété alpha peut être définie sur n’importe quelle valeur comprise entre 0 et 1, sachant que 0 correspond à une transparence totale et 1 à une opacité totale. Par exemple, le code suivant rend l’objet myBall transparent à 50 % lors d’un clic de souris : function fadeBall(event:MouseEvent):void { myBall.alpha = .5; } myBall.addEventListener(MouseEvent.CLICK, fadeBall); Vous pouvez également modifier la transparence d’un objet d’affichage en utilisant les réglages de couleur proposés par la classe ColorTransform. Pour plus d’informations, voir « Réglage des couleurs DisplayObject » à la page 194. Masquage des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser un objet d’affichage comme masque pour créer un « trou » laissant apparaître le contenu d’un autre objet. Définition d’un masque Pour indiquer qu’un objet d’affichage sera le masque d’un autre objet d’affichage, définissez l’objet masque comme propriété mask de l’objet à masquer : // Make the object maskSprite be a mask for the object mySprite. mySprite.mask = maskSprite; L’objet d’affichage masqué est révélé sous toutes les zones opaques (non transparentes) de l’objet d’affichage servant de masque. Par exemple, le code suivant crée une occurrence de Shape qui contient un carré rouge de 100 pixels sur 100 et une occurrence de Sprite contenant un cercle bleu d’un rayon de 25 pixels. Lorsque l’utilisateur clique sur le cercle, il devient le masque du carré, de sorte que l’unique partie du carré affichée est la section couverte par la partie pleine du cercle. En d’autres termes, seul un cercle rouge est visible. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 198 Programmation de l’affichage Dernière mise à jour le 27/4/2013 // This code assumes it's being run within a display object container // such as a MovieClip or Sprite instance. import flash.display.Shape; // Draw a square and add it to the display list. var square:Shape = new Shape(); square.graphics.lineStyle(1, 0x000000); square.graphics.beginFill(0xff0000); square.graphics.drawRect(0, 0, 100, 100); square.graphics.endFill(); this.addChild(square); // Draw a circle and add it to the display list. var circle:Sprite = new Sprite(); circle.graphics.lineStyle(1, 0x000000); circle.graphics.beginFill(0x0000ff); circle.graphics.drawCircle(25, 25, 25); circle.graphics.endFill(); this.addChild(circle); function maskSquare(event:MouseEvent):void { square.mask = circle; circle.removeEventListener(MouseEvent.CLICK, maskSquare); } circle.addEventListener(MouseEvent.CLICK, maskSquare); L’objet d’affichage qui sert de masque peut être glissé, animé, redimensionné dynamiquement et peut utiliser plusieurs formes au sein d’un masque unique. Il n’est pas nécessaire que l’objet qui fait office de masque soit ajouté à la liste d’affichage. Toutefois, pour que l’objet servant de masque soit mis à l’échelle lors de la mise à l’échelle de la scène ou pour activer l’interaction utilisateur avec le masque (opération de type glisser et redimensionner contrôlée par l’utilisateur, par exemple), vous devez l’ajouter à la liste d’affichage. L’indice de profondeur (z-index, pour l’ordre de superposition) des objets d’affichage n’a pas d’importance, dès lors que l’objet masque est ajouté à la liste d’affichage (l’objet servant de masque ne s’affiche pas à l’écran, sauf en tant que masque). Si l’objet servant de masque est une occurrence de MovieClip dotée de plusieurs images, il lit toutes les images de son scénario, comme il le ferait s’il ne faisait pas office de masque. Pour supprimer un masque, définissez la propriété mask sur null : // remove the mask from mySprite mySprite.mask = null; Il est impossible d’utiliser un masque pour en masquer un autre. Il est impossible de définir la propriété _alpha d’un objet d’affichage servant de masque. Seuls les remplissages sont utilisés dans un objet d’affichage employé comme masque ; les traits sont ignorés. AIR 2 Si un objet d’affichage masqué est mis en cache en définissant les propriétés cacheAsBitmap et cacheAsBitmapMatrix, le masque doit correspondre à un enfant de l’objet d’affichage masqué. De même, si l’objet d’affichage masqué est un descendant d’un conteneur d’objet d’affichage mis en cache, le masque et l’objet d’affichage doivent tous deux être des descendants du conteneur. Si l’objet masqué est un descendant de plusieurs conteneurs d’objet d’affichage mis en cache, le masque doit être un descendant du conteneur mis en cache le plus proche de l’objet masqué dans la liste d’affichage. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 199 Programmation de l’affichage Dernière mise à jour le 27/4/2013 A propos du masquage des polices de périphérique Vous pouvez utiliser un objet d’affichage pour masquer le texte défini dans une police de périphérique. Dans ce cas, le cadre de sélection rectangulaire du masque est utilisé comme forme de masquage. Ainsi, si vous créez un masque objet d’affichage non rectangulaire pour un texte de police de périphérique, le masque qui apparaît dans le fichier SWF prend la forme du cadre de sélection rectangulaire du masque, et non celle du masque en tant que tel. Masquage du canal alpha Le masquage du canal alpha est pris en charge si le masque et les objets d’affichage masqués utilisent la mise en cache sous forme de bitmap, comme illustré ci-après : // maskShape is a Shape instance which includes a gradient fill. mySprite.cacheAsBitmap = true; maskShape.cacheAsBitmap = true; mySprite.mask = maskShape; Une application du masquage du canal alpha consiste par exemple à appliquer un filtre à l’objet masque indépendamment d’un filtre appliqué à l’objet d’affichage masqué. Dans l’exemple suivant, un fichier d’image externe est chargé sur la scène. Cette image (ou, plus précisément, l’occurrence de Loader dans laquelle elle est chargée) correspondra à l’objet d’affichage masqué. Un ovale dégradé (centre noir uni dont les bords deviennent progressivement transparents) est dessiné sur l’image. Il s’agit-là du masque alpha. La mise en cache sous forme de bitmap est activée pour les deux objets d’affichage. L’ovale est défini en tant que masque de l’image, puis peut être déplacé. // This code assumes it's being run within a display object container // such as a MovieClip or Sprite instance. import flash.display.GradientType; import flash.display.Loader; import flash.display.Sprite; import flash.geom.Matrix; import flash.net.URLRequest; // Load an image and add it to the display list. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); // Create a Sprite. var oval:Sprite = new Sprite(); // Draw a gradient oval. var colors:Array = [0x000000, 0x000000]; var alphas:Array = [1, 0]; var ratios:Array = [0, 255]; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 200 Programmation de l’affichage Dernière mise à jour le 27/4/2013 var matrix:Matrix = new Matrix(); matrix.createGradientBox(200, 100, 0, -100, -50); oval.graphics.beginGradientFill(GradientType.RADIAL, colors, alphas, ratios, matrix); oval.graphics.drawEllipse(-100, -50, 200, 100); oval.graphics.endFill(); // add the Sprite to the display list this.addChild(oval); // Set cacheAsBitmap = true for both display objects. loader.cacheAsBitmap = true; oval.cacheAsBitmap = true; // Set the oval as the mask for the loader (and its child, the loaded image) loader.mask = oval; // Make the oval draggable. oval.startDrag(true); Animation des objets Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’animation consiste à faire bouger un élément ou à le faire progressivement évoluer. Les animations par script représentent un élément fondamental des jeux vidéo, et elles sont aussi fréquemment utilisées pour obtenir un résultat plus séduisant et ajouter des interactions à d’autres applications. Une animation par script est régie par un principe de base : il doit se produire une évolution et cette dernière doit être divisée en incréments, au fil du temps. Il est facile de répéter une opération en ActionScript, à l’aide d’une simple boucle. Toutefois, une boucle exécute toutes ses itérations avant de mettre à jour l’affichage. Pour créer une animation par script, vous devez écrire un code ActionScript qui exécute plusieurs fois une action au fil du temps et met également à jour l’écran à chaque exécution. Supposons par exemple que vous souhaitez créer une animation simple, telle qu’une balle qui traverse l’écran. ActionScript comprend un mécanisme simple qui permet de suivre le passage du temps et de mettre à jour l’écran en conséquence. En d’autres termes, vous pourriez écrire un code qui déplace la balle d’un petit incrément à chaque fois jusqu’à ce qu’elle atteigne sa destination. Après chaque déplacement, l’écran serait mis à jour, afin que l’utilisateur puisse visualiser le mouvement à l’écran. D’un point de vue pratique, il est logique de synchroniser l’animation par script avec la cadence du fichier SWF (en d’autres termes, de modifier une animation à chaque fois qu’une nouvelle image s’affiche ou devrait s’afficher), puisque cela permet de définir la fréquence des mises à jour de l’écran par Flash Player ou AIR. Chaque objet d’affichage possède un événement enterFrame qui est diffusé en fonction de la cadence d’affichage du fichier SWF (un événement par image). La plupart des développeurs qui créent une animation par script utilisent l’événement enterFrame pour générer des actions répétées au fil du temps. Vous pourriez écrire du code qui écoute l’événement enterFrame, déplace la balle animée d’un incrément déterminé à chaque image et, lorsque l’écran est mis à jour (à chaque image), la balle est redessinée à sa nouvelle position, créant ainsi un mouvement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 201 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Remarque : une autre technique pour exécuter une action de manière répétitive dans le temps consiste à utiliser la classe Timer. Une occurrence de Timer déclenche une notification d’événement après un délai horaire donné. Il est donc possible d’écrire du code effectuant une animation sur la base de l’événement timer de la classe Timer, en définissant un intervalle très court (une fraction de seconde). Pour plus d’informations sur l’utilisation de la classe Timer, voir « Contrôle des intervalles temporels » à la page 4. Dans l’exemple suivant, une occurrence circulaire de Sprite, appelée circle, est créée sur la scène. Lorsque l’utilisateur clique sur le cercle, une séquence animée par script débute et entraîne un fondu de circle (sa propriété alpha diminue) jusqu’à ce qu’il soit complètement transparent : import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; // draw a circle and add it to the display list var circle:Sprite = new Sprite(); circle.graphics.beginFill(0x990000); circle.graphics.drawCircle(50, 50, 50); circle.graphics.endFill(); addChild(circle); // When this animation starts, this function is called every frame. // The change made by this function (updated to the screen every // frame) is what causes the animation to occur. function fadeCircle(event:Event):void { circle.alpha -= .05; if (circle.alpha <= 0) { circle.removeEventListener(Event.ENTER_FRAME, fadeCircle); } } function startAnimation(event:MouseEvent):void { circle.addEventListener(Event.ENTER_FRAME, fadeCircle); } circle.addEventListener(MouseEvent.CLICK, startAnimation); Lorsque l’utilisateur clique sur le cercle, la fonction fadeCircle() est enregistrée en tant qu’écouteur de l’événement enterFrame. En d’autres termes, elle commence à être appelée une fois par image. Cette fonction provoque un fondu de l’objet circle en changeant sa propriété alpha, si bien qu’à chaque nouvelle image la valeur de la propriété alpha du cercle décroît de 0,05 (soit 5 %) et l’écran est actualisé. Au fil du temps, lorsque la valeur alpha correspond à 0 (auquel cas circle est complètement transparent), la fonction fadeCircle() est supprimée des écouteurs d’événement et l’animation s’arrête. Le même code permet, par exemple, de créer un mouvement animé au lieu d’un fondu. En substituant une autre propriété à alpha dans la fonction qui écoute l’événement enterFrame, cette propriété est animée. Par exemple, remplacer la ligne circle.alpha -= .05; par la ligne circle.x += 5; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 202 Programmation de l’affichage Dernière mise à jour le 27/4/2013 anime la propriété x. Le cercle se déplace alors vers la droite de la scène. La condition qui arrête l’animation peut être modifiée de sorte à arrêter l’animation (en d’autres termes, annuler l’enregistrement de l’écouteur enterFrame) lorsque la coordonnée x appropriée est atteinte. Orientation de la scène AIR 2.0 et les versions ultérieures Les périphériques mobiles réorientent généralement l’interface utilisateur de sorte à assurer un affichage à la verticale lorsque l’utilisateur fait pivoter le périphérique. Si vous activez l’orientation automatique dans votre application, le périphérique conserve l’orientation adéquate de l’écran, mais il vous incombe de vérifier que le contenu s’affiche correctement lorsque le format de la scène change. Si vous désactivez l’orientation automatique, l’écran du périphérique reste fixe, à moins que vous ne modifiiez l’orientation manuellement. Les applications AIR s’exécutent sur divers systèmes d’exploitation et périphériques mobiles. Le comportement d’orientation sous-jacent risque de varier selon le système d’exploitation, voire selon le périphérique sur un même système d’exploitation. Une stratégie de création simple adaptée à tous les périphériques et systèmes d’exploitation consiste à activer l’orientation automatique et à écouter les événements resize de l’objet Stage pour déterminer lorsqu’il est nécessaire d’actualiser la mise en forme de l’application. Si l’application prend en charge le format portrait uniquement ou le format paysage uniquement, vous pouvez également désactiver l’orientation automatique et définir le format géré dans le descripteur d’application AIR. Cette stratégie assure un comportement cohérent et sélectionne l’orientation la « plus » adaptée au format sélectionné. Par exemple, si vous activez le format paysage, l’orientation choisie convient aux périphériques dotés de claviers coulissants (en mode paysage). Identification du format et de l’orientation actuels de la scène L’orientation est indiquée relativement à la position normale du périphérique. Sur la plupart des périphériques, il existe une position verticale clairement identifiable. Cette position est considérée comme l’orientation par défaut. Les trois autres orientations possibles sont les suivantes : rotated left, rotated right et upside down. La classe StageOrientation intègre les constantes de type chaîne à utiliser lors de la définition ou de la comparaison de valeurs d’orientation. La classe Stage définit deux propriétés qui indiquent l’orientation, à savoir : • Stage.deviceOrientation : indique l’orientation physique du périphérique par rapport à la position par défaut. Remarque : l’orientation du périphérique n’est pas toujours disponible si l’application vient de démarrer ou si le périphérique est posé à plat. Dans ces cas de figure, l’orientation indiquée du périphérique correspond à unknown. • Stage.orientation : indique l’orientation de la scène par rapport à la position par défaut. Si vous avez activé l’orientation automatique, la scène pivote dans la direction opposée à celle du périphérique pour demeurer verticale. Les positions droite et gauche indiquées par la propriété orientation représentent donc l’opposé des positions indiquées par la propriété deviceOrientation. Ainsi, si deviceRotation indique rotated right, orientation indique rotated left. Pour identifier le format de la scène, il suffit de comparer la largeur et la hauteur actuelles de la scène : var aspect:String = this.stage.stageWidth >= this.stage.stageHeight ? StageAspectRatio.LANDSCAPE : StageAspectRatio.PORTRAIT; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 203 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Orientation automatique Si l’orientation automatique est activée et que l’utilisateur fait pivoter le périphérique, le système d’exploitation réoriente l’interface utilisateur entière, y compris la barre des tâches système et l’application. Le format de la scène passe du mode portrait au mode paysage, et vice versa. La modification du format entraîne également la modification des dimensions de la scène. Pour activer ou désactiver l’orientation automatique lors de l’exécution, définissez la propriété autoOrients de l’objet Stage sur true ou false. Vous pouvez définir la valeur initiale de cette propriété dans le descripteur d’application AIR avec l’élément . (Notez que dans les versions d’AIR antérieures à 2.6, autoOrients est une propriété disponible en lecture seule, que vous ne pouvez définir que dans le descripteur d’application.) Si vous spécifiez le format paysage ou portrait et activez l’orientation automatique, AIR définit l’orientation automatique au format spécifié. Modification des dimensions de la scène En cas de modification des dimensions de la scène, le contenu de cette dernière est mis à l’échelle et repositionné comme stipulé par les propriétés scaleMode et align de l’objet Stage. Dans la plupart des cas, il n’est pas recommandé de se fier au comportement automatique défini par les paramètres scaleMode de l’objet Stage. Pour prendre en charge plusieurs formats, il est préférable de modifier la mise en forme des graphiques et des composants ou de rafraîchir ces derniers. (Une logique de mise en forme souple présente également l’avantage d’assurer un meilleur fonctionnement de l’application sur des périphériques aux tailles d’écran et formats distincts.) L’illustration suivante présente les effets des différents paramètres scaleMode lors de la rotation d’un périphérique mobile standard : Rotation d’un format paysage vers un format portrait Cette illustration décrit le comportement du périphérique lorsque l’utilisateur passe du mode paysage au mode portrait avec différents modes de mise à l’échelle. Le passage du mode portrait au mode paysage produit des effets similaires. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 204 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Evénements de changement d’orientation L’objet Stage distribue deux types d’événements, dont vous disposez pour détecter les changements d’orientation et réagir à ces derniers. Les événements resize et orientationChange de la scène sont tous deux distribués si l’orientation automatique est activée. Privilégiez l’événement resize si vous vous fiez à l’orientation automatique pour assurer une position verticale à l’affichage. Lorsque la scène distribue un événement resize, changez la disposition de votre contenu ou redessinez-le si nécessaire. L’événement resize n’est distribué que si le mode de mise à l’échelle de la scène est défini sur noScale. L’événement orientationChange permet également de détecter les changements d’orientation. L’événement orientationChange n’est distribué que si l’orientation automatique est activée. Remarque : sur certaines plates-formes mobiles, la scène distribue un événement orientationChanging, que vous pouvez annuler, avant de distribuer les événements resize ou orientationChange. Etant donné que cet événement n’est pas pris en charge sur toutes les plates-formes, évitez de trop vous y fier. Orientation manuelle AIR 2.6 et les versions ultérieures Vous pouvez contrôler l’orientation de la scène via la méthode setOrientation() ou setAspectRatio() de l’objet Stage. Définition de l’orientation de la scène Vous pouvez définir l’orientation de la scène à l’exécution à l’aide de la méthode setOrientation() de l’objet Stage. Utilisez les constantes de chaîne définies par la classe StageOrientation pour spécifier l’orientation de votre choix : this.stage.setOrientation( StageOrientation.ROTATED_RIGHT ); Tous les périphériques et systèmes d’exploitation ne prennent pas en charge toutes les orientations possibles. Par exemple, Android 2.2 ne prend pas en charge la sélection par programmation de l’orientation vers la gauche sur les périphériques portrait standard et ne prend pas du tout en charge l’orientation à l’envers. La propriété supportedOrientations de la scène fournit une liste des orientations pouvant être transmises à la méthode setOrientation() : var orientations:Vector. = this.stage.supportedOrientations; for each( var orientation:String in orientations ) { trace( orientation ); } Définition du format de la scène Si le format de la scène vous importe, vous pouvez le définir sur portrait ou paysage. Vous pouvez définir le format soit dans le descripteur de l’application AIR, soit à l’exécution à l’aide de la méthode setAspectRatio() de l’objet Stage : this.stage.setAspectRatio( StageAspectRatio.LANDSCAPE ); Le moteur d’exécution choisit l’une des deux orientations possibles pour le format spécifié. Il est possible que ce choix ne corresponde pas à l’orientation du périphérique. Par exemple, l’orientation par défaut est préférée à l’orientation à l’envers (AIR 3.2 et les versions antérieures) et l’orientation convenant au clavier coulissant est préférée à l’orientation opposée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 205 Programmation de l’affichage Dernière mise à jour le 27/4/2013 (AIR 3.3 et versions ultérieures) A partir d’AIR 3.3 (SWF version 16), vous pouvez également utiliser la constante StageAspectRatio.ANY. Si vous définissez Stage.autoOrients sur true et appelez setAspectRatio(StageAspectRatio.ANY), votre application a la capacité de réorienter toutes les orientations (paysage vers la gauche, paysage vers la droite, portait et portrait à l’envers). Autre nouveauté dans AIR 3.3 : le format est persistent et toute rotation du périphérique est soumise à l’orientation spécifiée. Exemple : définition de l’orientation de la scène de façon à ce qu’elle corresponde à l’orientation du périphérique L’exemple suivant illustre une fonction qui met à jour l’orientation de la scène afin qu’elle corresponde à celle du périphérique. La propriété deviceOrientation de la scène indique l’orientation physique du périphérique, même si l’orientation automatique est désactivée. function refreshOrientation( theStage:Stage ):void { switch ( theStage.deviceOrientation ) { case StageOrientation.DEFAULT: theStage.setOrientation( StageOrientation.DEFAULT ); break; case StageOrientation.ROTATED_RIGHT: theStage.setOrientation( StageOrientation.ROTATED_LEFT ); break; case StageOrientation.ROTATED_LEFT: theStage.setOrientation( StageOrientation.ROTATED_RIGHT ); break; case StageOrientation.UPSIDE_DOWN: theStage.setOrientation( StageOrientation.UPSIDE_DOWN ); break; default: //No change } } La modification de l’orientation est asynchrone. Vous pouvez écouter l’événement orientationChange distribué par la scène pour savoir quand la modification est terminée. Si une orientation n’est pas prise en charge sur un périphérique, l’appel de setOrientation() échoue sans distribuer d’erreur. Chargement dynamique du contenu d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les éléments d’affichage externes suivants peuvent être chargés dans une application ActionScript 3.0 : • Fichier SWF programmé dans ActionScript 3.0 : ce fichier peut correspondre à Sprite, MovieClip ou toute classe qui étend Sprite. Dans les applications AIR sous iOS, seuls les fichiers SWF qui ne contiennent pas de code d’octet ActionScript peuvent être chargés. En d’autres termes, les fichiers SWF qui contiennent des données incorporées, telles qu’images et son, peuvent être chargées, mais pas les fichiers SWF contenant du code exécutable. • Fichier d’image : tels que les fichiers JPG, PNG et GIF. • Fichier AVM1 SWF : fichier SWF écrit en ActionScript 1.0 ou 2.0. (non pris en charge sur les applications mobiles AIR) Vous chargez ces ressources par le biais de la classe Loader. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 206 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Chargement d’objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les objets Loader permettent de charger des fichiers SWF et des fichiers graphiques dans une application. La classe Loader est une sous-classe de la classe DisplayObjectContainer. La liste d’affichage d’un objet Loader ne comporte qu’un seul objet d’affichage enfant : l’objet d’affichage qui représente le fichier SWF ou graphique qu’il charge. Lorsque vous ajoutez un objet Loader à la liste d’affichage, comme dans le code ci-dessous, vous ajoutez également l’objet d’affichage enfant chargé à la liste d’affichage, une fois le chargement effectué : var pictLdr:Loader = new Loader(); var pictURL:String = "banana.jpg" var pictURLReq:URLRequest = new URLRequest(pictURL); pictLdr.load(pictURLReq); this.addChild(pictLdr); Lorsque le fichier SWF ou l’image sont chargés, vous pouvez transférer l’objet d’affichage chargé dans un autre conteneur d’objets d’affichage, tel que l’objet container de la classe DisplayObjectContainer dans l’exemple illustré : import flash.display.*; import flash.net.URLRequest; import flash.events.Event; var container:Sprite = new Sprite(); addChild(container); var pictLdr:Loader = new Loader(); var pictURL:String = "banana.jpg" var pictURLReq:URLRequest = new URLRequest(pictURL); pictLdr.load(pictURLReq); pictLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaded); function imgLoaded(event:Event):void { container.addChild(pictLdr.content); } Surveillance de la progression du chargement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque le chargement du fichier débute, un objet LoaderInfo est créé. Un objet LoaderInfo fournit diverses informations sur le chargement : progression, adresses URL du chargeur et du chargé, nombre d’octets total de l’objet multimédia et dimensions nominales (hauteur et largeur) de celui-ci. Par ailleurs, un objet LoaderInfo distribue les événements qui permettent de suivre la progression du chargement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 207 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Le diagramme suivant présente les diverses utilisations de l’objet LoaderInfo, pour l’occurrence de la classe principale du fichier SWF, pour un objet Loader et pour un objet chargé par ce dernier : Vous pouvez accéder à l’objet LoaderInfo en tant que propriété de l’objet Loader et de l’objet d’affichage chargé. Dès que le chargement débute, vous pouvez accéder à l’objet LoaderInfo par le biais de la propriété contentLoaderInfo de l’objet Loader. Lorsque le chargement de l’objet d’affichage est terminé, vous pouvez également accéder à l’objet LoaderInfo en tant que propriété de cet objet chargé par le biais de la propriété loaderInfo de l’objet d’affichage. La propriété loaderInfo de l’objet d’affichage chargé se réfère au même objet LoaderInfo que la propriété contentLoaderInfo de l’objet Loader. En d’autres termes, un objet LoaderInfo est partagé entre un objet chargé et l’objet Loader qui l’a chargé (entre le chargeur et le chargé). Pour accéder aux propriétés du contenu chargé, il est recommandé d’ajouter un écouteur d’événement à l’objet LoaderInfo, comme indiqué dans le code suivant : import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; var ldr:Loader = new Loader(); var urlReq:URLRequest = new URLRequest("Circle.swf"); ldr.load(urlReq); ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded); addChild(ldr); function loaded(event:Event):void { var content:Sprite = event.target.content; content.scaleX = 2; } Pour plus d’informations, voir « Gestion des événements » à la page 129. Définition du contexte de chargement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous chargez un fichier externe dans Flash Player ou AIR par le biais de la méthode load() ou loadBytes() de la classe Loader, vous pouvez indiquer le paramètre context. Ce paramètre est un objet LoaderContext. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 208 Programmation de l’affichage Dernière mise à jour le 27/4/2013 La classe LoaderContext comporte trois propriétés qui permettent de définir le contexte d’utilisation du contenu chargé : • checkPolicyFile : utilisez cette propriété uniquement pour le chargement d’un fichier image (pas pour un fichier SWF). Si vous définissez cette propriété sur true, l’objet Loader vérifie si le serveur d’origine héberge un fichier de régulation (voir « Contrôles de site Web (fichiers de régulation) » à la page 1095). Cette opération n’est requise que si le contenu émane de domaines autres que celui du fichier SWF qui contient l’objet Loader. Si le serveur accorde une autorisation au domaine de Loader, le code ActionScript extrait des fichiers SWF du domaine de Loader peut accéder aux données de l’image chargée. En d’autres termes, vous pouvez utiliser la commande BitmapData.draw() pour accéder aux données de l’image chargées. Notez qu’un fichier SWF extrait d’un autre domaine que celui de l’objet Loader peut appeler Security.allowDomain() pour autoriser un domaine déterminé. • securityDomain : utilisez cette propriété uniquement pour le chargement d’un fichier SWF (pas pour une image). Cette propriété peut être appelée pour un fichier SWF provenant d’un autre domaine que celui du fichier qui contient l’objet Loader. Lorsque vous indiquez cette option, Flash Player vérifie l’existence d’un fichier de régulation et, s’il existe, les fichiers SWF des domaines autorisés dans ce fichier peuvent utiliser des opérations de programmation croisée avec le contenu du fichier SWF chargé. Vous pouvez stipuler flash.system.SecurityDomain.currentDomain en tant que paramètre. • applicationDomain : utilisez cette propriété uniquement lors du chargement d’un fichier SWF écrit dans ActionScript 3.0 (et non une image ou un fichier SWF écrit dans ActionScript 1.0 ou 2.0). Lorsque vous chargez un fichier, vous devez indiquer que le fichier doit être inclus dans le même domaine d’application que l’objet Loader en attribuant au paramètre applicationDomain la valeur flash.system.ApplicationDomain.currentDomain. Si vous placez le fichier SWF chargé dans le même domaine d’application, vous pourrez accéder directement à ses classes, ce qui s’avère utile si vous chargez un fichier SWF contenant des média intégrés, auxquels vous pouvez accéder via les noms de classes associés. Pour plus d’informations, voir « Utilisation de domaines d’application » à la page 152. Exemple de vérification d’un fichier de régulation lors du chargement d’une image bitmap provenant d’un autre domaine : var context:LoaderContext = new LoaderContext(); context.checkPolicyFile = true; var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/photo11.jpg"); var ldr:Loader = new Loader(); ldr.load(urlReq, context); Exemple de vérification d’un fichier de régulation lors du chargement d’un fichier SWF à partir d’un autre domaine, dans le but de placer ce fichier dans la même Sandbox de sécurité que l’objet Loader. Par ailleurs, le code ajoute les classes du fichier SWF chargé dans le même domaine d’application que celui de l’objet Loader : var context:LoaderContext = new LoaderContext(); context.securityDomain = SecurityDomain.currentDomain; context.applicationDomain = ApplicationDomain.currentDomain; var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/library.swf"); var ldr:Loader = new Loader(); ldr.load(urlReq, context); Pour plus d’informations, voir la classe LoaderContext dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 209 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Chargement de fichiers SWF dans AIR pour iOS Adobe AIR 3.6 et ultérieur, iOS uniquement Il existe des restrictions concernant le chargement et la compilation de code à l’exécution sur les périphériques iOS. En raison de ces restrictions, vous constaterez certaines différences nécessaires dans la tâche de chargement des fichiers SWF externes dans votre application : • Tous les fichiers contenant du code ActionScript doivent être inclus dans le package d’application. Aucun fichier SWF contenant du code ne peut être chargé depuis une source externe (via un réseau, par exemple). Lors de la création du package de l’application, le code ActionScript des fichiers SWF du package d’application est compilé en code natif pour périphériques iOS. • Il est impossible de charger, décharger, puis recharger un fichier SWF. Si vous tentez de le faire, une erreur se produit. • Le comportement en cas de chargement en mémoire, puis de déchargement, est le même qu’avec les systèmes d’exploitation d’ordinateur de bureau. Si vous chargez un fichier SWF, puis que vous le déchargez, tous les éléments visuels contenus dans le SWF sont déchargés de la mémoire. Toutefois, les références de classe à une classe ActionScript dans le fichier SWF chargé restent en mémoire et sont accessibles par le code ActionScript. • Tous les fichiers SWF doivent être chargés dans le même domaine d’application que le fichier SWF principal. Ceci n’est pas le comportement par défaut. C’est pourquoi, pour chaque SWF chargé, vous devez créer un objet LoaderContext spécifiant le domaine d’application principal et transmettre cet objet LoaderContext à l’appel de méthode Loader.load(). Si vous tentez de charger un fichier SWF dans un domaine d’application autre que le domaine d’application SWF principal, une erreur se produit. Cela est vrai même si le fichier SWF chargé ne contient que des éléments visuels sans code ActionScript. L’exemple suivant montre le code à utiliser pour charger le SWF depuis le package d’application dans le domaine d’application du fichier SWF principal : var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("swfs/SecondarySwf.swf"); var loaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, null); loader.load(url, loaderContext); Un fichier SWF contenant uniquement des actifs sans code peut être chargé depuis le package d’application ou via réseau. Dans les deux cas, le fichier SWF doit toujours être chargé dans le domaine d’application principal. Pour les versions d’AIR antérieures à 3.6, le code est retiré de tous les fichiers SWF, à l’exception du fichier d’application SWF principal, au cours du processus de compilation. Les fichiers SWF ne contenant que des éléments visuels peuvent être inclus dans le package d’application et chargés à l’exécution, mais pas le code. Si vous tentez de charger un fichier SWF contenant du code ActionScript, une erreur se produit. Cette erreur cause l’apparition d’un message d’erreur « ActionScript non compilé » dans l’application. Voir aussi Packaging and loading multiple SWFs in AIR apps on iOS (disponible en anglais uniquement). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 210 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Utilisation des classes ProLoader et ProLoaderInfo Flash Player 9 et les versions ultérieures et Adobe AIR 1.0 et les versions ultérieures requièrent Flash Professional CS5.5 Pour faciliter le préchargement de la bibliothèque RSL (Remote Shared Library), Flash Professional CS5.5 intègre à présent les classes fl.display.ProLoader et fl.display.ProLoaderInfo. Ces classes reflètent les classes flash.display.Loader et flash.display.LoaderInfo, mais assurent un chargement plus cohérent. La classe ProLoader permet en particulier de charger les fichiers SWF qui font appel à Text Layout Framework (TLF) lors d’un préchargement RSL. A l’exécution, les fichiers SWF qui préchargent d’autres fichiers SWF ou des fichiers SWZ, tels que TLF, nécessitent un fichier d’enveloppe SWF à usage interne uniquement. Cette couche complémentaire de complexité imposée par le fichier d’enveloppe SWF entraîne parfois un comportement inattendu. La classe ProLoader résout ce problème en permettant de charger les fichiers comme des fichiers SWF standard. La solution adoptée par la classe ProLoader est transparente du point de vue de l’utilisateur et ne requiert pas de traitement particulier dans ActionScript. La classe ProLoader charge par ailleurs correctement les contenus SWF standard. Dans Flash Professional CS 5.5 et ultérieur, vous pouvez remplacer la classe Loader par la classe ProLoader dans tous les cas de figure en toute sécurité. Exportez ensuite l’application vers Flash Player 10.2 ou ultérieur, afin que la classe ProLoader puisse accéder à la fonctionnalité ActionScript requise. Vous pouvez également faire appel à la classe ProLoader si vous ciblez des versions antérieures de Flash Player qui prennent en charge ActionScript 3.0. Toutefois, seul Flash Player 10.2 ou ultérieur exploite pleinement les fonctions de Proloader. Utilisez toujours la classe ProLoader si vous faites appel à TLF dans Flash Professional CS5.5 ou ultérieur. L’utilisation de ProLoader est superflue dans les environnements autres que Flash Professional. Important : pour les fichiers SWF publiés dans Flash Professional CS5.5 et ultérieur, il est toujours possible d’utiliser les classes fl.display.ProLoader et fl.display.ProLoaderInfo au lieu des classes flash.display.Loader et flash.display.LoaderInfo. Problèmes résolus par la classe ProLoader La classe ProLoader résout les problèmes que la classe Loader existante, de par sa conception, ne prenait pas en charge. Ces problèmes résultent du préchargement RSL de bibliothèques TLF. Ils concernent spécifiquement les fichiers SWF qui chargent d’autres fichiers SWF par le biais d’un objet Loader. Les problèmes résolus sont les suivants : • L’utilisation de scripts entre le fichier de chargement et le fichier chargé entraîne des résultats inattendus. La classe ProLoader définit automatiquement le fichier SWF de chargement en tant que parent du fichier SWF chargé. De ce fait, les communications émanant du fichier SWF de chargement ciblent directement le fichier SWF chargé. • L’application SWF doit gérer activement le processus de chargement. Cette opération requiert la mise en oeuvre d’événements supplémentaires tels que added, removed, addedToStage et removedFromStage. Si l’application cible Flash Player 10.2 ou ultérieur, la classe ProLoader permet d’éviter cette tâche supplémentaire. Mise à jour du code en vue d’utiliser ProLoader au lieu de Loader Etant donné que la classe ProLoader reflète la classe Loader, substituer une classe à l’autre dans le code ne présente aucune difficulté. L’exemple suivant illustre la mise à jour du code existant en vue d’utiliser la nouvelle classe : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 211 Programmation de l’affichage Dernière mise à jour le 27/4/2013 import flash.display.Loader; import flash.events.Event; var l:Loader = new Loader(); addChild(l); l.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete); l.load("my.swf"); function loadComplete(e:Event) { trace('load complete!'); } Il est possible de mettre à jour ce code pour utiliser la classe ProLoader, comme suit : import fl.display.ProLoader; import flash.events.Event; var l:ProLoader = new ProLoader(); addChild(l); l.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete); l.load("my.swf"); function loadComplete(e:Event) { trace('load complete!'); } Exemple d’objet d’affichage : SpriteArranger Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple d’application SpriteArranger est basé sur l’exemple d’application Geometric Shapes (voir Formation à ActionScript 3.0). L’exemple SpriteArranger illustre divers concepts de gestion des objets d’affichage : • Extension des classes d’objet d’affichage • Ajout d’objets à la liste d’affichage • Superposition des objets d’affichage et utilisation des conteneurs d’objets d’affichage • Réponse aux événements d’objet d’affichage • Utilisation des propriétés et méthodes des objets d’affichage Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application SpriteArranger résident dans le dossier Examples/SpriteArranger. L’application se compose des fichiers suivants : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 212 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Définition des classes SpriteArranger Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application SpriteArranger permet à l’utilisateur d’ajouter divers objets d’affichage au rectangle de la zone de dessin à l’écran. La classe DrawingCanvas définit une zone de dessin, soit un type de conteneur d’objets d’affichage, à laquelle l’utilisateur peut ajouter des formes à l’écran. Ces formes sont des occurrences de l’une des sous-classes de la classe GeometricSprite. Fichier Description SpriteArranger.mxml ou SpriteArranger.fla Fichier d’application principal dans Flash (FLA) ou Flex (MXML). com/example/programmingas3/SpriteArranger/CircleSprite.as Classe définissant un type d’objet Sprite qui assure le rendu d’un cercle à l’écran. com/example/programmingas3/SpriteArranger/DrawingCanvas.as Classe définissant le rectangle de la zone de dessin, soit un conteneur d’objets d’affichage comportant des objets GeometricSprite. com/example/programmingas3/SpriteArranger/SquareSprite.as Classe définissant un type d’objet Sprite qui assure le rendu d’un carré à l’écran. com/example/programmingas3/SpriteArranger/TriangleSprite.as Classe définissant un type d’objet Sprite qui assure le rendu d’un triangle à l’écran. com/example/programmingas3/SpriteArranger/GeometricSprite.as Classe qui étend l’objet Sprite, utilisé pour définir une forme à l’écran. CircleSprite, SquareSprite et TriangleSprite étendent chacun cette classe. com/example/programmingas3/geometricshapes/IGeometricShape.as Interface de base qui définit les méthodes à implémenter par toutes les classes de formes géométriques. com/example/programmingas3/geometricshapes/IPolygon.as Interface qui définit les méthodes à implémenter par les classes de forme géométrique dotées de plusieurs côtés. com/example/programmingas3/geometricshapes/RegularPolygon.as Type de forme géométrique dont les côtés sont de longueur égale et positionnés symétriquement autour du centre de la forme. com/example/programmingas3/geometricshapes/Circle.as Type de forme géométrique qui définit un cercle. com/example/programmingas3/geometricshapes/EquilateralTriangle.as Sous-classe de RegularPolygon qui définit un triangle équilatéral. com/example/programmingas3/geometricshapes/Square.as Sous-classe de RegularPolygon qui définit un carré. com/example/programmingas3/geometricshapes/GeometricShapeFactory.as Classe qui contient une « méthode usine » permettant de créer des formes d’une taille et d’un type de forme donnés. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 213 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Classe DrawingCanvas Dans Flex, tous les objets d’affichage enfant ajoutés à un objet Container doivent appartenir à une classe issue de la classe mx.core.UIComponent. Cette application ajoute une occurrence de la classe DrawingCanvas en tant qu’enfant d’un objet mx.containers.VBox, ainsi que le définit le code MXML dans le fichier SpriteArranger.mxml. Cet héritage est défini dans la déclaration de classe DrawingCanvas, comme suit : public class DrawingCanvas extends UIComponent La classe UIComponent héritage des classes DisplayObject, DisplayObjectContainer et Sprite et le code de la classe DrawingCanvas utilise les méthodes et propriétés de ces dernières. La classe DrawingCanvas étend la classe Sprite et cet héritage est défini dans la déclaration de classe DrawingCanvas, comme suit : public class DrawingCanvas extends Sprite La classe Sprite est une sous-classe des classes DisplayObjectContainer et DisplayObject et la classe DrawingCanvas utilise les méthodes et propriétés de ces dernières. La méthode constructeur DrawingCanvas() définit un objet Rectangle, bounds, qui est une propriété utilisée ultérieurement lors du tracé du contour de la zone de dessin. Elle appelle ensuite la méthode initCanvas(), comme suit : this.bounds = new Rectangle(0, 0, w, h); initCanvas(fillColor, lineColor); Comme l’indique l’exemple suivant, la méthode initCanvas() définit diverses propriétés de l’objet DrawingCanvas, transmises en tant qu’arguments à la méthode constructeur : this.lineColor = lineColor; this.fillColor = fillColor; this.width = 500; this.height = 200; La méthode initCanvas() appelle ensuite la méthode drawBounds() qui trace le rectangle de la zone de dessin à l’aide de la propriété graphics de la classe DrawingCanvas. La propriété graphics est héritée de la classe Shape. this.graphics.clear(); this.graphics.lineStyle(1.0, this.lineColor, 1.0); this.graphics.beginFill(this.fillColor, 1.0); this.graphics.drawRect(bounds.left - 1, bounds.top - 1, bounds.width + 2, bounds.height + 2); this.graphics.endFill(); Les autres méthodes de la classe DrawingCanvas, indiquées ci-après, sont appelées en fonction des interactions de l’utilisateur avec l’application : • Les méthodes addShape() et describeChildren(), décrites à la section « Ajout d’objets d’affichage au rectangle de la zone de dessin » à la page 214 • Les méthodes moveToBack(), moveDown(), moveToFront() et moveUp(), décrites à la section « Réorganisation de l’ordre de superposition des objets d’affichage » à la page 217 • La méthode onMouseUp(), décrite à la section « Cliquer-déplacer un objet d’affichage » à la page 216 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 214 Programmation de l’affichage Dernière mise à jour le 27/4/2013 Classe GeometricSprite et ses sous-classes Chaque objet d’affichage susceptible d’être ajouté par l’utilisateur au rectangle de la zone de dessin est une occurrence de l’une des sous-classes suivantes de la classe GeometricSprite : • CircleSprite • SquareSprite • TriangleSprite La classe GeometricSprite étend la classe flash.display.Sprite : public class GeometricSprite extends Sprite La classe GeometricSprite comprend diverses propriétés communes à tous les objets GeometricSprite. Elles sont définies dans la fonction constructeur en fonction des paramètres transmis à cette dernière. Exemple : this.size = size; this.lineColor = lColor; this.fillColor = fColor; La propriété geometricShape de la classe GeometricSprite définit une interface IGeometricShape, qui stipule les propriétés mathématiques, mais non visuelles, de la forme. Les classes qui implémentent l’interface IGeometricShape sont définies dans l’exemple d’application GeometricShapes (voir Formation à ActionScript 3.0). La classe GeometricSprite définit la méthode drawShape(), qui est affinée dans les définitions de remplacement de chaque sous-classe de GeometricSprite. Pour plus d’informations, voir ci-après « Ajout d’objets d’affichage au rectangle de la zone de dessin ». La classe GeometricSprite propose également les méthodes suivantes : • Les méthodes onMouseDown() et onMouseUp(), décrites à la section « Cliquer-déplacer un objet d’affichage » à la page 216 • Les méthodes showSelected() et hideSelected(), décrites à la section « Cliquer-déplacer un objet d’affichage » à la page 216 Ajout d’objets d’affichage au rectangle de la zone de dessin Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque l’utilisateur clique sur le bouton Add Shape, l’application appelle la méthode addShape() de la classe DrawingCanvas. Elle crée une occurrence de GeometricSprite en appelant la fonction constructeur appropriée de l’une des sous-classes de GeometricSprite, comme illustré dans l’exemple suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 215 Programmation de l’affichage Dernière mise à jour le 27/4/2013 public function addShape(shapeName:String, len:Number):void { var newShape:GeometricSprite; switch (shapeName) { case "Triangle": newShape = new TriangleSprite(len); break; case "Square": newShape = new SquareSprite(len); break; case "Circle": newShape = new CircleSprite(len); break; } newShape.alpha = 0.8; this.addChild(newShape); } Chaque méthode constructeur appelle la méthode drawShape(), qui utilise la propriété graphics de la classe (héritée de la classe Sprite) pour dessiner le graphique vectoriel approprié. Par exemple, la méthode drawShape() de la classe CircleSprite comprend le code suivant : this.graphics.clear(); this.graphics.lineStyle(1.0, this.lineColor, 1.0); this.graphics.beginFill(this.fillColor, 1.0); var radius:Number = this.size / 2; this.graphics.drawCircle(radius, radius, radius); L’avant-dernière ligne de la fonction addShape() définit la propriété alpha de l’objet d’affichage (héritée de la classe DisplayObject), de sorte que chaque objet d’affichage ajouté au rectangle de la zone de dessin soit légèrement transparent, permettant ainsi à l’utilisateur de visualiser les objets placés derrière. La derrière ligne de la méthode addChild() ajoute le nouvel objet d’affichage à la liste enfant de l’occurrence de la classe DrawingCanvas, qui figure déjà dans la liste d’affichage. Le nouvel objet d’affichage apparaît alors sur la scène. L’interface de l’application comprend deux champs de texte, selectedSpriteTxt et outputTxt. Les propriétés de texte de ces champs sont mises à jour avec des informations relatives aux objets GeometricSprite ajoutés au rectangle de la zone de dessin ou sélectionnés par l’utilisateur. La classe GeometricSprite gère ces tâches de transmission d’informations en annulant la méthode toString() comme suit : public override function toString():String { return this.shapeType + " of size " + this.size + " at " + this.x + ", " + this.y; } La propriété shapeType est définie sur la valeur appropriée de la méthode constructeur de chaque sous-classe GeometricSprite. La méthode toString() pourrait par exemple renvoyer la valeur suivante pour une occurrence de CircleSprite récemment ajoutée à l’occurrence de DrawingCanvas : Circle of size 50 at 0, 0 La méthode describeChildren() de la classe DrawingCanvas parcourt la liste enfant du rectangle de la zone de dessin en utilisant la propriété numChildren (héritée de la classe DisplayObjectContainer) pour définir la limite de la boucle for. Elle génère une chaîne qui recense chaque enfant, comme suit : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 216 Programmation de l’affichage Dernière mise à jour le 27/4/2013 var desc:String = ""; var child:DisplayObject; for (var i:int=0; i < this.numChildren; i++) { child = this.getChildAt(i); desc += i + ": " + child + '\n'; } La chaîne résultante permet de définir la propriété text du champ de texte outputTxt. Cliquer-déplacer un objet d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque l’utilisateur clique sur une occurrence de GeometricSprite, l’application appelle le gestionnaire de l’événement onMouseDown(). Comme le montre le code ci-dessous, ce gestionnaire écoute les événements de clic gauche de souris dans la fonction constructeur de la classe GeometricSprite : this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); La méthode onMouseDown() appelle ensuite la méthode showSelected() de l’objet GeometricSprite. S’il s’agit du premier appel de cette méthode sur l’objet, elle crée un objet Shape appelé selectionIndicator et utilise la propriété graphics de l’objet Shape pour dessiner un rectangle rouge de mise en valeur, comme suit : this.selectionIndicator = new Shape(); this.selectionIndicator.graphics.lineStyle(1.0, 0xFF0000, 1.0); this.selectionIndicator.graphics.drawRect(-1, -1, this.size + 1, this.size + 1); this.addChild(this.selectionIndicator); S’il ne s’agit pas du premier appel de la méthode onMouseDown(), celle-ci active simplement la propriété visible (héritée de la classe DisplayObject) de la forme selectionIndicator : this.selectionIndicator.visible = true; La méthode hideSelected() masque la forme selectionIndicator de l’objet précédemment sélectionné en définissant sa propriété visible sur false. La méthode du gestionnaire d’événement onMouseDown() appelle également la méthode startDrag() (héritée de la classe Sprite), qui comprend le code suivant : var boundsRect:Rectangle = this.parent.getRect(this.parent); boundsRect.width -= this.size; boundsRect.height -= this.size; this.startDrag(false, boundsRect); L’utilisateur peut alors déplacer l’objet sélectionné sur la zone de dessin, au sein des limites définies par le rectangle boundsRect. Lorsque l’utilisateur relâche le bouton de la souris, l’événement mouseUp est distribué. La méthode constructeur de DrawingCanvas configure l’écouteur d’événement suivant : this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); Cet écouteur d’événement est associé à l’objet DrawingCanvas, plutôt qu’aux objets GeometricSprite individuels. En effet, lorsque l’utilisateur déplace l’objet GeometricSprite, celui-ci risque d’être placé derrière un autre objet d’affichage (un autre objet GeometricSprite) lorsque le bouton de la souris est relâché. L’événement « mouse up » s’appliquerait à l’objet d’affichage en avant-plan, mais non à l’objet d’affichage déplacé par l’utilisateur. Ajouter l’écouteur à l’objet DrawingCanvas assure la gestion de l’événement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 217 Programmation de l’affichage Dernière mise à jour le 27/4/2013 La méthode onMouseUp() appelle la méthode onMouseUp() de l’objet GeometricSprite, qui appelle alors la méthode stopDrag() de l’objet GeometricSprite. Réorganisation de l’ordre de superposition des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’interface utilisateur de l’application comprend des boutons intitulés Move Back, Move Down, Move Up et Move to Front. Lorsque l’utilisateur clique sur l’un de ces boutons, l’application appelle la méthode correspondante de la classe DrawingCanvas, à savoir : moveToBack(), moveDown(), moveUp() ou moveToFront(). Par exemple, la méthode moveToBack() comporte le code suivant : public function moveToBack(shape:GeometricSprite):void { var index:int = this.getChildIndex(shape); if (index > 0) { this.setChildIndex(shape, 0); } } Cette méthode utilise la méthode setChildIndex() (héritée de la classe DisplayObjectContainer) pour placer l’objet d’affichage à la position d’index 0 de la liste des enfants de l’occurrence de DrawingCanvas (this). Le fonctionnement de la méthode moveDown() est similaire, mais elle décrémente la position d’index de l’objet d’affichage d’une unité dans la liste des enfants de l’occurrence de DrawingCanvas : public function moveDown(shape:GeometricSprite):void { var index:int = this.getChildIndex(shape); if (index > 0) { this.setChildIndex(shape, index - 1); } } Le fonctionnement des méthodes moveUp() et moveToFront() est similaire aux méthodes moveToBack() et moveDown(). 218 Dernière mise à jour le 27/4/2013 Chapitre 11 : Utilisation de la géométrie Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le package flash.geom contient des classes qui définissent des objets géométriques, tels que des points, des rectangles et des matrices de transformation. Vous utilisez ces classes pour définir les propriétés des objets qui sont utilisés dans d’autres classes. Voir aussi flash.geom, package Principes de base de la géométrie Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le package flash.geom contient des classes qui définissent des objets géométriques, tels que des points, des rectangles et des matrices de transformation. Ces classes ne fournissent pas nécessairement de fonctionnalité par elles-mêmes ; néanmoins, elles sont utilisées pour définir les propriétés des objets utilisés dans d’autres classes. Toutes les classes de géométrie se basent sur la notion selon laquelle les emplacements à l’écran sont représentés comme un plan en deux dimensions. L’écran est traité comme un graphique plat avec un axe horizontal (x) et un axe vertical (y). Tout emplacement (ou point) à l’écran peut être représenté sous la forme d’une paire de valeurs x et y, appelées coordonnées de cet emplacement. Chaque objet d’affichage, y compris la scène, possède son propre espace de coordonnées. L’espace de coordonnées constitue le graphe d’un objet et permet de tracer la position des dessins, des objets d’affichage enfant, etc. L’origine occupe la position 0, 0 (soit l’intersection des axes x et y) et est placée dans l’angle supérieur gauche de l’objet d’affichage. La position de l’origine est systématiquement respectée pour la scène, mais pas nécessairement pour d’autres objets d’affichage. La taille des valeurs figurant sur l’axe x croît vers la droite et diminue vers la gauche. La coordonnée x des positions figurant sur la gauche de l’origine est négative. Cependant, contrairement aux systèmes de coordonnées classiques, la valeur des coordonnées de l’axe y croît vers le bas de l’écran et diminue vers le haut dans le moteur d’exécution de Flash. La coordonnée y des valeurs situées au-dessus de l’origine est négative. Puisque l’angle supérieur gauche de la scène correspond à l’origine de son espace de coordonnées, la coordonnée x de la plupart des objets de la scène est supérieure à 0 et inférieure à la largeur de la scène. La coordonnée y d’un même objet est supérieure à 0 et inférieure à la hauteur de la scène. Vous pouvez utiliser des occurrences de la classe Point pour représenter des points individuels dans un espace de coordonnées. Vous pouvez créer une occurrence de Rectangle pour représenter une région rectangulaire dans un espace de coordonnées. Les utilisateurs chevronnés peuvent utiliser une occurrence de Matrix pour appliquer des transformations multiples ou complexes à un objet d’affichage. De nombreuses transformations simples (rotation, position, et changements d’échelle, par exemple) peuvent être appliquées directement à un objet d’affichage à l’aide des propriétés de ce dernier. Pour plus d’informations sur l’application de transformations à l’aide des propriétés d’un objet d’affichage, voir « Manipulation des objets d’affichage » à la page 180. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 219 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 Concepts importants et terminologie La liste de référence suivante contient des termes de géométrie importants : Coordonnées cartésiennes Les coordonnées sont généralement écrites sous la forme d’une paire de nombres (5, 12 ou 17, -23). Les deux nombres sont la coordonnée x et la coordonnée y, respectivement. Espace de coordonnées Représentation graphique des coordonnées contenues dans un objet d’affichage, par rapport auquel sont positionnés les éléments enfant. Origine Point d’intersection des axes x et y dans un espace de coordonnées. Ce point a les coordonnées 0, 0. Point Emplacement unique dans un espace de coordonnées. Dans le système de coordonnées 2D utilisé dans ActionScript, la position sur les axes x et y (en d’autres termes, les coordonnées du point) définit ce dernier. Point d’alignement Dans un objet d’affichage, origine (coordonnées 0, 0) de son espace de coordonnées. Mise à l’échelle Taille relative d’un objet par rapport à sa taille d’origine. Mettre un objet à l’échelle consiste à modifier sa taille en l’étirant ou en le rétrécissant. Translation Conversion des coordonnées d’un point d’un espace de coordonnées à un autre. Transformation Modification des caractéristiques visuelles d’un graphique (rotation de l’objet, modification de son échelle, désalignement, déformation ou altération de sa couleur). Axe x Axe horizontal dans le système de coordonnées en 2 dimensions utilisé dans ActionScript. Axe y Axe vertical dans le système de coordonnées en 2 dimensions utilisé dans ActionScript. Utilisation des objets Point Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un objet Point définit une paire de coordonnées cartésiennes. Il représente un emplacement dans un système de coordonnées à deux dimensions, dans lequel x est l’axe horizontal et y l’axe vertical. Pour définir un objet Point, vous définissez ses propriétés x et y comme suit : import flash.geom.*; var pt1:Point = new Point(10, 20); // x == 10; y == 20 var pt2:Point = new Point(); pt2.x = 10; pt2.y = 20; Calcul de la distance entre deux points Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser la méthode distance() de la classe Point pour calculer la distance entre deux points dans un espace de coordonnées. Par exemple, le code suivant calcule la distance entre les points d’alignement de deux objets d’affichage, circle1 et circle2, dans le même conteneur d’objet d’affichage : import flash.geom.*; var pt1:Point = new Point(circle1.x, circle1.y); var pt2:Point = new Point(circle2.x, circle2.y); var distance:Number = Point.distance(pt1, pt2); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 220 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 Translation d’espaces de coordonnées Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si deux objets d’affichage résident dans des conteneurs d’objet d’affichage distincts, ils peuvent figurer dans des espaces de coordonnées distincts. Vous pouvez utiliser la méthode localToGlobal() de la classe DisplayObject pour traduire les coordonnées dans le même espace de coordonnées (global), celui de la scène. Par exemple, le code suivant calcule la distance entre les points d’alignement de deux objets d’affichage, circle1 et circle2, dans les différents conteneurs d’objet d’affichage : import flash.geom.*; var pt1:Point = new Point(circle1.x, circle1.y); pt1 = circle1.localToGlobal(pt1); var pt2:Point = new Point(circle2.x, circle2.y); pt2 = circle2.localToGlobal(pt2); var distance:Number = Point.distance(pt1, pt2); De même, pour calculer la distance du point d’alignement d’un objet d’affichage nommé target à partir d’un point spécifique de la scène, utilisez la méthode localToGlobal() de la classe DisplayObject : import flash.geom.*; var stageCenter:Point = new Point(); stageCenter.x = this.stage.stageWidth / 2; stageCenter.y = this.stage.stageHeight / 2; var targetCenter:Point = new Point(target.x, target.y); targetCenter = target.localToGlobal(targetCenter); var distance:Number = Point.distance(stageCenter, targetCenter); Déplacement d’un objet d’affichage en fonction d’une distance et d’un angle donnés Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser la méthode polar() de la classe Point pour déplacer un objet d’affichage d’une distance et d’un angle spécifiques. Par exemple, le code suivant déplace l’objet myDisplayObject en fonction d’une distance de 100 pixels et d’un angle de 60° : import flash.geom.*; var distance:Number = 100; var angle:Number = 2 * Math.PI * (90 / 360); var translatePoint:Point = Point.polar(distance, angle); myDisplayObject.x += translatePoint.x; myDisplayObject.y += translatePoint.y; Autres utilisations de la classe Point Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser des objets Point avec les propriétés et les méthodes suivantes : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 221 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 Utilisation des objets Rectangle Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un objet Rectangle définit une zone rectangulaire. Un objet Rectangle possède une position, définie par les coordonnées x et y de son angle supérieur gauche, une propriété width et une propriété height. Pour définir les propriétés d’un nouvel objet Rectangle, appelez la fonction constructeur Rectangle(), comme suit : import flash.geom.Rectangle; var rx:Number = 0; var ry:Number = 0; var rwidth:Number = 100; var rheight:Number = 50; var rect1:Rectangle = new Rectangle(rx, ry, rwidth, rheight); Redimensionnement et repositionnement des objets Rectangle Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Il existe de nombreuses façons de redimensionner et de repositionner des objets Rectangle. Vous pouvez redimensionner directement l’objet Rectangle en modifiant ses propriétés x et y. Ce changement n’a aucune incidence sur la largeur ou la hauteur de l’objet Rectangle. Classe Méthodes ou propriétés Description DisplayObjectContainer areInaccessibleObjectsUnderPoint()getObject sUnderPoint() Utilisée pour renvoyer une liste d’objets sous un point dans un conteneur d’objet d’affichage. BitmapData hitTest() Utilisée pour définir le pixel dans l’objet BitmapData ainsi que le point pour lequel vous recherchez une zone active. BitmapData applyFilter() copyChannel() merge() paletteMap() pixelDissolve() threshold() Utilisée pour indiquer les positions des rectangles qui définissent les opérations. Matrice deltaTransformPoint() transformPoint() Utilisée pour définir des points auxquels vous souhaitez appliquer une transformation. Rectangle bottomRight size topLeft Utilisée pour définir ces propriétés. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 222 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.x = 20; rect1.y = 30; trace(rect1); // (x=20, y=30, w=100, h=50) Comme l’illustre le code suivant, l’objet Rectangle est repositionné lorsque vous modifiez la propriété left ou top correspondante. Les propriétés x et y de l’objet rectangle correspondent respectivement aux propriétés left et top. Néanmoins, la position de l’angle inférieur gauche de l’objet Rectangle ne change pas. Par conséquent, il est redimensionné. import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.left = 20; rect1.top = 30; trace(rect1); // (x=20, y=30, w=80, h=20) De même, comme indiqué dans l’exemple suivant, si vous modifiez la propriété bottom ou right d’un objet Rectangle, la position de son angle supérieur gauche ne change pas. L’objet Rectangle est redimensionné en conséquence : import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.right = 60; trect1.bottom = 20; trace(rect1); // (x=0, y=0, w=60, h=20) Vous pouvez également repositionner un objet Rectangle à l’aide de la méthode offset(), comme suit : import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.offset(20, 30); trace(rect1); // (x=20, y=30, w=100, h=50) La méthode offsetPt() fonctionne de la même façon, sauf qu’elle prend un objet Point comme paramètre, plutôt que les valeurs de décalage x et y. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 223 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 Vous pouvez également redimensionner un objet Rectangle à l’aide de la méthode inflate(), qui inclut deux paramètres, dx et dy. Le paramètre dx représente le déplacement à partir du centre des côtés droit et gauche de l’objet Rectangle, exprimé en pixels. Le paramètre dy représente le déplacement à partir du centre du haut et du bas de l’objet Rectangle, exprimé en pixels. import flash.geom.Rectangle; var x1:Number = 0; var y1:Number = 0; var width1:Number = 100; var height1:Number = 50; var rect1:Rectangle = new Rectangle(x1, y1, width1, height1); trace(rect1) // (x=0, y=0, w=100, h=50) rect1.inflate(6,4); trace(rect1); // (x=-6, y=-4, w=112, h=58) La méthode inflatePt() fonctionne de la même façon, sauf qu’elle prend un objet Point comme paramètre, plutôt que les valeurs de décalage dx et dy. Recherche d’unions et d’intersections d’objets Rectangle Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous utilisez la méthode union() pour rechercher la région rectangulaire formée par les limites de deux rectangles : import flash.display.*; import flash.geom.Rectangle; var rect1:Rectangle = new Rectangle(0, 0, 100, 100); trace(rect1); // (x=0, y=0, w=100, h=100) var rect2:Rectangle = new Rectangle(120, 60, 100, 100); trace(rect2); // (x=120, y=60, w=100, h=100) trace(rect1.union(rect2)); // (x=0, y=0, w=220, h=160) Vous utilisez la méthode intersection() pour rechercher la région rectangulaire formée par la région commune de deux rectangles : import flash.display.*; import flash.geom.Rectangle; var rect1:Rectangle = new Rectangle(0, 0, 100, 100); trace(rect1); // (x=0, y=0, w=100, h=100) var rect2:Rectangle = new Rectangle(80, 60, 100, 100); trace(rect2); // (x=120, y=60, w=100, h=100) trace(rect1.intersection(rect2)); // (x=80, y=60, w=20, h=40) Vous utilisez la méthode intersects() pour savoir si deux rectangles se recouvrent. Vous pouvez également utiliser la méthode intersects() pour savoir si un objet d’affichage est dans une certaine région de la scène. Dans l’exemple de code suivant, supposez que l’espace de coordonnées du conteneur d’objet d’affichage contenant l’objet circle soit identique à celui de la scène. L’exemple indique comment utiliser la méthode intersects() pour déterminer si un objet d’affichage, circle, recoupe des régions spécifiées de la scène, définies par les objets Rectangle target1 et target2 : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 224 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 import flash.display.*; import flash.geom.Rectangle; var circle:Shape = new Shape(); circle.graphics.lineStyle(2, 0xFF0000); circle.graphics.drawCircle(250, 250, 100); addChild(circle); var circleBounds:Rectangle = circle.getBounds(stage); var target1:Rectangle = new Rectangle(0, 0, 100, 100); trace(circleBounds.intersects(target1)); // false var target2:Rectangle = new Rectangle(0, 0, 300, 300); trace(circleBounds.intersects(target2)); // true De même, vous pouvez utiliser la méthode intersects() pour savoir si les cadres de délimitation de deux objets d’affichage se chevauchent. Utilisez la méthode getRect() de la classe DisplayObject pour inclure un espace supplémentaire que les traits d’un objet d’affichage ajoutent à une région de sélection. Autres utilisations des objets Rectangle Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les objets Rectangle sont utilisés dans les propriétés et méthodes suivantes : Utilisation des objets Matrix Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Matrix représente une matrice de transformation qui détermine le mappage des points d’un espace de coordonnées à l’autre. Pour appliquer diverses transformations graphiques à un objet d’affichage, vous pouvez définir les propriétés d’un objet Matrix, puis appliquer cet objet à la propriété matrix d’un objet Transform que vous appliquez ensuite comme propriété transform de l’objet d’affichage. Ces fonctions de transformation incluent la translation (repositionnement de x et y), la rotation, le redimensionnement et l’inclinaison. Classe Méthodes ou propriétés Description BitmapData applyFilter(), colorTransform(), copyChannel(), copyPixels(), draw(), drawWithQuality(), encode(), fillRect(), generateFilterRect(), getColorBoundsRect(), getPixels(), merge(), paletteMap(), pixelDissolve(), setPixels() et threshold() Utilisée comme type de certains paramètres pour définir une région de l’objet BitmapData. DisplayObject getBounds(), getRect(), scrollRect, scale9Grid Utilisée comme type de données pour la propriété ou le type de données renvoyé. PrintJob addPage() Utilisée pour définir le paramètre printArea. Sprite startDrag() Utilisée pour définir le paramètre bounds. TextField getCharBoundaries() Utilisée comme type de valeur renvoyé. Transform pixelBounds Utilisée comme type de données. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 225 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 Même si vous pouvez définir une matrice en ajustant directement les propriétés (a, b, c, d, tx, ty) d’un objet Matrix, il est plus facile d’utiliser la méthode createBox(). Cette méthode comporte des paramètres qui vous permettent de définir directement les effets de redimensionnement, de rotation et de translation de la matrice résultante. Par exemple, le code suivant crée un objet Matrix qui redimensionne un objet horizontalement de 2,0, le redimensionne verticalement de 3,0, le fait pivoter de 45°, le déplace (par translation) de 10 pixels vers la droite et de 20 pixels vers le bas : var matrix:Matrix = new Matrix(); var scaleX:Number = 2.0; var scaleY:Number = 3.0; var rotation:Number = 2 * Math.PI * (45 / 360); var tx:Number = 10; var ty:Number = 20; matrix.createBox(scaleX, scaleY, rotation, tx, ty); Vous pouvez également ajuster les effets de redimensionnement, de rotation et de translation d’un objet Matrix à l’aide des méthodes scale(), rotate() et translate(). Ces méthodes sont combinées aux valeurs de l’objet Matrix existant. Par exemple, le code suivant définit un objet Matrix qui redimensionne un objet d’un facteur de 4 et le fait pivoter de 60°, car les méthodes scale() et rotate() sont appelées deux fois : var matrix:Matrix = new Matrix(); var rotation:Number = 2 * Math.PI * (30 / 360); // 30° var scaleFactor:Number = 2; matrix.scale(scaleFactor, scaleFactor); matrix.rotate(rotation); matrix.scale(scaleX, scaleY); matrix.rotate(rotation); myDisplayObject.transform.matrix = matrix; Pour appliquer une transformation par inclinaison à un objet Matrix, ajustez sa propriété b ou c. Lorsque vous ajustez la propriété b, la matrice est inclinée verticalement et lorsque vous ajustez la propriété c, elle est inclinée horizontalement. Le code suivant incline l’objet Matrix myMatrix verticalement d’un facteur de 2 : var skewMatrix:Matrix = new Matrix(); skewMatrix.b = Math.tan(2); myMatrix.concat(skewMatrix); Vous pouvez appliquer une transformation Matrix à la propriété transform d’un objet d’affichage. Par exemple, le code suivant applique une transformation Matrix à un objet d’affichage nommé myDisplayObject : var matrix:Matrix = myDisplayObject.transform.matrix; var scaleFactor:Number = 2; var rotation:Number = 2 * Math.PI * (60 / 360); // 60° matrix.scale(scaleFactor, scaleFactor); matrix.rotate(rotation); myDisplayObject.transform.matrix = matrix; La première ligne définit un objet Matrix sur la matrice de transformation existante utilisée par l’objet d’affichage myDisplayObject (la propriété matrix de la propriété transformation de l’objet d’affichage myDisplayObject). Les méthodes de la classe Matrix que vous appelez ont ainsi un effet cumulatif sur la position, l’échelle et la rotation actuelles de l’objet d’affichage. Remarque : la classe ColorTransform est également comprise dans le package flash.geometry. Cette classe sert à définir la propriété colorTransform d’un objet Transform. Etant donné qu’elle n’applique aucune transformation géométrique, elle n’est pas traitée ici. Pour plus d’informations, voir la classe ColorTransform dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 226 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 Exemple de géométrie : application d’une transformation de matrice à un objet d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple d’application DisplayObjectTransformer présente de nombreuses fonctions permettant d’utiliser la classe Matrix pour transformer un objet d’affichage, notamment : • Rotation de l’objet d’affichage • Redimensionnement de l’objet d’affichage • Translation (repositionnement) de l’objet d’affichage • Inclinaison de l’objet d’affichage L’application fournit une interface permettant d’ajuster les paramètres de la transformation de matrice, comme suit : Lorsque l’utilisateur clique sur le bouton de transformation, l’application applique la transformation appropriée. L’objet d’affichage original et l’objet d’affichage pivoté de -45° et redimensionné de 50 % GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 227 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application DisplayObjectTransformer se trouvent dans le dossier Samples/DisplayObjectTransformer. L’application se compose des fichiers suivants : Définition de la classe MatrixTransformer Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe MatrixTransformer comprend des méthodes statiques qui appliquent des transformations géométriques d’objets Matrix. Méthode transform() La méthode transform() comprend des paramètres associés à chaque élément suivant : • sourceMatrix—La matrice d’entrée, que la méthode transforme • xScale et yScale—Le facteur de redimensionnement x et y • dx et dy—Les montants de translation x et y, en pixels • rotation—Le montant de rotation, en degrés • skew—Le facteur d’inclinaison, en pourcentage • skewType—Le sens d’inclinaison, "right" ou "left" La valeur renvoyée est la matrice résultante. La méthode transform() appelle les méthodes statiques suivantes de la classe : • skew() • scale() • translate() • rotate() Chacune renvoie la matrice source avec la transformation appliquée. Méthode skew() La méthode skew() incline la matrice en ajustant les propriétés b et c de la matrice. Un paramètre facultatif, unit, détermine les unités utilisées pour définir l’angle d’inclinaison et, le cas échéant, la méthode convertit la valeur angle en radians : Fichier Description DisplayObjectTransformer.mxml ou DisplayObjectTransformer.fla Fichier d’application principal en FLA pour Flash ou en MXML pour Flex com/example/programmingas3/geometry/MatrixTransformer.as Une classe qui contient des méthodes permettant d’appliquer des transformations de matrice. img/ Un répertoire contenant des exemples de fichiers image utilisés par l’application. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 228 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 if (unit == "degrees") { angle = Math.PI * 2 * angle / 360; } if (unit == "gradients") { angle = Math.PI * 2 * angle / 100; } Un objet Matrix skewMatrix est créé et ajusté pour appliquer la transformation par inclinaison. Au départ, il s’agit de la matrice d’identité, comme suit : var skewMatrix:Matrix = new Matrix(); Le paramètre skewSide détermine le côté auquel l’inclinaison est appliquée. S’il est défini sur "right", le code suivant définit la propriété b de la matrice : skewMatrix.b = Math.tan(angle); Autrement, le côté inférieur est incliné en ajustant la propriété c de la matrice, comme suit : skewMatrix.c = Math.tan(angle); L’inclinaison résultante est ensuite appliquée à la matrice existante en concaténant les deux matrices, comme indiqué dans l’exemple suivant : sourceMatrix.concat(skewMatrix); return sourceMatrix; Méthode scale() Comme le montre l’exemple suivant, la méthode scale() ajuste d’abord le facteur de redimensionnement s’il est défini sous la forme de pourcentage, puis utilise la méthode scale() de l’objet matrix : if (percent) { xScale = xScale / 100; yScale = yScale / 100; } sourceMatrix.scale(xScale, yScale); return sourceMatrix; Méthode translate() La méthode translate() applique simplement les facteurs de translation dx et dy en appelant la méthode translate() de l’objet matrix, comme suit : sourceMatrix.translate(dx, dy); return sourceMatrix; Méthode rotate() La méthode rotate() convertit le facteur de rotation d’entrée en radians (s’il est fourni en degrés ou dégradés), puis appelle la méthode rotate() de l’objet matrix : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 229 Utilisation de la géométrie Dernière mise à jour le 27/4/2013 if (unit == "degrees") { angle = Math.PI * 2 * angle / 360; } if (unit == "gradients") { angle = Math.PI * 2 * angle / 100; } sourceMatrix.rotate(angle); return sourceMatrix; Appel de la méthode MatrixTransformer.transform() depuis l’application Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application contient une interface utilisateur permettant d’obtenir les paramètres de transformation de l’utilisateur. Elle transmet ensuite ces valeurs, avec la propriété matrix de la propriété transform de l’objet d’affichage, à la méthode Matrix.transform(), comme suit : tempMatrix = MatrixTransformer.transform(tempMatrix, xScaleSlider.value, yScaleSlider.value, dxSlider.value, dySlider.value, rotationSlider.value, skewSlider.value, skewSide ); L’application applique alors la valeur renvoyée à la propriété matrix de la propriété transform de l’objet d’affichage, déclenchant ainsi la transformation : img.content.transform.matrix = tempMatrix; 230 Dernière mise à jour le 27/4/2013 Chapitre 12 : Utilisation de l’API de dessin Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Bien que l’importance des images et graphiques importés soit évidente, il ne faut pas négliger la fonctionnalité connue sous le nom d’API de dessin, qui permet de tracer des lignes et des formes en ActionScript. Vous pouvez ainsi ouvrir une application avec l’équivalent informatique d’une toile vierge et y créer des images. La possibilité de créer des graphiques ouvre de nouvelles possibilités pour vos applications. Les techniques présentées ci-après permettent notamment de créer un programme de dessin, de réaliser des éléments artistiques animés et interactifs ou de générer par programmation vos propres éléments d’interface. Voir aussi flash.display.Graphics Principes de base de l’API de dessin Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’API de dessin est le nom des fonctionnalités intégrées à ActionScript qui permettent de créer des graphiques vectoriels (lignes, courbes, formes, remplissages et dégradés) et de les afficher à l’aide d’ActionScript. Ces fonctionnalités sont prises en charge par la classe flash.display.Graphics. ActionScript permet de dessiner dans une occurrence d’un objet de type Shape, Sprite ou MovieClip, à l’aide de la propriété graphics définie dans chacune de ces classes (la propriété graphics de ces classes est en fait une occurrence de la classe Graphics). Si vous n’avez pas l’habitude de « dessiner » par code, la classe Graphics comprend plusieurs méthodes qui facilitent le tracé de formes courantes (cercles, ellipses, rectangles et rectangles à coins arrondis). Ces tracés peuvent être des lignes vides ou des formes remplies. Si vous avez besoin de fonctionnalités plus sophistiquées, la classe Graphics comporte aussi des méthodes destinées au tracé de lignes et de courbes de Bézier, qui peuvent être utilisées conjointement avec les fonctions trigonométriques de la classe Math pour créer n’importe quelle forme. Les moteurs d’exécution Flash (tels que Flash Player 10, Adobe AIR 1.5 et les versions ultérieures) prennent en charge une nouvelle API de dessin, qui vous permet de tracer intégralement des formes par programmation à l’aide d’une commande unique. Une fois que vous vous êtes familiarisé avec la classe Graphics et les tâches décrites dans « Bases d’utilisation de l’API de dessin », passez à « Utilisation avancée de l’API de dessin » à la page 243 pour en savoir plus sur ces fonctions. Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs à l’utilisation de l’API de dessin : Point d’ancrage L’un des deux points d’extrémité d’une courbe de Bézier. Point de contrôle Point qui définit la direction et la forme d’une courbe de Bézier. Cette ligne courbe ne touche jamais le point de contrôle, mais elle s’arrondit comme si elle était tracée dans la direction de celui-ci. Espace de coordonnées Représentation graphique des coordonnées contenues dans un objet d’affichage, par rapport auquel sont positionnés les éléments enfant. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 231 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Remplissage Partie intérieure opaque d’une forme constituée par le remplissage d’une ligne ou d’une forme ne possédant pas de ligne de contour. Dégradé Transition progressive d’une couleur à une ou plusieurs autres couleurs (par opposition à une couleur unie). Point Emplacement unique dans un espace de coordonnées. Dans le système de coordonnées en 2 dimensions utilisé dans ActionScript, un point est défini par son emplacement le long de l’axe x et de l’axe y (les coordonnées du point). Courbe de Bézier quadratique Type de courbe défini par une formule mathématique déterminée. Dans ce type de courbe, la forme de la courbe est calculée à partir des positions des points d’ancrage (les points d’extrémité de la courbe) et d’un point de contrôle qui définit la forme et la direction de la courbe. Mise à l’échelle Taille relative d’un objet par rapport à sa taille d’origine. Mettre un objet à l’échelle consiste à modifier sa taille en l’étirant ou en le rétrécissant. Trait Ligne de contour d’une forme constituée par le remplissage de cette ligne, ou forme ne possédant pas de remplissage. Translation Conversion des coordonnées d’un point d’un espace de coordonnées à un autre. Axe x Axe horizontal dans le système de coordonnées en 2 dimensions utilisé dans ActionScript. Axe y Axe vertical dans le système de coordonnées en 2 dimensions utilisé dans ActionScript. Classe Graphics Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Chaque objet Shape, Sprite et MovieClip possède une propriété graphics qui est une occurrence de la classe Graphics. La classe Graphics comporte des propriétés et des méthodes permettant de tracer des lignes, des remplissages et des formes. Pour disposer d’un objet d’affichage qui sera uniquement utilisé comme « toile de fond » pour un dessin, utilisez une occurrence de Shape. Une occurrence de Shape est mieux adaptée au dessin que les autres objets, car elle ne comporte pas les fonctionnalités (inutiles dans ce type d’utilisation) des classes Sprite et MovieClip. Par contre, si vous souhaitez créer un objet d’affichage qui servira de support à du contenu graphique mais doit également pouvoir contenir d’autres objets d’affichage, utilisez une occurrence de Sprite. Pour plus d’informations sur le choix des objets d’affichage en fonction de la tâche prévue, voir « Sélection d’une sous-classe de DisplayObject » à la page 179 Dessin de lignes et de courbes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Tous les graphiques qu’il est possible de réaliser à l’aide d’une occurrence de la classe Graphics sont des tracés à l’aide de lignes et de courbes. Tous les dessins réalisés en ActionScript doivent donc suivre les mêmes étapes : • Définition de styles de ligne et de remplissage • Définition de la position de dessin initiale • Dessin de lignes, courbes et formes (éventuellement en déplaçant le point de traçage) • Le cas échéant, création d’un remplissage GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 232 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Définition de styles de ligne et de remplissage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour utiliser la propriété graphics d’une occurrence de Shape, Sprite ou MovieClip, vous devez d’abord définir le style (épaisseur et couleur de la ligne, couleur de remplissage) à utiliser. A l’instar des outils de dessin d’Adobe® Flash® Professional ou de toute autre application de dessin, en ActionScript vous pouvez dessiner avec ou sans trait, et avec ou sans remplissage. Pour indiquer l’apparence du trait, utilisez la méthode lineStyle() ou lineGradientStyle(). Pour créer une ligne pleine, utilisez la méthode lineStyle(). Lors de l’appel de cette méthode, les valeurs les plus courantes à indiquer sont les trois premiers paramètres : épaisseur de ligne, couleur et alpha. Par exemple, la ligne de code suivante indique que la forme myShape doit tracer des lignes de deux pixels d’épaisseur, en rouge (0x990000) et avec une opacité de 75 % : myShape.graphics.lineStyle(2, 0x990000, .75); La valeur par défaut du paramètre alpha est 1.0 (100 %), vous pouvez donc l’omettre si vous souhaitez tracer une ligne entièrement opaque. La méthode lineStyle() gère également deux autres paramètres associés à l’indice de lissage des pixels et au mode de mise à l’échelle. Pour plus d’informations sur ces paramètres, voir la description de la méthode Graphics.lineStyle() dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Pour créer une ligne dégradée, utilisez la méthode lineGradientStyle(). Pour plus d’informations sur cette méthode, voir « Création de lignes et de remplissages en dégradé » à la page 235. Pour créer une forme remplie, appelez les méthodes beginFill(), beginGradientFill(), beginBitmapFill() ou beginShaderFill() avant de débuter le dessin. La plus basique, beginFill(), accepte deux paramètres : la couleur de remplissage et, le cas échéant, la valeur alpha correspondante. Par exemple, pour tracer une forme avec un remplissage vert uni, utilisez le code suivant (on suppose ici que vous dessinez dans un objet nommé myShape) : myShape.graphics.beginFill(0x00FF00); L’appel d’une méthode de remplissage annule implicitement le remplissage précédemment défini avant l’implémentation du nouveau. L’appel d’une méthode qui spécifie un style de trait remplace le style de trait précédent, mais ne modifie pas le remplissage précédemment défini, et vice-versa. Une fois spécifié le style de ligne et de remplissage, l’étape suivante consiste à indiquer le point de départ du dessin. L’occurrence de Graphics possède un point de traçage, tout comme la pointe d’un crayon sur une feuille de papier. Quel que soit l’emplacement du point de traçage, il représente l’origine de l’action de dessin à venir. Initialement, un objet Graphics débute avec son point de traçage aux points 0,0 dans l’espace de coordonnées de l’objet dans lequel il dessine. Pour que le tracé débute en un autre point, appelez la méthode moveTo() avant d’appeler une des méthodes de dessin. Cet appel peut être comparé à l’action de lever la pointe du crayon du papier et de l’amener à un nouvel emplacement. Lorsque le point de traçage est en place, utilisez une série d’appels aux méthodes lineTo() (pour tracer des lignes droites) et curveTo() (pour tracer des courbes). Pendant l’opération de dessin, vous pouvez à tout moment appeler la méthode moveTo() pour amener le point de traçage à une nouvelle position sans dessiner. Si vous avez défini une couleur de remplissage, vous pouvez désactiver le remplissage en appelant la méthode endFill() pendant l’opération de dessin. Si vous n’avez pas tracé de forme fermée (autrement dit, si lors de l’appel de la méthode endFill() le point de traçage ne correspond pas au point de départ de la forme), lorsque vous appelez la méthode endFill(), le moteur d’exécution Flash ferme automatiquement la forme en traçant une ligne droite entre le point de traçage actuel et l’emplacement spécifié dans le dernier appel à la méthode moveTo(). Si vous avez débuté un remplissage et n’avez pas appelé endFill(), tout appel à beginFill() (ou à l’une des autres méthodes de remplissage) ferme le remplissage actif et en débute un nouveau. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 233 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Dessin de lignes droites Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous appelez la méthode lineTo(), l’objet Graphics trace une ligne droite (en utilisant le style de ligne que vous avez spécifié) entre le point de traçage actuel et les coordonnées que vous transmettez en paramètres à cette méthode. Par exemple, cette ligne de code place le point de traçage aux coordonnées 100, 100 puis trace une ligne jusqu’au point 200, 200 : myShape.graphics.moveTo(100, 100); myShape.graphics.lineTo(200, 200); L’exemple suivant trace des triangles rouges et verts d’une hauteur de 100 pixels : var triangleHeight:uint = 100; var triangle:Shape = new Shape(); // red triangle, starting at point 0, 0 triangle.graphics.beginFill(0xFF0000); triangle.graphics.moveTo(triangleHeight / 2, 0); triangle.graphics.lineTo(triangleHeight, triangleHeight); triangle.graphics.lineTo(0, triangleHeight); triangle.graphics.lineTo(triangleHeight / 2, 0); // green triangle, starting at point 200, 0 triangle.graphics.beginFill(0x00FF00); triangle.graphics.moveTo(200 + triangleHeight / 2, 0); triangle.graphics.lineTo(200 + triangleHeight, triangleHeight); triangle.graphics.lineTo(200, triangleHeight); triangle.graphics.lineTo(200 + triangleHeight / 2, 0); this.addChild(triangle); Dessin de courbes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode curveTo() dessine une courbe de Bézier. Elle trace un arc entre deux points (appelés points d’ancrage) courbé en direction d’un troisième point (appelé point de contrôle). L’objet Graphics utilise la position de traçage actuelle comme premier point d’ancrage. Lorsque vous appelez la méthode curveTo(), vous transmettez quatre paramètres : les coordonnées x et y du point de contrôle, puis les coordonnées x et y du second point d’ancrage. Par exemple, le code suivant trace une courbe entre le point 100, 100 et le point 200, 200. Le point de contrôle ayant les coordonnées 175, 125, la courbe est orientée vers la droite puis vers le bas : myShape.graphics.moveTo(100, 100); myShape.graphics.curveTo(175, 125, 200, 200); L’exemple suivant trace des objets circulaires rouges et verts avec une largeur et une hauteur de 100 pixels. Notez qu’en raison même de la nature de l’équation de Bézier, ces cercles ne sont pas parfaits : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 234 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 var size:uint = 100; var roundObject:Shape = new Shape(); // red circular shape roundObject.graphics.beginFill(0xFF0000); roundObject.graphics.moveTo(size / 2, 0); roundObject.graphics.curveTo(size, 0, size, size / 2); roundObject.graphics.curveTo(size, size, size / 2, size); roundObject.graphics.curveTo(0, size, 0, size / 2); roundObject.graphics.curveTo(0, 0, size / 2, 0); // green circular shape roundObject.graphics.beginFill(0x00FF00); roundObject.graphics.moveTo(200 + size / 2, 0); roundObject.graphics.curveTo(200 + size, 0, 200 + size, size / 2); roundObject.graphics.curveTo(200 + size, size, 200 + size / 2, size); roundObject.graphics.curveTo(200, size, 200, size / 2); roundObject.graphics.curveTo(200, 0, 200 + size / 2, 0); this.addChild(roundObject); Dessin de formes à l’aide des méthodes intégrées Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour vous permettre de tracer plus commodément des formes courantes (cercles, ellipses, rectangles et rectangles à coins arrondis), ActionScript 3.0 comporte des méthodes qui tracent automatiquement ces formes. Ces méthodes sont drawCircle(), drawEllipse(), drawRect() et drawRoundRect(), et sont toutes définies dans la classe Graphics. Elles peuvent être utilisées à la place des méthodes lineTo() et curveTo(). Notez toutefois qu’il est nécessaire de spécifier des styles de ligne et de remplissage avant d’appeler ces méthodes. L’exemple suivant dessine des carrés bleus, rouges et verts avec une largeur et une hauteur de 100 pixels. Ce code utilise la méthode drawRect() et spécifie que l’opacité de la couleur de remplissage est de 50 % (0,5) : var squareSize:uint = 100; var square:Shape = new Shape(); square.graphics.beginFill(0xFF0000, 0.5); square.graphics.drawRect(0, 0, squareSize, squareSize); square.graphics.beginFill(0x00FF00, 0.5); square.graphics.drawRect(200, 0, squareSize, squareSize); square.graphics.beginFill(0x0000FF, 0.5); square.graphics.drawRect(400, 0, squareSize, squareSize); square.graphics.endFill(); this.addChild(square); Dans un objet Sprite ou MovieClip, tout contenu graphique créé à l’aide de la propriété graphics apparaît toujours derrière les objets d’affichage enfant contenus par cet objet. Par ailleurs, le contenu créé avec la propriété graphics n’est pas un objet d’affichage séparé. Il n’apparaît donc pas dans la liste des enfants d’un objet Sprite ou MovieClip. Par exemple, l’objet Sprite suivant reçoit l’instruction de tracer un cercle avec sa propriété graphics, et un objet TextField figure dans sa liste d’objets d’affichage enfant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 235 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 var mySprite:Sprite = new Sprite(); mySprite.graphics.beginFill(0xFFCC00); mySprite.graphics.drawCircle(30, 30, 30); var label:TextField = new TextField(); label.width = 200; label.text = "They call me mellow yellow..."; label.x = 20; label.y = 20; mySprite.addChild(label); this.addChild(mySprite); Notez que l’objet TextField apparaît au-dessus du cercle tracé avec la propriété graphics. Création de lignes et de remplissages en dégradé Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’objet Graphics permet aussi de tracer des traits et des remplissages avec des dégradés au lieu de couleurs unies. Pour créer un trait dégradé, utilisez la méthode lineGradientStyle(). Pour créer un remplissage dégradé, utilisez la méthode beginGradientFill(). Ces deux méthodes reçoivent les mêmes paramètres. Les quatre premiers sont obligatoires : type, couleurs, transparences alpha et rapports. Les quatre suivants sont facultatifs mais peuvent être utiles pour plus de personnalisation. • Le premier paramètre spécifie le type de dégradé à créer. Les valeurs acceptables sont GradientType.LINEAR ou GradientType.RADIAL. • Le deuxième paramètre indique le tableau de valeurs colorimétriques à utiliser. Dans un dégradé linéaire, les couleurs sont organisées de gauche à droite. Dans un dégradé radial, les couleurs sont organisées de l’intérieur à l’extérieur. L’ordre des couleurs dans le tableau représente l’ordre dans lequel elles sont tracées dans le dégradé. • Le troisième paramètre indique les valeurs de transparence alpha pour les couleurs correspondantes du paramètre précédent. • Le quatrième paramètre spécifie les rapports, c’est-à-dire l’importance de chaque couleur dans le dégradé. Les valeurs acceptables vont de 0 à 255. Ces valeurs ne représentent pas une hauteur ou une largeur, mais plutôt la position au sein du dégradé : 0 représente le début du dégradé, et 255 la fin. Cette plage de rapports doit augmenter séquentiellement et comporter le même nombre d’éléments que les tableaux des couleurs et des valeurs alpha spécifiés comme deuxième et troisième paramètres. Le cinquième paramètre, la matrice de transformation, est facultatif mais fréquemment utilisé, car il représente un moyen à la fois puissant et aisé de contrôler l’aspect du dégradé. Ce paramètre accepte une occurrence de l’objet Matrix. Le moyen le plus simple de créer un objet Matrix pour un dégradé consiste à utiliser la méthode createGradientBox() de la classe Matrix. Définition d’un objet Matrix à utiliser avec un dégradé Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Utilisez les méthodes beginGradientFill() et lineGradientStyle() de la classe flash.display.Graphics pour définir les dégradés à utiliser dans des formes. Lorsque vous définissez un dégradé, vous fournissez une matrice comme l’un des paramètres de ces méthodes. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 236 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 La façon la plus facile de définir la matrice est d’utiliser la méthode createGradientBox(), de la classe Matrix, qui définit un tableau utilisé pour définir le dégradé. Définissez l’échelle, la rotation et la position du dégradé à l’aide des paramètres transmis à la méthode createGradientBox(). La méthode createGradientBox() reçoit les paramètres suivants : • Largeur de la zone de dégradé : largeur (en pixels) sur laquelle s’étend le dégradé • Hauteur de la zone de dégradé : hauteur (en pixels) sur laquelle s’étend le dégradé • Rotation de la zone de dégradé : rotation (en radians) qui sera appliquée au dégradé • Translation horizontale : distance (en pixels) de déplacement horizontal du dégradé • Translation verticale : distance (en pixels) de déplacement vertical du dégradé Par exemple, supposons un dégradé possédant les caractéristiques suivantes : • GradientType.LINEAR • Deux couleurs, vert et bleu, avec le tableau ratios défini sur [0, 255] • SpreadMethod.PAD • InterpolationMethod.LINEAR_RGB Les exemples suivants présentent des dégradés dans lesquels le paramètre rotation de la méthode createGradientBox() varie comme indiqué, mais tous les autres réglages restent inchangés : Les exemples suivants présentent les effets sur un dégradé linéaire vert à bleu dans lequel les paramètres rotation, tx et ty de la méthode createGradientBox() varient comme indiqué, mais tous les autres réglages restent inchangés : width = 100; height = 100; rotation = 0; tx = 0; ty = 0; width = 100; height = 100; rotation = Math.PI/4; // 45° tx = 0; ty = 0; width = 100; height = 100; rotation = Math.PI/2; // 90° tx = 0; ty = 0; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 237 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Les paramètres width, height, tx et ty de la méthode createGradientBox() ont une incidence sur la taille et la position d’un remplissage en dégradé radial également, comme indiqué dans l’exemple suivant : Le code suivant produit le dernier dégradé radial illustré : width = 50; height = 100; rotation = 0; tx = 0; ty = 0; width = 50; height = 100; rotation = 0 tx = 50; ty = 0; width = 100; height = 50; rotation = Math.PI/2; // 90° tx = 0; ty = 0; width = 100; height = 50; rotation = Math.PI/2; // 90° tx = 0; ty = 50; width = 50; height = 100; rotation = 0; tx = 25; ty = 0; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 238 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 import flash.display.Shape; import flash.display.GradientType; import flash.geom.Matrix; var type:String = GradientType.RADIAL; var colors:Array = [0x00FF00, 0x000088]; var alphas:Array = [1, 1]; var ratios:Array = [0, 255]; var spreadMethod:String = SpreadMethod.PAD; var interp:String = InterpolationMethod.LINEAR_RGB; var focalPtRatio:Number = 0; var matrix:Matrix = new Matrix(); var boxWidth:Number = 50; var boxHeight:Number = 100; var boxRotation:Number = Math.PI/2; // 90° var tx:Number = 25; var ty:Number = 0; matrix.createGradientBox(boxWidth, boxHeight, boxRotation, tx, ty); var square:Shape = new Shape; square.graphics.beginGradientFill(type, colors, alphas, ratios, matrix, spreadMethod, interp, focalPtRatio); square.graphics.drawRect(0, 0, 100, 100); addChild(square); Notez que la largeur et la hauteur du dégradé sont déterminées par la largeur et la hauteur de la matrice du dégradé, plutôt que par celles qui sont dessinées à l’aide de l’objet Graphics. Si vous dessinez avec l’objet Graphics, vous tracez ce qui existe à ces coordonnées dans la matrice du dégradé. Même si vous utilisez l’une des méthodes de création de forme d’un objet de type Graphics, par exemple drawRect(), le dégradé n’est pas étiré en fonction de la taille de la forme dessinée : sa taille doit être spécifiée dans la matrice du dégradé. L’exemple ci-dessous illustre la différence visuelle entre les dimensions de la matrice du dégradé et celles du dessin : var myShape:Shape = new Shape(); var gradientBoxMatrix:Matrix = new Matrix(); gradientBoxMatrix.createGradientBox(100, 40, 0, 0, 0); myShape.graphics.beginGradientFill(GradientType.LINEAR, [0xFF0000, 0x00FF00, 0x0000FF], [1, 1, 1], [0, 128, 255], gradientBoxMatrix); myShape.graphics.drawRect(0, 0, 50, 40); myShape.graphics.drawRect(0, 50, 100, 40); myShape.graphics.drawRect(0, 100, 150, 40); myShape.graphics.endFill(); this.addChild(myShape); Ce code trace trois dégradés avec le même style de remplissage, spécifié avec une distribution égale de rouge, vert et bleu. Les dégradés sont tracés à l’aide de la méthode drawRect() avec des largeurs en pixels de 50, 100 et 150 respectivement. La matrice de dégradé qui est spécifiée dans la méthode beginGradientFill() est créée avec une largeur de 100 pixels. Le premier dégradé ne couvre donc que la moitié de son spectre, le deuxième le couvre en entier, et le troisième le couvre en entier et possède 50 pixels supplémentaires de bleu à droite. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 239 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 La méthode lineGradientStyle() fonctionne de façon similaire à beginGradientFill(), si ce n’est qu’outre la définition du dégradé vous devez aussi indiquer l’épaisseur du trait à l’aide de la méthode lineStyle() avant de tracer. Le code suivant trace une boîte avec un trait dégradé rouge, vert et bleu : var myShape:Shape = new Shape(); var gradientBoxMatrix:Matrix = new Matrix(); gradientBoxMatrix.createGradientBox(200, 40, 0, 0, 0); myShape.graphics.lineStyle(5, 0); myShape.graphics.lineGradientStyle(GradientType.LINEAR, [0xFF0000, 0x00FF00, 0x0000FF], [1, 1, 1], [0, 128, 255], gradientBoxMatrix); myShape.graphics.drawRect(0, 0, 200, 40); this.addChild(myShape); Pour plus d’informations sur la classe Matrix, voir « Utilisation des objets Matrix » à la page 224. Utilisation de la classe Math avec les méthodes de dessin Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un objet Graphics trace des cercles et des carrés, mais il permet aussi de dessiner des formes plus complexes, en particulier lorsque les méthodes de dessin sont utilisées en combinaison avec les propriétés et les méthodes de la classe Math. La classe Math contient des constantes d’intérêt général en mathématiques, telles que Math.PI (environ 3,14159265...), qui est la constante définissant le rapport entre la circonférence et le diamètre d’un cercle. Elle contient également des méthodes de fonctions trigonométriques, entre autres Math.sin(), Math.cos() et Math.tan(). L’utilisation de ces méthodes et constantes pour le dessin de formes permet d’obtenir des effets visuels plus dynamiques, en particulier en utilisant des répétitions et des récursions. De nombreuses méthodes de la classe Math attendent des mesures circulaires en radians, et non en degrés. La conversion entre ces deux types d’unités représente elle-même un cas d’utilisation courante de la classe Math : var degrees = 121; var radians = degrees * Math.PI / 180; trace(radians) // 2.111848394913139 L’exemple suivant crée une onde sinusoïdale et une onde cosinusoïdale, afin d’illustrer la différence entre les méthodes Math.sin() et Math.cos() pour une même valeur. var sinWavePosition = 100; var cosWavePosition = 200; var sinWaveColor:uint = 0xFF0000; var cosWaveColor:uint = 0x00FF00; var waveMultiplier:Number = 10; var waveStretcher:Number = 5; var i:uint; for(i = 1; i < stage.stageWidth; i++) { var sinPosY:Number = Math.sin(i / waveStretcher) * waveMultiplier; var cosPosY:Number = Math.cos(i / waveStretcher) * waveMultiplier; graphics.beginFill(sinWaveColor); graphics.drawRect(i, sinWavePosition + sinPosY, 2, 2); graphics.beginFill(cosWaveColor); graphics.drawRect(i, cosWavePosition + cosPosY, 2, 2); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 240 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Animation avec l’API de dessin Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’un des avantages de la création de contenu graphique avec l’API de dessin est que ce contenu peut être repositionné à loisir. Tout ce que vous tracez peut être modifié, en modifiant simplement les variables utilisées pour ce dessin. Vous pouvez donc obtenir de l’animation en changeant les variables et en retraçant, soit sur un nombre d’images donné, soit à l’aide d’un timer. Par exemple, le code suivant change l’affichage à chaque nouvelle image (en écoutant l’événement Event.ENTER_FRAME) : il incrémente la valeur de degrés actuelle, puis ordonne à l’objet graphique d’effacer et redessiner avec la nouvelle position. stage.frameRate = 31; var currentDegrees:Number = 0; var radius:Number = 40; var satelliteRadius:Number = 6; var container:Sprite = new Sprite(); container.x = stage.stageWidth / 2; container.y = stage.stageHeight / 2; addChild(container); var satellite:Shape = new Shape(); container.addChild(satellite); addEventListener(Event.ENTER_FRAME, doEveryFrame); function doEveryFrame(event:Event):void { currentDegrees += 4; var radians:Number = getRadians(currentDegrees); var posX:Number = Math.sin(radians) * radius; var posY:Number = Math.cos(radians) * radius; satellite.graphics.clear(); satellite.graphics.beginFill(0); satellite.graphics.drawCircle(posX, posY, satelliteRadius); } function getRadians(degrees:Number):Number { return degrees * Math.PI / 180; } Pour produire un résultat nettement différent, vous pouvez expérimenter en modifiant les valeurs initiales au début du code, currentDegrees, radius et satelliteRadius. Par exemple, essayez en réduisant la valeur de la variable radius et/ou en augmentant la valeur de la variable totalSatellites. Ce n’est qu’un exemple simple de la façon dont l’API de dessin permet de créer du contenu visuel dont la complexité dissimule la simplicité de création. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 241 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Exemple d’utilisation de l’API de dessin : générateur algorithmique d’effets visuels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple de générateur algorithmique d’effets visuels trace de manière dynamique plusieurs « satellites », des cercles qui se déplacent suivant une orbite circulaire. Les fonctionnalités présentées sont les suivantes : • Utilisation de l’API de dessin pour tracer une forme simple avec un aspect dynamique • Utilisation de l’interaction de l’utilisateur pour modifier les propriétés utilisées pour le dessin • Effet d’animation par effacement du contenu et retraçage à chaque nouvelle image. L’exemple de la section précédente animait un satellite isolé à l’aide de l’événement Event.ENTER_FRAME. Cet exemple le reprend en y ajoutant un panneau de contrôle avec divers curseurs qui actualisent immédiatement l’affichage de plusieurs satellites. Dans cet exemple, le code est formalisé dans des classes externes et le code de création du satellite est imbriqué dans une boucle, en conservant une référence à chaque satellite dans le tableau satellites. Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers de l’application se trouvent dans le dossier Samples/AlgorithmicVisualGenerator. Celui-ci contient les fichiers suivants : Définition des écouteurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application commence par créer trois écouteurs. Le premier attend qu’un événement soit distribué par le panneau de contrôle pour signaler qu’une reconstruction des satellites est nécessaire. Le second attend des changements de taille de la scène du fichier SWF. Le troisième attend le passage de chaque image du fichier SWF et son retraçage à l’aide de la fonction doEveryFrame(). Fichier Description AlgorithmicVisualGenerator.fla Fichier d’application principal de Flash Professional (FLA) com/example/programmingas3/algorithmic/AlgorithmicVisualGenerator.as Classe comportant les principales fonctionnalités de l’application : dessin des satellites sur la scène et actualisation des variables utilisées pour ces dessins en réponse aux événements du panneau de contrôle. com/example/programmingas3/algorithmic/ControlPanel.as Cette classe gère les interactions de l’utilisateur avec les curseurs et distribue les événements appropriés. com/example/programmingas3/algorithmic/Satellite.as Cette classe représente l’objet d’affichage qui tourne sur son orbite autour d’un point central et contient des propriétés relatives à son état de dessin actuel. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 242 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Création des satellites Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Après la définition de ces écouteurs, la fonction build() est appelée. Cette fonction appelle d’abord la fonction clear(), qui efface le contenu du tableau satellites et supprime les éventuelles formes déjà présentes sur la scène. Cette précaution est nécessaire car la fonction build() peut être appelée à nouveau à la suite d’un événement diffusé par le panneau de contrôle, par exemple en cas de modification des couleurs. Dans ce cas, les satellites doivent être supprimés et recréés. La fonction crée ensuite les satellites, en définissant les propriétés initiales nécessaires à cette création, dont la variable position qui définit une position aléatoire sur l’orbite et la variable color, qui dans cet exemple ne change pas une fois que le satellite a été créé. Lors de la création de chaque satellite, une référence est ajoutée dans le tableau satellites. Lorsque la fonction doEveryFrame() est appelée, elle actualise tous les satellites du tableau. Actualisation de la position des satellites Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La fonction doEveryFrame() est au coeur du processus d’animation de l’application. Elle est appelée à chaque image, donc à une fréquence identique à la cadence du fichier SWF. Les variables du dessin changent légèrement, ce qui permet d’obtenir un effet d’animation. La fonction efface d’abord tous les éventuels dessins antérieurs et retrace l’arrière-plan. Elle effectue ensuite une boucle dans le conteneur de chaque satellite et incrémente la propriété position de chaque satellite, puis actualise les propriétés radius et orbitRadius qui peuvent avoir été modifiées par suite d’une action de l’utilisateur dans le panneau de contrôle. Enfin, la nouvelle position de chaque satellite est affichée en appelant la méthode draw() de la classe Satellite. Notez que la variable de compteur i n’est incrémentée que jusqu’à la valeur de la variable visibleSatellites. En effet, si l’utilisateur a limité à l’aide du panneau de contrôle le nombre de satellites affichés, les autres satellites de la boucle ne doivent pas être redessinés, mais masqués. La boucle chargée de cette action suit immédiatement celle qui est responsable du dessin. Lorsque la fonction doEveryFrame() se termine, le nombre de satellites visibles (visibleSatellites) est redessiné aux nouvelles positions. Réponse aux interactions de l’utilisateur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’interactivité est assurée par le panneau de contrôle, qui est géré par la classe ControlPanel. Cette classe définit pour chaque curseur un écouteur et des valeurs individuelles minimum, maximum et par défaut. Lorsque l’utilisateur déplace ces curseurs, la fonction changeSetting() est appelée. Elle actualise les propriétés du panneau de contrôle. Si la modification nécessite un nouvel affichage, un événement est distribué et pris en charge dans le fichier principal de l’application. En fonction de la modification signalée par le panneau de contrôle, la fonction doEveryFrame() redessine chaque satellite sur la base des nouvelles variables. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 243 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Améliorations possibles Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Cet exemple est simplement destiné à illustrer la création d’effets visuels avec l’API de dessin. Il utilise relativement peu de lignes de code pour créer une animation interactive qui semble très complexe. Même ainsi, cet exemple pourrait être amélioré moyennant quelques modifications mineures. Voici quelques idées : • La fonction doEveryFrame() pourrait incrémenter la valeur colorimétrique du satellite. • La fonction doEveryFrame() pourrait réduire ou augmenter progressivement le rayon de l’orbite du satellite. • Il n’est pas nécessaire que l’orbite du satellite soit circulaire, la classe Math permet de le déplacer selon une sinusoïdale, par exemple. • Les satellites pourraient utiliser une détection de collision entre eux. L’API de dessin peut être considérée comme autre solution pour la création d’effets visuels dans l’environnement de création Flash, en dessinant des formes de base lors de l’exécution. Mais elle permet aussi de créer des effets visuels qu’il serait impossible de créer manuellement. L’API de dessin et quelques notions de mathématiques permettent au développeur en ActionScript de donner vie à de nombreuses créations inattendues. Utilisation avancée de l’API de dessin Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Flash Player 10, Adobe AIR 1.5 et les moteurs d’exécution Flash ultérieurs prennent en charge un jeu avancé de fonctions de dessin. Les améliorations de l’API de dessin associées à ces moteurs d’exécution, qui étendent les méthodes de dessin des versions antérieures, vous permettent de définir des ensembles de données pour générer des formes, les modifier lors de l’exécution et créer des effets tridimensionnels. Les améliorations de l’API de dessin consolident les méthodes existantes comme commandes alternatives. Ces commandes s’appuient sur des tableaux de vecteurs et des classes d’énumération pour fournir des ensembles de données aux méthodes de dessin. Les tableaux de vecteurs accélèrent le rendu de formes plus complexes. Les développeurs peuvent modifier les valeurs des tableaux par programmation pour rendre des formes dynamiques à l’exécution. Les nouvelles fonctions de dessins de Flash Player 10 sont décrites dans les sections suivantes : « Tracés de dessin » à la page 244, « Définition des règles d’enroulement » à la page 245, « Utilisation des classes de données graphiques » à la page 247 et « A propos de l’utilisation de drawTriangles() » à la page 250. Vous souhaiterez probablement effectuer les tâches suivantes à l’aide des fonctions avancées de l’API de dessin dans ActionScript : • Stockage des données destinées aux méthodes de dessin à l’aide d’objets Vector • Définition de tracés pour tracer des formes par programmation en une seule opération • Définition de règles d’enroulement pour déterminer le remplissage de formes se chevauchant • La lecture du contenu graphique vectoriel d’un objet d’affichage, par exemple pour sérialiser et enregistrer les données graphiques, pour générer une feuille Sprite à l’exécution ou pour dessiner une copie du contenu graphique vectoriel. • Utilisation de triangles et de méthodes de dessin pour obtenir des effets tridimensionnels GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 244 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Concepts importants et terminologie La liste de référence suivante énumère les termes importants que vous rencontrerez dans cette section : • Vecteur : tableau de valeurs d’un type de données identique. Un objet Vector peut stocker un tableau de valeurs qu’utilisent des méthodes de dessin pour construire des lignes et des formes par le biais d’une commande unique. Pour plus d’informations sur les objets Vector, voir « Tableaux indexés » à la page 27. • Tracé : un tracé est composé d’un ou de plusieurs segments droits ou incurvés. Le début et la fin de chaque segment sont indiqués par des coordonnées qui fonctionnent à la manière d’épingles maintenant un fil en place. Un tracé peut être fermé (un cercle, par exemple) ou ouvert, s’il comporte des extrémités distinctes (une ligne onduleuse, par exemple). • Enroulement : direction d’un tracé tel qu’il est interprété par le rendu, soit positive (sens horaire) soit négative (sens antihoraire). • GraphicsStroke : classe permettant de définir le style de ligne. Bien que le « trait » à proprement parler n’ait pas été inclus dans la nouvelle API de dessin, l’utilisation d’une classe pour désigner un style de ligne avec ses propres propriétés de remplissage constitue l’une des améliorations intégrées. Vous pouvez régler dynamiquement le style d’une ligne à l’aide de la classe GraphicsStroke. • Objet Fill : objet créé à l’aide de classes d’affichage telles que flash.display.GraphicsBitmapFill et flash.display.GraphicsGradientFill, et transmis à la commande de dessin Graphics.drawGraphicsData(). Les objets Fill et les commandes de dessin optimisées proposent une approche de programmation plus orientée objets pour répliquer Graphics.beginBitmapFill() et Graphics.beginGradientFill(). Tracés de dessin Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La section sur le dessin de lignes et de courbes (voir « Dessin de lignes et de courbes » à la page 231) a présenté les commandes permettant de tracer une ligne (Graphics.lineTo()) ou courbe (Graphics.curveTo()) unique, puis de la déplacer vers un autre point (Graphics.moveTo()) pour obtenir une forme. Les méthodes Graphics.drawPath() et Graphics.drawTriangles() acceptent une série d’objets représentant ces mêmes commandes de dessin comme paramètre. Ces méthodes permettent de définir une série de commandes Graphics.lineTo(), Graphics.curveTo() ou Graphics.moveTo() traitées par le moteur d’exécution Flash en une seule instruction. La classe d’énumération GraphicsPathCommand définit une série de constantes qui correspondent aux commandes de dessin. Vous transmettez une série de ces constantes (encapsulées dans une occurrence de Vector) comme paramètre de la méthode Graphics.drawPath(). Vous pouvez ensuite rendre une forme entière ou plusieurs formes à l’aide d’une seule commande. Vous pouvez aussi modifier les valeurs transmises à ces méthodes pour modifier une forme existante. Outre l’occurrence Vector des commandes de dessin, la méthode drawPath() a besoin d’un ensemble de coordonnées qui correspondent aux coordonnées de chaque commande de dessin. Créez une occurrence de Vector contenant des coordonnées (instances de Number) et transmettez-la à la méthode drawPath() comme second argument (data). Remarque : les valeurs du vecteur ne sont pas des objets Point. Le vecteur est une série de nombres, dont chaque paire représente une paire de coordonnées x/y. La méthode Graphics.drawPath() fait correspondre chaque commande à ses valeurs de point respectives (une série de deux ou quatre nombres) pour générer un tracé dans l’objet Graphics : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 245 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 package { import flash.display.*; public class DrawPathExample extends Sprite { public function DrawPathExample(){ var squareCommands:Vector. = new Vector.(5, true); squareCommands[0] = GraphicsPathCommand.MOVE_TO; squareCommands[1] = GraphicsPathCommand.LINE_TO; squareCommands[2] = GraphicsPathCommand.LINE_TO; squareCommands[3] = GraphicsPathCommand.LINE_TO; squareCommands[4] = GraphicsPathCommand.LINE_TO; var squareCoord:Vector. = new Vector.(10, true); squareCoord[0] = 20; //x squareCoord[1] = 10; //y squareCoord[2] = 50; squareCoord[3] = 10; squareCoord[4] = 50; squareCoord[5] = 40; squareCoord[6] = 20; squareCoord[7] = 40; squareCoord[8] = 20; squareCoord[9] = 10; graphics.beginFill(0x442266);//set the color graphics.drawPath(squareCommands, squareCoord); } } } Définition des règles d’enroulement Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures L’API de dessin améliorée prend désormais en charge le concept d’« enroulement » de tracé, qui définit la direction de ce dernier. L’enroulement d’un tracé est soit positif (sens horaire) soit négatif (sens antihoraire). L’ordre dans lequel le rendu interprète les coordonnées que fournit le vecteur au paramètre data détermine l’enroulement. Enroulement positif et négatif A. Les flèches indiquent la direction du tracé. B. Enroulement positif (sens horaire) C. Enroulement négatif (sens antihoraire) B 1 3 2 0 1 2 0 3 C A GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 246 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 En outre, vous remarquerez que la méthode Graphics.drawPath() possède un troisième paramètre facultatif, appelé « winding » : drawPath(commands:Vector., data:Vector., winding:String = "evenOdd"):void Dans ce contexte, le troisième paramètre est une chaîne ou une constante qui détermine la règle d’enroulement ou de remplissage de tracés se croisant (les valeurs de constante sont définies dans la classe GraphicsPathWinding sous la forme GraphicsPathWinding.EVEN_ODD ou GraphicsPathWinding.NON_ZERO). La règle d’enroulement est importante lorsque des tracés se croisent. Règle d’enroulement standard, la règle pair-impair est utilisée par l’API de dessin héritée. C’est aussi la règle par défaut de la méthode Graphics.drawPath(). Lorsqu’elle est appliquée, des tracés qui se croisent alternent entre des remplissages ouverts et fermés. Si deux carrés utilisant un même remplissage se croisent, la zone d’intersection est remplie. En règle générale, les zones adjacentes ne sont pas remplies ou leur remplissage n’est pas effacé. La règle non null, en revanche, se fonde sur l’enroulement (direction du tracé) pour déterminer si les zones définies par des tracés qui se croisent sont remplies. Lorsque des tracés dont l’enroulement est différent se croisent, la zone définie n’est pas remplie, comme avec la règle pair-impair. Si l’enroulement est identique, la zone dont le remplissage serait effacé est remplie : Règles d’enroulement associée aux zones d’intersection A. Règle d’enroulement pair-impair B. Règle d’enroulement non nul Nom des règles d’enroulement Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Les noms se réfèrent à une règle beaucoup plus spécifique qui définit comment ces remplissages sont gérés. On affecte aux chemins d’enroulement positifs une valeur +1 et aux négatifs une valeur -1. A partir d’un point au sein d’une surface close d’une forme, tirez un trait qui s’étend indéfiniment. Le nombre de fois que cette ligne traverse un chemin, ainsi que les valeurs combinées de ces chemins, est utilisé pour déterminer le remplissage. Pour des enroulements pairimpair, c’est le nombre de fois que la ligne traverse un chemin qui est utilisé. Lorsque le décompte est un nombre impair, la zone est remplie. Lorsqu’il est impair, la zone ne l’est pas. Pour des enroulements non nuls, ce sont les valeurs affectées aux chemins qui sont utilisées. Lorsque les valeurs combinées du chemin ne sont pas nulles, la zone est remplie. Lorsque la valeur combinée est 0, la zone n’est pas remplie. A B GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 247 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Règles de décompte et remplissage d’enroulements A. Règle d’enroulement pair-impair B. Règle d’enroulement non nul Utilisation des règles d’enroulement Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Ces règles de remplissage sont complexes mais elles s’avèrent nécessaires dans certaines situations. Par exemple, prenons le dessin d’une forme étoilée. Suivant la règle pair-impair standard, la forme nécessiterait dix lignes différentes. Suivant la règle d’enroulement non nul, ces dix lignes sont réduites à cinq. Voici le code ActionScript pour une étoile à cinq lignes et une règle d’enroulement non nul : graphics.beginFill(0x60A0FF); graphics.drawPath( Vector.([1,2,2,2,2]), Vector.([66,10, 23,127, 122,50, 10,49, 109,127]), GraphicsPathWinding.NON_ZERO); Et voici la forme de l’étoile : Une forme d’étoile qui utilise différentes règles d’enroulement A. 10 lignes en pair-impair B. 5 lignes en pair-impair C. 5 lignes non nulles Et, comme les images sont animées ou utilisées comme textures sur des objets à trois dimensions et qu’elles se recouvrent, les règles d’enroulement deviennent plus importantes. Utilisation des classes de données graphiques Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures L’API de dessin amélioré inclut un ensemble de classes dans le package flash.display qui met en oeuvre l’interface IGraphicsData. Ces classes fonctionnent comme des objets de valeur (conteneurs de données) qui représentent les méthodes de l’API de dessin. Les classes suivantes implémentent l’interface IGraphicsData : • GraphicsBitmapFill • GraphicsEndFill A B A B C GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 248 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 • GraphicsGradientFill • GraphicsPath • GraphicsShaderFill • GraphicsSolidFill • GraphicsStroke • GraphicsTrianglePath Ces classes vous permettent de stocker un dessin complet dans un objet Vector de type IGraphicsData (Vector.). Vous pouvez ensuite réutiliser les données graphiques comme source de données pour les autres instances de la forme ou pour stocker les informations de dessin pour une utilisation ultérieure. Vous remarquerez qu’il existe plusieurs classes de remplissage (Fill) correspondant à chaque style de remplissage, mais une seule classe de trait (Stroke). ActionScript propose une seule classe de trait IGraphicsData car elle définit son style sur la base des classes de remplissage. Ainsi, chaque trait est en fait défini par une combinaison de la classe stroke et d’une classe fill. Pour le reste, l’API de ces classes de données graphiques est identique aux méthodes qu’elles représentent dans la classe flash.display.Graphics : En outre, la classe GraphicsPath possède ses propres méthodes d’utilitaire (GraphicsPath.moveTo(), GraphicsPath.lineTo(), GraphicsPath.curveTo(), GraphicsPath.wideLineTo() et GraphicsPath.wideMoveTo()) pour simplifier la définition de ces commandes pour une occurrence de GraphicsPath. Ces méthodes facilitent la définition ou la mise à jour directe des commandes et des valeurs de données. Réalisation d’un dessin avec les données graphiques vectorielles Lorsque vous disposez d’une série d’instances de IGraphicsData, utilisez la méthode drawGraphicsData() de la classe Graphics pour effectuer le rendu des graphiques. La méthode drawGraphicsData() exécute un ensemble d’instructions de dessin à partir d’un vecteur d’instances de IGraphicsData en séquence : Méthode graphique Classe correspondante beginBitmapFill() GraphicsBitmapFill beginFill() GraphicsSolidFill beginGradientFill() GraphicsGradientFill beginShaderFill() GraphicsShaderFill lineBitmapStyle() GraphicsStroke + GraphicsBitmapFill lineGradientStyle() GraphicsStroke + GraphicsGradientFill lineShaderStyle() GraphicsStroke + GraphicsShaderFill lineStyle() GraphicsStroke + GraphicsSolidFill moveTo() lineTo() curveTo() drawPath() GraphicsPath drawTriangles() GraphicsTrianglePath GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 249 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 // stroke object var stroke:GraphicsStroke = new GraphicsStroke(3); stroke.joints = JointStyle.MITER; stroke.fill = new GraphicsSolidFill(0x102020);// solid stroke // fill object var fill:GraphicsGradientFill = new GraphicsGradientFill(); fill.colors = [0x0000FF, 0xEEFFEE]; fill.matrix = new Matrix(); fill.matrix.createGradientBox(70, 70, Math.PI/2); // path object var path:GraphicsPath = new GraphicsPath(new Vector.(), new Vector.()); path.commands.push(GraphicsPathCommand.MOVE_TO, GraphicsPathCommand.LINE_TO, GraphicsPathCommand.LINE_TO); path.data.push(125,0, 50,100, 175,0); // combine objects for complete drawing var drawing:Vector. = new Vector.(); drawing.push(stroke, fill, path); // draw the drawing graphics.drawGraphicsData(drawing); En modifiant une valeur du tracé utilisé par le dessin de l’exemple, il est possible de retracer la forme plusieurs fois pour obtenir une image plus complexe : // draw the drawing multiple times // change one value to modify each variation graphics.drawGraphicsData(drawing); path.data[2] += 200; graphics.drawGraphicsData(drawing); path.data[2] -= 150; graphics.drawGraphicsData(drawing); path.data[2] += 100; graphics.drawGraphicsData(drawing); path.data[2] -= 50;graphicsS.drawGraphicsData(drawing); Bien que les objets IGraphicsData puissent définir des styles de remplissage et de trait, ceux-ci ne sont pas obligatoires. Autrement dit, il est possible de définir des styles à l’aide des méthodes de la classe Graphics ou d’utiliser des objets IGraphicsData pour tracer un ensemble enregistré de tracés, et inversement. Remarque : la méthode Graphics.clear() permet d’effacer un dessin avant d’en commencer un nouveau, à moins que vous ne complétiez le dessin d’origine, comme l’illustre l’exemple ci-dessus. Lorsque vous modifiez une partie d’un tracé ou d’un ensemble d’objets IGraphicsData, retracez le dessin entier pour visualiser les changements. Lorsque vous utilisez des classes de données graphiques, le remplissage est rendu chaque fois que trois points au moins sont tracés car la forme est nécessairement fermée à ce point. Bien que le remplissage ait un effet de fermeture, ce n’est pas le cas du trait. Ce comportement est différent de celui de commandes Graphics.lineTo() ou Graphics.moveTo() utilisées plusieurs fois. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 250 Utilisation de l’API de dessin Dernière mise à jour le 27/4/2013 Lecture de données graphiques vectorielles Flash Player 11.6 et les versions ultérieures, Adobe AIR 3.6 et les versions ultérieures Dans Flash Player 11.6, Adobe AIR 3.6 et versions ultérieures, vous pouvez utiliser la méthode readGraphicsData() de la classe Graphics non seulement pour tracer le contenu vectoriel d’un objet d’affichage, mais aussi pour obtenir une représentation en données du contenu graphique vectoriel de cet objet. Ceci peut être utilisé pour créer un instantané d’un graphique afin notamment d’enregistrer, de copier ou de créer une feuille Sprite lors de l’exécution. L’appel de la méthode readGraphicsData() renvoie une occurrence de Vector contenant des objets IGraphicsData. Il s’agit des mêmes objets que ceux utilisés pour tracer des graphiques vectoriels à l’aide de la méthode drawGraphicsData(). Plusieurs limitations s’appliquent à la lecture des graphiques vectoriels avec la méthode readGraphicsData(). Pour plus d’informations, voir l’entrée readGraphicsData() dans le Guide de référence ActionScript. A propos de l’utilisation de drawTriangles() Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Une autre méthode avancée intégrée à Flash Player 10 et Adobe AIR 1.5, Graphics.drawTriangles(), s’apparente à la méthode Graphics.drawPath(). La méthode Graphics.drawTriangles() utilise également un objet Vector. pour spécifier les points permettant de dessiner un tracé. La méthode Graphics.drawTriangles() a néanmoins pour but principal de faciliter la création d’effets tridimensionnels par le biais d’ActionScript. Pour plus d’informations sur l’utilisation de Graphics.drawTriangles() pour produire des effets tridimensionnels, voir « Création d’effets 3D à l’aide de triangles » à la page 375. 251 Dernière mise à jour le 27/4/2013 Chapitre 13 : Utilisation des images bitmap Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Outre ses possibilités en matière de dessin vectoriel, ActionScript 3.0 permet également de créer des images bitmap ou de manipuler les données de pixels d’images bitmap externes chargées dans un fichier SWF. Cette possibilité de lire et modifier des valeurs de pixel individuelles permet de créer des effets visuels comme ceux des filtres et d’utiliser les fonctions intégrées de gestion du « bruit » pour créer des textures et des bruits aléatoires. • Renaun Erickson: Rendering game assets in ActionScript using blitting techniques (disponible en anglais uniquement) • Bitmap programming: chapitre 26 du document Essential ActionScript 3, par Colin Moock (O’Reilly Media, 2007, disponible en anglais uniquement) • Mike Jones: Working with Sprites in Pushbutton Engine (disponible en anglais uniquement) • Flash & Math: Pixel Particles Made Simple (disponible en anglais uniquement) • Flixel Principes de base de l’utilisation des images bitmap Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Tout travail avec des images numériques nécessite de gérer deux types de graphismes : les bitmaps et les graphismes vectoriels. Les images bitmap, également appelées graphismes en points, sont composées de petits carrés (les pixels) organisés en une grille rectangulaire. De leur côté, les graphismes vectoriels sont composés de formes géométriques (lignes, courbes et polygones) générées à l’aide de formules mathématiques. Les images bitmap sont définies par la largeur et la hauteur de l’image, mesurées en pixels, et par le nombre de bits contenu dans chaque pixel (ce nombre de bits définit le nombre de couleurs que peut comporter l’image). Dans le cas d’une image bitmap utilisant le modèle colorimétrique RVB, les pixels sont composés de trois octets : rouge, vert et bleu. Chaque octet contient une valeur comprise entre 0 et 255. C’est la combinaison de ces octets pour chaque pixel qui produit une couleur, un peu comme le mélange des couleurs de base par un peintre. Par exemple, un pixel contenant les valeurs 255, 102 et 0 respectivement pour les octets dévolus au rouge, au vert et au bleu produira un orange vif. La qualité d’une image bitmap est déterminée en combinant la résolution en pixels de l’image avec sa profondeur de couleur exprimée en bits ou en octets. La résolution définit le nombre de pixels contenus dans l’image. Plus le nombre de pixels est important, plus la résolution est élevée et plus l’image semble bien définie. La profondeur de couleurs définit la quantité d’informations colorimétriques contenues par chaque pixel. Par exemple, une image ayant une profondeur de couleur de 16 bits par pixel ne peut pas représenter un nombre de nuances aussi élevé qu’une image ayant une profondeur de couleur de 48 bits. En conséquence, l’image sur 48 bits aura plus de nuances que la version sur 16 bits. Dans la mesure où les images bitmap dépendent de la résolution, il est délicat de modifier leur échelle, ce qui se remarque particulièrement avec les images bitmap agrandies, qui perdent beaucoup de détails et de qualité. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 252 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Format des fichiers bitmap Les images bitmap existent en divers formats de fichier. Ces formats utilisent différents types d’algorithmes de compression pour réduire la taille des fichiers et optimiser la qualité de l’image en fonction de sa destination. Les moteurs d’exécution Adobe gèrent les formats d’image bitmap BMP, GIF, JPG, PNG et TIFF. BMP Le format BMP (pixellisé) est un format d’image par défaut utilisé par le système d’exploitation Microsoft Windows. Il ne fait appel à aucune forme d’algorithme de compression ; il en résulte généralement des tailles de fichiers assez importantes. GIF Le format GIF (Graphics Interchange Format) fut développé à l’origine par CompuServe en 1987, dans le but de transmettre des images en 256 couleurs (codées sur 8 bits). Ce format, qui permet d’obtenir des fichiers de petite taille, est très utilisé pour les images sur le Web. Toutefois, en raison de son nombre limité de couleurs, ce format n’est pas adapté aux photographies, qui nécessitent en général un nombre de nuances plus élevé. Les images GIF autorisent la transparence sur un bit, ce qui permet de rendre les couleurs invisibles (ou transparentes). C’est ainsi que sont produits les fonds transparents des images de pages Web. JPEG Développé par le Joint Photographic Experts Group (JPEG), le format d’image JPEG (souvent noté JPG) fait appel à un algorithme de compression avec perte pour autoriser une profondeur de couleur de 24 bits avec une taille de fichier très réduite. En raison de la compression avec perte, chaque fois que l’image est enregistrée elle perd des données, donc de la qualité, mais la taille de fichier résultante en est d’autant plus réduite. Le format JPEG est idéal pour les photographies, car il permet d’afficher des millions de couleurs différentes. La possibilité de contrôler le taux de compression appliqué à l’image permet de modifier la qualité de l’image et la taille du fichier. PNG Le format PNG (Portable Network Graphics) a été créé comme autre possibilité gratuite (open source) au format de fichier GIF, qui est breveté. Les fichiers PNG acceptent jusqu’à 64 bits de profondeur de couleur, ce qui permet d’obtenir jusqu’à 16 millions de couleurs. Le format PNG étant relativement récent, les versions anciennes de certains navigateurs ne gèrent pas ces fichiers. Contrairement au JPG, le format PNG utilise une compression sans perte, ce qui signifie qu’aucune donnée de l’image n’est perdue lors de l’enregistrement. De plus, les fichiers PNG acceptent également la transparence alpha, ce qui autorise jusqu’à 256 niveaux de transparence. TIFF Le format TIFF (ou Tagged Image File Format) était le format multiplate-forme de choix avant l’arrivée de PNG. Le format TIFF a un inconvénient qui est la multiplicité de ses variétés : aucun lecteur n’est en mesure de traiter toutes les versions disponibles. De surcroît, les navigateurs Web ne prennent pas en charge ce format actuellement. TIFF peut utiliser une compression avec ou sans pertes et il est en mesure de traiter des espaces de couleurs spécifiques au périphérique tels que CMJN (cyan-magenta-jaune-noir). Fichiers bitmap transparents et opaques Les images bitmap qui utilisent le format GIF ou PNG peuvent comporter pour chaque pixel un octet supplémentaire pour le canal alpha. Cet octet de pixel supplémentaire représente la valeur de transparence du pixel. Les images GIF n’autorisent la transparence que sur la base d’un bit, ce qui ne permet de spécifier la transparence que pour une seule couleur (dans une palette de 256 couleurs). Par contre, les images PNG acceptent jusqu’à 256 niveaux de transparence. Cette caractéristique est particulièrement intéressante pour « fondre » les images ou le texte avec l’arrière-plan. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 253 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 ActionScript 3.0 permet de gérer cet octet supplémentaire de transparence à l’aide de la classe BitmapData. Comme le modèle de transparence PNG, ActionScript propose jusqu’à 256 niveaux de transparence. Concepts importants et terminologie La liste suivante contient des termes importants relatifs aux graphiques bitmap : Alpha Niveau de transparence (ou, plus précisément, d’opacité) d’une couleur ou d’une image. La valeur alpha est fréquemment appelée valeur du canal alpha. Couleur ARGB Modèle colorimétrique suivant lequel la couleur de chaque pixel est définie selon ses composants rouge, vert et bleu, ainsi que par sa transparence spécifiée comme valeur alpha. Canal de couleur En général, les couleurs sont représentées par le mélange des couleurs primaires, rouge, vert et bleu (pour les graphiques sur ordinateur). Chaque couleur primaire est considérée comme un canal de couleur. C’est le mélange des proportions de chaque canal de couleur qui détermine la couleur finale. Codage des couleurs Parfois appelée codage, cette caractéristique détermine la quantité de mémoire vive dévolue à chaque pixel, ce qui, indirectement, définit le nombre de couleurs qu’il est possible d’afficher dans l’image. Pixel Unité d’information de base d’une image bitmap (fondamentalement, un point coloré). Résolution Dimensions d’une image en pixels, qui détermine le niveau de détails fins d’une image. La résolution est fréquemment exprimée en nombre de pixels pour la largeur et la hauteur. Couleur RVB Modèle colorimétrique suivant lequel la couleur de chaque pixel est définie selon ses composants rouge, vert et bleu. Classes Bitmap et BitmapData Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les principales classes ActionScript 3.0 d’utilisation des images bitmap sont la classe Bitmap, qui permet d’afficher les images bitmap à l’écran, et la classe BitmapData, qui permet d’accéder et de manipuler les données brutes d’une image bitmap. Voir aussi flash.display.Bitmap flash.display.BitmapData Présentation de la classe Bitmap Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Sous-classe de la classe DisplayObject, la classe Bitmap est la principale classe utilisée en ActionScript 3.0 pour l’affichage d’images bitmap. Ces images sont souvent chargées par le biais de la classe flash.display.Loader ou créées dynamiquement à l’aide du constructeur Bitmap(). En cas de chargement d’une image provenant d’une source externe, un objet Bitmap ne peut contenir que des images aux formats GIF, JPEG ou PNG. L’occurrence de l’objet Bitmap peut être considérée comme enveloppe d’un objet BitmapData devant être affiché sur la scène. Une occurrence de Bitmap étant un objet d’affichage, toutes les caractéristiques et fonctionnalités des objets d’affichage peuvent être utilisées pour la manipuler. Pour plus d’informations sur l’utilisation des objets d’affichage, voir « Programmation de l’affichage » à la page 156. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 254 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Accrochage et lissage des pixels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Outre les fonctionnalités communes à tous les objets d’affichage, la classe Bitmap dispose de quelques fonctionnalités supplémentaires, propres aux images bitmap. La propriété pixelSnapping de la classe Bitmap détermine si un objet Bitmap accroche le pixel le plus proche. Cette propriété accepte l’une des trois constantes définies dans la classe PixelSnapping : ALWAYS, AUTO et NEVER. La syntaxe de l’accrochage aux pixels est la suivante : myBitmap.pixelSnapping = PixelSnapping.ALWAYS; Lorsque des images bitmap sont redimensionnées, il est fréquent qu’elles deviennent floues et distordues. Pour réduire cette distorsion, utilisez la propriété smoothing de la classe BitmapData. Lorsque cette propriété booléenne a la valeur true, elle adoucit les pixels par un effet d’anticrènelage appliqué aux images redimensionnées. Celles-ci ont alors un aspect plus clair, plus naturel. Présentation de la classe BitmapData Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe BitmapData, qui se trouve dans le package flash.display, peut être comparée à un cliché photographique des pixels d’une image bitmap, que celle-ci soit chargée ou créée dynamiquement. Ce cliché est représenté par une grille de données des pixels de l’objet. La classe BitmapData contient également une série de méthodes permettant de créer et modifier des données de pixels. Pour instancier un objet BitmapData, utilisez le code suivant : var myBitmap:BitmapData = new BitmapData(width:Number, height:Number, transparent:Boolean, fillColor:uinit); Les paramètres width et height déterminent la taille de l’image bitmap. Dans AIR 3 et Flash Player 11 et les versions ultérieures, les limites de taille pour un objet BitmapData ont été supprimées. La taille maximale d’une image bitmap dépend du système d’exploitation. Dans AIR 1.5 et Flash Player 10, la taille maximale d’un objet BitmapData est de 8 191 pixels en largeur ou en hauteur, et le nombre total de pixels ne peut pas excéder 16 777 215 pixels (ainsi, si la largeur d’un objet BitmapData est de 8 191 pixels, sa hauteur maximale doit être de 2 048 pixels). Dans Flash Player 9 et les versions antérieures, ainsi que dans AIR 1.1 et les versions antérieures, la limite est de 2 880 pixels de haut sur 2 880 pixels de large. Le paramètre transparent indique si l’image bitmap comporte un canal alpha (true) ou non (false). Le paramètre fillColor est une valeur colorimétrique sur 32 bits qui spécifie la couleur d’arrière-plan, ainsi que la valeur de la transparence (si cette dernière est true). L’exemple suivant crée un objet BitmapData dont l’arrière-plan orange est transparent à 50 % : var myBitmap:BitmapData = new BitmapData(150, 150, true, 0x80FF3300); Pour afficher un objet BitmapData nouvellement créé, affectez-le à une occurrence de Bitmap. Pour ce faire, vous pouvez soit transmettre l’objet BitmapData sous forme de paramètre du constructeur de l’objet Bitmap, ou l’affecter à la propriété bitmapData d’une occurrence de Bitmap existante. Vous devez également affecter cette occurrence de Bitmap à la liste d’affichage en appelant la méthode addChild() ou addChildAt() du conteneur d’objet d’affichage qui contiendra cette occurrence de Bitmap. Pour plus d’informations sur l’utilisation de la liste d’affichage, voir « Ajout d’objets d’affichage à la liste d’affichage » à la page 165. L’exemple suivant crée un objet BitmapData avec un remplissage rouge, et l’affiche dans une occurrence de Bitmap : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 255 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 var myBitmapDataObject:BitmapData = new BitmapData(150, 150, false, 0xFF0000); var myImage:Bitmap = new Bitmap(myBitmapDataObject); addChild(myImage); Manipulation des pixels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe BitmapData contient des méthodes qui permettent de modifier les valeurs des données de pixels. Manipulation individuelle de pixels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour modifier une image bitmap au niveau des pixels, il est d’abord nécessaire d’obtenir les valeurs colorimétriques des pixels de la zone à modifier. La méthode getPixel() permet d’obtenir ces valeurs de pixels. La méthode getPixel() renvoie les valeurs RVB des coordonnées (de pixels) x et y qui lui sont passées en paramètres. Si l’un des pixels comporte des informations de transparence (canal alpha), il est nécessaire d’utiliser la méthode getPixel32(). Cette méthode récupère également une valeur RVB, mais contrairement à ce qui se passe avec getPixel(), la valeur renvoyée par getPixel32() contient des données supplémentaires qui représentent la valeur du canal alpha (transparence) du pixel sélectionné. Pour simplement modifier la couleur ou la transparence d’un pixel contenu dans un bitmap, il est aussi possible d’utiliser la méthode setPixel() ou setPixel32(). Pour définir la couleur d’un pixel, il suffit de passer les coordonnées x et y et la valeur colorimétrique à l’une de ces méthodes. Dans l’exemple suivant, setPixel() est utilisée pour tracer une croix sur un fond vert BitmapData. La méthode getPixel() permet ensuite de récupérer la valeur colorimétrique du pixel ayant les coordonnées 50, 50 et de suivre la valeur renvoyée. import flash.display.Bitmap; import flash.display.BitmapData; var myBitmapData:BitmapData = new BitmapData(100, 100, false, 0x009900); for (var i:uint = 0; i < 100; i++) { var red:uint = 0xFF0000; myBitmapData.setPixel(50, i, red); myBitmapData.setPixel(i, 50, red); } var myBitmapImage:Bitmap = new Bitmap(myBitmapData); addChild(myBitmapImage); var pixelValue:uint = myBitmapData.getPixel(50, 50); trace(pixelValue.toString(16)); Pour lire la valeur d’un groupe de pixels, et non pas d’un pixel isolé, utilisez la méthode getPixels(). Cette méthode génère un tableau d’octets à partir d’une zone rectangulaire de données de pixels, et le passe en paramètre. Chaque élément du tableau d’octets (autrement dit, les valeurs des pixels) est un entier non signé (valeurs non multipliées sur 32 bits). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 256 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Inversement, pour modifier (ou définir) la valeur d’un groupe de pixels, utilisez la méthode setPixels(). Cette méthode attend deux paramètres (rect et inputByteArray), qui sont combinés pour produire une zone rectangulaire (rect) de données de pixels (inputByteArray). Au fur et à mesure de la lecture (ou de l’écriture) des données dans inputByteArray, la méthode ByteArray.readUnsignedInt() est appelée pour chaque pixel du tableau. Si pour une raison quelconque inputByteArray ne contient pas un rectangle complet de données de pixels, la méthode interrompt le traitement des données de l’image. Il est important de comprendre que pour lire ou modifier des données de pixels, le tableau d’octets attend les valeurs suivantes sur 32 octets : alpha, rouge, vert, bleu (ARVB). L’exemple suivant utilise les méthodes getPixels() et setPixels() pour copier un groupe de pixels d’un objet BitmapData à un autre : import flash.display.Bitmap; import flash.display.BitmapData; import flash.utils.ByteArray; import flash.geom.Rectangle; var bitmapDataObject1:BitmapData = new BitmapData(100, 100, false, 0x006666FF); var bitmapDataObject2:BitmapData = new BitmapData(100, 100, false, 0x00FF0000); var rect:Rectangle = new Rectangle(0, 0, 100, 100); var bytes:ByteArray = bitmapDataObject1.getPixels(rect); bytes.position = 0; bitmapDataObject2.setPixels(rect, bytes); var bitmapImage1:Bitmap = new Bitmap(bitmapDataObject1); addChild(bitmapImage1); var bitmapImage2:Bitmap = new Bitmap(bitmapDataObject2); addChild(bitmapImage2); bitmapImage2.x = 110; Détection de collision au niveau des pixels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode BitmapData.hitTest() effectue une détection de collision au niveau des pixels entre les données bitmap et celles d’un autre objet ou d’un point. La méthode BitmapData.hitTest() accepte cinq paramètres : • firstPoint (Point) : ce paramètre référence la position du coin supérieur gauche du premier objet BitmapData sur lequel le test de collision doit être effectué. • firstAlphaThreshold (uint) : ce paramètre spécifie la valeur la plus élevée du canal alpha considéré comme étant opaque pour ce test de collision. • secondObject (Object) : ce paramètre représente la zone d’impact. L’objet secondObject peut être un objet de type Rectangle, Point, Bitmap ou BitmapData. Cet objet représente la zone dans laquelle doit être effectuée la détection de collision. • secondBitmapDataPoint (Point) : ce paramètre facultatif définit l’emplacement d’un pixel dans le deuxième objet BitmapData. Utilisez uniquement ce paramètre lorsque la valeur de secondObject est un objet BitmapData. La valeur par défaut est null. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 257 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 • secondAlphaThreshold (uint) : ce paramètre facultatif représente la valeur la plus élevée de canal alpha considérée comme étant opaque dans le deuxième objet BitmapData. La valeur par défaut est 1. Utilisez uniquement ce paramètre lorsque la valeur de secondObject est un objet BitmapData et que les deux objets BitmapData sont transparents. Lors d’une détection de collision sur des images opaques, n’oubliez pas qu’ActionScript traite l’image comme si c’était un rectangle entièrement opaque (ou un cadre de sélection). Par ailleurs, lors de tests de collision au niveau des pixels pour des images qui sont transparentes, les deux images doivent être transparentes. De plus, ActionScript utilise les paramètres de seuil alpha pour déterminer le point auquel les pixels passent de transparents à opaques. L’exemple suivant crée trois images bitmap et teste une éventuelle collision de pixels en deux différents points (l’un renvoie false, l’autre true) : import flash.display.Bitmap; import flash.display.BitmapData; import flash.geom.Point; var bmd1:BitmapData = new BitmapData(100, 100, false, 0x000000FF); var bmd2:BitmapData = new BitmapData(20, 20, false, 0x00FF3300); var bm1:Bitmap = new Bitmap(bmd1); this.addChild(bm1); // Create a red square. var redSquare1:Bitmap = new Bitmap(bmd2); this.addChild(redSquare1); redSquare1.x = 0; // Create a second red square. var redSquare2:Bitmap = new Bitmap(bmd2); this.addChild(redSquare2); redSquare2.x = 150; redSquare2.y = 150; // Define the point at the top-left corner of the bitmap. var pt1:Point = new Point(0, 0); // Define the point at the center of redSquare1. var pt2:Point = new Point(20, 20); // Define the point at the center of redSquare2. var pt3:Point = new Point(160, 160); trace(bmd1.hitTest(pt1, 0xFF, pt2)); // true trace(bmd1.hitTest(pt1, 0xFF, pt3)); // false Copie de données bitmap Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous disposez de plusieurs méthodes pour copier les données bitmap d’une image à une autre : clone(), copyPixels(), copyChannel(), draw() et drawWithQuality()(la méthode drawWithQuality est disponible dans Flash Player 11.3 et les versions ultérieures et dans AIR 3.3 et les versions ultérieures). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 258 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Comme son nom l’indique, la méthode clone() permet de cloner, ou échantillonner, des données bitmap d’un objet BitmapData à un autre. Cette méthode renvoie un nouvel objet BitmapData qui est un clone exact de l’occurrence originale. L’exemple suivant clone une copie d’un carré orange (parent) et place le clone à côté du carré parent original : import flash.display.Bitmap; import flash.display.BitmapData; var myParentSquareBitmap:BitmapData = new BitmapData(100, 100, false, 0x00ff3300); var myClonedChild:BitmapData = myParentSquareBitmap.clone(); var myParentSquareContainer:Bitmap = new Bitmap(myParentSquareBitmap); this.addChild(myParentSquareContainer); var myClonedChildContainer:Bitmap = new Bitmap(myClonedChild); this.addChild(myClonedChildContainer); myClonedChildContainer.x = 110; La méthode copyPixels() permet de copier rapidement et aisément des pixels d’un objet BitmapData dans un autre. Cette méthode prend un « cliché » rectangulaire (défini par le paramètre sourceRect) de l’image source et le copie dans une autre zone rectangulaire de taille égale. L’emplacement du rectangle ainsi « collé » est défini par le paramètre destPoint. La méthode copyChannel() analyse une valeur de canal de couleur prédéfini (alpha, rouge, vert ou bleu) dans un objet source BitmapData et la copie dans un canal donné de l’objet BitmapData de destination. Cette méthode n’affecte pas les autres canaux de l’objet BitmapData de destination. Les méthodes draw() et drawWithQuality() dessinent ou affichent le contenu graphique d’un objet d’affichage source (Sprite, Clip, etc.) dans un nouveau bitmap. Les paramètres matrix, colorTransform, blendMode et clipRect permettent de modifier l’aspect du nouveau bitmap. Cette méthode utilise le programme de rendu vectoriel de Flash Player et AIR pour générer les données. Pour appeler la méthode draw() ou drawWithQuality(), vous devez lui transmettre l’objet source (Sprite, Clip ou tout autre objet d’affichage) comme premier paramètre, comme ci-dessous : myBitmap.draw(movieClip); Si des transformations (couleur, matrice, etc.) ont été appliquées à l’objet source après son chargement, ces transformations ne sont pas copiées dans le nouvel objet. Pour copier les transformations dans le nouveau bitmap, vous devez copier la valeur de la propriété transform de l’objet original dans la propriété transform de l’objet Bitmap qui utilise le nouvel objet BitmapData. Compression des données d’une image bitmap Flash Player 11.3 et les versions ultérieures, AIR 3.3 et les versions ultérieures La méthode flash.display.BitmapData.encode() permet de compresser de façon native les données d’une image bitmap dans l’un des formats de compression d’image suivants : • PNG : utilise la compression PNG, en ayant éventuellement recours à une compression rapide pour augmente la vitesse de compression selon la taille du fichier. Pour utiliser la compression PNG, transmettez un nouvel objet flash.display.PNGEncoderOptions comme second paramètre de la méthode BitmapData.encode(). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 259 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 • JPEG : utilise la compression JPEG, en spécifiant éventuellement la qualité de l’image. Pour utiliser la compression JPEG, transmettez un nouvel objet flash.display.JPEGEncoderOptions comme second paramètre de la méthode BitmapData.encode(). • JPEGXR : utilise la compression JPEG Extended Range (XR), en spécifiant éventuellement les paramètres Canal de couleur, Avec perte et Entropie. Pour utiliser la compression JPEGXR, transmettez un nouvel objet flash.display.JPEGXREncoderOptions comme second paramètre de la méthode BitmapData.encode(). Vous pouvez utiliser cette fonction pour le traitement des images dans le cadre d’un flux de chargement ou de téléchargement sur le serveur. L’exemple de fragment de code suivant compresse l’objet BitmapData avec JPEGEncoderOptions : // Compress a BitmapData object as a JPEG file. var bitmapData:BitmapData = new BitmapData(640,480,false,0x00FF00); var byteArray:ByteArray = new ByteArray(); bitmapData.encode(new Rectangle(0,0,640,480), new flash.display.JPEGEncoderOptions(), byteArray); Création de textures avec les fonctions de bruit aléatoire Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour modifier l’aspect d’un bitmap, vous pouvez lui appliquer un effet de bruit à l’aide de la méthode noise() ou de la méthode perlinNoise(). La « neige » qui apparaît sur l’écran d’un téléviseur mal réglé est du bruit, ou du souffle. Pour appliquer un effet de bruit à un bitmap, utilisez la méthode noise(). Cette méthode applique une valeur colorimétrique aléatoire aux pixels de la zone spécifiée d’une image bitmap. Cette méthode accepte cinq paramètres : • randomSeed (int) : valeur aléatoire de départ qui déterminera le motif. En dépit du nom de ce paramètre, une même valeur pour ce nombre produira toujours le même résultat. Pour obtenir un résultat véritablement aléatoire, utilisez la méthode Math.random() pour transmettre un nombre aléatoire pour ce paramètre. • low (uint) : ce paramètre représente la valeur la plus faible à générer pour chaque pixel (de 0 à 255). Sa valeur par défaut est 0. Les valeurs les plus basses produisent un motif de bruit sombre, les valeurs les plus élevées produisent un motif de plus en plus clair. • high (uint) : ce paramètre représente la valeur la plus élevée à générer pour chaque pixel (de 0 à 255). La valeur par défaut est 255. Les valeurs les plus basses produisent un motif de bruit sombre, les valeurs les plus élevées produisent un motif de plus en plus clair. • channelOptions (uint) : ce paramètre indique le canal de couleur de l’objet bitmap auquel le motif de bruit sera appliqué. Ce nombre peut être une combinaison quelconque des quatre valeurs des canaux de couleur (ARVB). La valeur par défaut est 7. • grayScale (Boolean) : lorsque ce paramètre est activé (true), la valeur de randomSeed est appliquée aux pixels du bitmap, ce qui donne concrètement un effet de délavé sur toutes les couleurs de l’image. Le canal alpha n’est pas affecté par ce paramètre. La valeur par défaut est false. L’exemple suivant crée une image bitmap et lui applique un motif de bruit bleu : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 260 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; public class BitmapNoise1 extends Sprite { public function BitmapNoise1() { var myBitmap:BitmapData = new BitmapData(250, 250,false, 0xff000000); myBitmap.noise(500, 0, 255, BitmapDataChannel.BLUE,false); var image:Bitmap = new Bitmap(myBitmap); addChild(image); } } } Si vous souhaitez créer une texture d’aspect plus organique, utilisez la méthode perlinNoise(). La méthode perlinNoise() produit des textures organiques plus réalistes, qui sont idéales pour des effets de fumée, de nuage, d’eau, de flamme ou même d’explosion. Comme la méthode perlinNoise() fait appel à un algorithme, elle nécessite moins de mémoire vive que les textures à base de bitmaps. Elle peut malgré tout consommer beaucoup de ressources processeur, ce qui risque de ralentir le contenu et de provoquer des actualisations d’écran plus lentes que la cadence nominale, en particulier sur les ordinateurs plus anciens. En effet, les algorithmes de cette méthode effectuent des calculs en virgule flottante. Cette méthode accepte neuf paramètres (les six premiers sont obligatoires) : • baseX (Number) : détermine la valeur x (taille) des motifs créés. • baseY (Number) : détermine la valeur y (taille) des motifs créés. • numOctaves: (uint) : nombre d’octaves ou fonctions de bruit individuelles à combiner pour créer ce bruit. Les nombres d’octaves élevés offrent davantage de détails mais nécessitent également un temps de traitement plus important. • randomSeed (int) : la valeur aléatoire de départ fonctionne exactement comme dans la fonction noise(). Pour obtenir un résultat véritablement aléatoire, utilisez la méthode Math.random() pour transmettre un nombre aléatoire pour ce paramètre. • stitch (Boolean) : si la valeur est true, cette méthode tente de lisser les bords de transition de l’image pour créer des textures sans bords définis, en vue d’une utilisation en mosaïque. • fractalNoise (Boolean) : ce paramètre concerne les bords des dégradés générés par cette méthode. S’il a la valeur true, la méthode génère un bruit fractal qui adoucit le pourtour. S’il a la valeur false, la méthode génère des turbulences. Les dégradés d’une image créée avec des turbulences présentent des discontinuités visibles qui permettent de mieux restituer certains effets visuels comme les flammes ou les vagues. • channelOptions (uint) : le paramètre channelOptions fonctionne exactement comme dans la méthode noise(). Il indique le canal de couleur de l’objet bitmap auquel le motif de bruit sera appliqué. Ce nombre peut être une combinaison quelconque des quatre valeurs des canaux de couleur (ARVB). La valeur par défaut est 7. • grayScale (Boolean) : le paramètre grayScale fonctionne exactement comme dans la méthode noise(). Si ce paramètre est activé (true), la valeur de randomSeed est appliquée aux pixels du bitmap, ce qui donne concrètement un effet de délavé sur toutes les couleurs de l’image. La valeur par défaut est false. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 261 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 • offsets: (Array) : un tableau de points correspondant aux décalages x et y pour chaque octave. En modifiant les valeurs de décalage, vous pouvez faire défiler en continu les calques d’une image. Chaque point du tableau de décalage affecte une fonction de bruit pour une octave spécifique. La valeur par défaut est null. L’exemple suivant crée un objet BitmapData de 150 x 150 pixels qui appelle la méthode perlinNoise() pour générer un effet de nuage vert et bleu : package { import flash.display.Sprite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; public class BitmapNoise2 extends Sprite { public function BitmapNoise2() { var myBitmapDataObject:BitmapData = new BitmapData(150, 150, false, 0x00FF0000); var seed:Number = Math.floor(Math.random() * 100); var channels:uint = BitmapDataChannel.GREEN | BitmapDataChannel.BLUE myBitmapDataObject.perlinNoise(100, 80, 6, seed, false, true, channels, false, null); var myBitmap:Bitmap = new Bitmap(myBitmapDataObject); addChild(myBitmap); } } } Défilement du contenu d’images bitmap Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Supposons que vous avez créé une application cartographique. Chaque fois que l’utilisateur déplace la carte, vous devez actualiser l’affichage (même si le plan n’a été déplacé que de quelques pixels). Pour obtenir cette fonctionnalité, il est possible de réafficher une nouvelle image contenant le plan actualisé à chaque déplacement. Il est également possible de créer une grande image globale et d’utiliser la méthode scroll(). La méthode scroll() copie une image bitmap affichée et la colle à un nouvel emplacement, spécifié par les paramètres (x, y). S’il se trouve qu’une partie de l’image est située hors écran, l’effet obtenu est celui d’un défilement de l’image. Si cette fonction est combinée avec un timer (ou un événement enterFrame), l’image semble animée. L’exemple suivant reprend l’exemple précédent et génère une image bitmap de grande taille (dont les trois-quarts sont restitués hors scène). La méthode scroll() est alors appliquée. Grâce à un écouteur pour l’événement enterFrame, l’image est décalée d’un pixel en diagonale vers le bas. Cette méthode est appelée pour chaque nouvelle image. Les parties de l’image non affichées initialement apparaissent alors peu à peu sur la scène grâce à ce défilement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 262 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 import flash.display.Bitmap; import flash.display.BitmapData; var myBitmapDataObject:BitmapData = new BitmapData(1000, 1000, false, 0x00FF0000); var seed:Number = Math.floor(Math.random() * 100); var channels:uint = BitmapDataChannel.GREEN | BitmapDataChannel.BLUE; myBitmapDataObject.perlinNoise(100, 80, 6, seed, false, true, channels, false, null); var myBitmap:Bitmap = new Bitmap(myBitmapDataObject); myBitmap.x = -750; myBitmap.y = -750; addChild(myBitmap); addEventListener(Event.ENTER_FRAME, scrollBitmap); function scrollBitmap(event:Event):void { myBitmapDataObject.scroll(1, 1); } Utilisation du mipmapping Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les mipmaps sont des images bitmap qui sont regroupées et associées à une texture dans le but d’améliorer la qualité et les performances d’affichage à l’exécution. Chaque image bitmap dans le mipmap est une version de l’image bitmap principale, mais à un niveau de détails réduit. Par exemple, vous pouvez disposer d’un mipmap qui inclut une image principale à une qualité optimale de 64 × 64 pixels. Les images de qualité inférieure dans le mipmap seront de 32 × 32, 16 × 16, 8 × 8, 4 × 4, 2 × 2 et de 1 × 1 pixels. La diffusion en continu de texture fait référence à la capacité de charger tout d’abord les images bitmap de qualité inférieure, puis d’afficher progressivement les images bitmap de qualité supérieure au fur et à mesure de leur chargement. Etant donné que les bitmaps de qualité inférieure sont de petites images, elles se chargent plus rapidement que l’image principale. Par conséquent, les utilisateurs de l’application peuvent afficher l’image dans une application avant le chargement de l’image bitmap principale de qualité supérieure. Flash Player 9.115.0 (et les versions ultérieures) et AIR implémentent cette technique (dite de mip-mapping), en créant des versions optimisées à diverses échelles de chaque bitmap (en partant de 50 %). Flash Player 11.3 et AIR 3.3 prennent en charge la diffusion en continu de textures via le paramètre streamingLevels des méthodes Context3D.createCubeTexture() et Context3D.createTexture(). La compression de texture permet d'enregistrer des images de texture au format compressé directement sur le GPU en vue d'économiser la mémoire GPU et la bande passante. En règle générale, les textures sont compressées hors ligne et téléchargées sur le GPU au format compressé. Néanmoins, Flash Player 11.4 et AIR 3.4 prennent en charge la compression de texture à l'exécution, utile dans certaines situations, notamment lors du rendu des textures dynamiques d'une illustration vectorielle. Pour utiliser la compression de texture à l'exécution, procédez comme suit : • Créez l'objet de texture en appelant la méthode Context3D.createTexture(), et en transmettant flash.display3D.Context3DTextureFormat.COMPRESSED ou flash.display3D.Context3DTextureFormat.COMPRESSED_ALPHA dans le troisième paramètre. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 263 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 • A l'aide de l'occurrence flash.display3D.textures.Texture renvoyée par createTexture(), appelez la méthode flash.display3D.textures.Texture.uploadFromBitmapData() ou flash.display3D.textures.Texture.uploadFromByteArray(). Ces méthodes permettent de télécharger et de compresser simultanément la texture. Les mipmaps sont créées pour les types de bitmap suivants : • Une image bitmap (fichiers JPEG, GIF ou PNG) affichée par le biais de la classe Loader d’ActionScript 3.0. • Une image bitmap dans la bibliothèque d’un document Flash Professional. • Un objet BitmapData. • Une image bitmap affichée à l’aide de la fonction loadMovie() d’ActionScript 2.0. Les mipmaps ne sont pas appliqués aux objets filtrés ni aux clips dont les bitmaps sont en cache. En revanche, ils sont appliqués si un objet d’affichage filtré contient des transformations de bitmap, même si le bitmap se trouve dans un contenu masqué. Le mipmapping est exécuté automatiquement, mais les quelques conseils suivants vous permettront d’être certain que vos images bénéficient de cette optimisation : • Pour la lecture vidéo, définissez la propriété smoothing sur true pour l’objet Video (voir la classe Video). • Pour les bitmaps, il n’est pas nécessaire de définir la propriété smoothing sur true, mais l’activation de cette propriété assure une amélioration visible de la qualité. • Utilisez des tailles de bitmap divisibles par 4 ou 8 pour les images bidimensionnelles (affichage 640 x 128, qui peut être réduit comme suit : 320 x 64 > 160 x 32 > 80 x 16 > 40 x 8 > 20 x 4 > 10 x 2 > 5 x 1). Pour les textures tridimensionnelles, utilisez des mipmaps dans lesquels la résolution de chaque image est une puissance de 2 (2^n). Par exemple, la résolution de l’image principale est de 1 024 x 1 024 pixels. Les images de qualité inférieure dans le mipmap seront à 512 x 512, 256 x 256, 128 x 128 jusqu’à 1 x 1 pixels pour un total de 11 images dans le mipmap. Notez que le mip-mapping ne gère pas un contenu de bitmap dont la largeur ou la hauteur est impaire. Exemple d’objet Bitmap : lune en rotation animée Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple de lune en rotation animée illustre les techniques d’utilisation des objets Bitmap et des données d’image bitmap (objets BitmapData). L’exemple crée une animation d’une lune sphérique en rotation et utilise comme données d’image brutes une image plane de la surface de la lune. Les techniques suivantes sont illustrées : • Chargement d’une image externe et accès aux données d’image brutes correspondantes • Création d’une animation par copie répétée des pixels de différentes parties d’une image source • Création d’une image bitmap par définition de la valeur des pixels Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application de la lune en rotation animée résident dans le dossier Samples/SpinningMoon. L’application se compose des fichiers suivants : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 264 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Chargement d’une image externe comme données bitmap Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La première tâche à exécuter dans cet exemple consiste à charger une image externe, une photographie de la surface de la lune. Le chargement est géré par deux méthodes de la classe MoonSphere : le constructeur MoonSphere(), qui lance le processus de chargement, et la méthode imageLoadComplete(), qui est appelée au terme du chargement de l’image externe. Le chargement d’une image externe est similaire à celui d’un fichier SWF externe : il est réalisé par une occurrence de la classe flash.display.Loader. Le code ci-après de la méthode MoonSphere() commence à charger l’image : var imageLoader:Loader = new Loader(); imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadComplete); imageLoader.load(new URLRequest("moonMap.png")); La première ligne déclare l’occurrence de Loader appelée imageLoader. La troisième ligne commence le processus de chargement à proprement parler en appelant la méthode load() de l’objet Loader. Cette méthode transmet une occurrence URLRequest représentant l’URL de l’image à charger. La deuxième ligne définit l’écouteur d’événement qui se déclenchera à l’issue du chargement de l’image. Observez que la méthode addEventListener() n’est pas appelée sur l’occurrence de Loader elle-même, mais sur la propriété contentLoaderInfo de l’objet Loader. L’occurrence de Loader n’envoie pas d’événements en rapport avec le contenu chargé. En revanche, sa propriété contentLoaderInfo contient une référence à l’objet LoaderInfo qui est associé au contenu chargé dans l’objet Loader (en l’occurrence, l’image externe). L’objet LoaderInfo génère des événements en rapport avec le déroulement et la fin du chargement du contenu externe, notamment l’événement complete (Event.COMPLETE) qui déclenche un appel à la méthode imageLoadComplete() au terme du chargement de l’image. S’il est essentiel de lancer le chargement de l’image externe, il est tout aussi important de savoir comment procéder au terme de cette opération. Comme l’illustre le code ci-dessus, la fonction imageLoadComplete() est appelée une fois l’image chargée. Cette fonction exécute diverses opérations sur les données chargées, comme indiqué ultérieurement. Cependant, pour utiliser les données d’image, elle doit pouvoir y accéder. Une image externe chargée par le biais d’un objet Loader devient une image Bitmap jointe en tant qu’objet d’affichage enfant de l’objet Loader. Dans ce cas, la méthode écouteur d’événement a accès à l’occurrence de Loader dans l’objet événement transmis en tant que paramètre à la méthode. Les premières lignes de la méthode imageLoadComplete() sont les suivantes : private function imageLoadComplete(event:Event):void { textureMap = event.target.content.bitmapData; ... } Fichier Description SpinningMoon.mxml ou SpinningMoon.fla Le fichier d’application principal dans Flex (MXML) ou Flash (FLA). com/example/programmingas3/moon/MoonSphere.as Classe exécutant le chargement, l’affichage et l’animation de la lune. moonMap.png Fichier image contenant une photographie de la surface de la lune, chargé et utilisé pour créer la lune en rotation animée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 265 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Notez que le paramètre de l’objet événement s’appelle event et que c’est une occurrence de la classe Event. Chaque occurrence de la classe Event possède une propriété target, qui fait référence à l’objet déclenchant l’événement (en l’occurrence, l’occurrence de LoaderInfo sur laquelle la méthode addEventListener() a été appelée, comme indiqué plus haut). De même, l’objet LoaderInfo possède une propriété content qui, à l’issue du chargement, contient une occurrence de Bitmap comportant l’image bitmap chargée. Pour afficher l’image directement à l’écran, vous pouvez joindre cette occurrence de Bitmap (event.target.content) à un conteneur d’objet d’affichage (vous pouvez aussi joindre l’objet Loader à un conteneur d’objet d’affichage). Toutefois, dans cet exemple, le contenu chargé n’est pas affiché à l’écran, il est utilisé en tant que données d’image brutes. Par conséquent, la première ligne de la méthode imageLoadComplete() lit la propriété bitmapData de l’occurrence de Bitmap chargée (event.target.content.bitmapData) et la stocke dans la variable d’occurrence de textureMap, qui est utilisée en tant que source des données d’image pour créer l’animation de la lune en rotation. Ce processus est décrit ci-après. Création d’une animation par copie de pixels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Une animation, dans sa définition la plus simple, est l’illusion d’un mouvement ou d’un changement, créée par la modification graduelle d’une image. Cet exemple a pour but de créer l’illusion d’une lune sphérique tournant sur son axe vertical. Cependant, pour les besoins de l’animation, vous pouvez ne pas tenir compte de l’aspect de distorsion sphérique de l’exemple. Examinez l’image chargée et utilisée comme source des données d’image de la lune : Comme vous pouvez le constater, l’image ne représente pas une ou plusieurs sphères ; c’est une photographie rectangulaire de la surface de la lune. La photographie ayant été prise à l’emplacement exact de l’équateur de la lune, les parties supérieures et inférieures de l’image sont donc étirées et déformées. Pour supprimer la distorsion de l’image et lui redonner son aspect sphérique, nous utiliserons un filtre Mappage de déplacement (voir plus bas). Toutefois, l’image source étant un rectangle, il suffit que le code fasse glisser horizontalement la photographie de la surface de la lune pour créer l’illusion d’une sphère en rotation. Observez que l’image contient en fait deux copies juxtaposées de la photographie de la surface de la lune. Cette image représente l’image source dans laquelle des données ont été copiées plusieurs fois pour créer un effet de mouvement. La juxtaposition de deux copies de l’image facilite la création d’un effet de défilement continu. Examinons en détail le processus d’animation afin de mieux le comprendre. Le processus s’applique à deux objets ActionScript distincts. Le premier de ces objets est l’image source chargée qui, dans le code, est représentée par l’occurrence de BitmapData textureMap Comme nous l’avons vu, les données d’image sont insérées dans textureMap dès le chargement de l’image externe à l’aide de ce code : textureMap = event.target.content.bitmapData; Le contenu de textureMap correspond à l’image de la lune rectangulaire. En outre, pour créer la rotation animée, le code utilise l’occurrence de Bitmap sphere, qui représente l’objet d’affichage qui affiche l’image de la lune à l’écran. A l’instar de textureMap, l’objet sphere contient les données d’image initiales de la méthode imageLoadComplete(), ainsi que le stipule le code suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 266 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 sphere = new Bitmap(); sphere.bitmapData = new BitmapData(textureMap.width / 2, textureMap.height); sphere.bitmapData.copyPixels(textureMap, new Rectangle(0, 0, sphere.width, sphere.height), new Point(0, 0)); Comme vous pouvez le constater, sphere est instancié. La hauteur et la largeur de sa propriété bitmapData (les données d’image brutes qui sont affichées par sphere) sont identiques à celles de textureMap. Autrement dit, le contenu de sphere a la même taille qu’une seule photographie de la lune (puisque l’image textureMap contient deux photographies juxtaposées). Des données d’image sont ensuite insérées dans la propriété bitmapData à l’aide de sa méthode copyPixels(). Les paramètres de l’appel de la méthode copyPixels() donnent plusieurs indications : • Le premier paramètre indique que les données d’image copiées proviennent de textureMap. • Le deuxième paramètre, une nouvelle occurrence de Rectangle, détermine quelle partie de textureMap est copiée. En l’occurrence, le cliché est un rectangle dont l’origine coïncide avec le coin supérieur gauche de textureMap (ce qu’indiquent les deux premiers paramètres de Rectangle() : 0, 0) et dont la largeur et la hauteur correspondent aux propriétés width et height de sphere. • Le troisième paramètre, une nouvelle occurrence de Point avec des valeurs de x et y égales à 0, définit la destination des données de pixel ; en l’occurrence, le coin supérieur gauche (0, 0) de sphere.bitmapData. Représenté visuellement, le code copie les pixels de textureMap mis en évidence ci-dessous et les colle sur sphere. Autrement dit le contenu BitmapData de sphere correspond à la partie de textureMap mise en évidence : Pour rappel, il s’agit seulement de l’état initial de sphere, le contenu de la première image copiée sur sphere. Une fois l’image source chargée et sphere créé, il ne reste plus à la méthode imageLoadComplete() qu’à définir l’animation. L’animation est pilotée par une occurrence de Timer, rotationTimer, créée et lancée par le code suivant : var rotationTimer:Timer = new Timer(15); rotationTimer.addEventListener(TimerEvent.TIMER, rotateMoon); rotationTimer.start(); Le code commence par créer l’occurrence de Timer rotationTimer. Le paramètre passé au constructeur Timer() indique que rotationTimer doit déclencher son événement timer toutes les 15 millisecondes. La méthode addEventListener() qui est appelée ensuite stipule que le déclenchement de l’événement timer (TimerEvent.TIMER) entraîne l’appel de la méthode rotateMoon(). Enfin, l’appel de la méthode start() du timer entraîne le démarrage de celui-ci. De par la définition de rotationTimer, Flash Player appelle la méthode rotateMoon() dans la classe MoonSphere environ toutes les 15 millisecondes, ce qui se traduit par l’animation de la lune. Le code source de la méthode rotateMoon() est le suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 267 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 private function rotateMoon(event:TimerEvent):void { sourceX += 1; if (sourceX > textureMap.width / 2) { sourceX = 0; } sphere.Data.copyPixels(textureMap, new Rectangle(sourceX, 0, sphere.width, sphere.height), new Point(0, 0)); event.updateAfterEvent(); } Ce code effectue trois opérations : 1 La valeur de la variable sourceX (initialement fixée à 0) est incrémentée d’une unité. sourceX += 1; sourceX permet de déterminer d’où proviennent, dans textureMap, les pixels copiés sur sphere. Ce code déplace donc le rectangle d’un pixel vers la droite sur textureMap. Comme le montre l’illustration suivante, après plusieurs cycles d’animation, le rectangle source s’est déplacé de plusieurs pixels vers la droite : Après plusieurs autres cycles, le rectangle se trouve encore plus à droite. C’est sur ce déplacement progressif constant de l’emplacement d’origine des pixels copiés que repose l’animation. Par un déplacement lent mais continu de l’emplacement source vers la droite, l’image affichée à l’écran dans sphere semble continuellement glisser vers la gauche. C’est pourquoi l’image source (textureMap) doit contenir deux copies de la photographie de la surface de la lune. Comme le rectangle se déplace continuellement vers la droite, il chevauche généralement les deux photographies et non pas seulement l’une d’elles. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 268 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 2 Ce lent déplacement vers la droite donne cependant lieu à un problème. Le rectangle finira par atteindre le bord droit de textureMap et ne trouvera plus de pixels à copier sur sphere : Les lignes suivantes du code permettent de résoudre ce problème : if (sourceX >= textureMap.width / 2) { sourceX = 0; } Le code vérifie si sourceX (le bord gauche du rectangle) a atteint le milieu de textureMap. Si tel est le cas, il remet la variable sourceX à 0 ; autrement dit, il la ramène au bord gauche de textureMap, et le cycle recommence : 3 Une fois la valeur de sourceX appropriée calculée, la dernière étape du processus d’animation consiste à copier les pixels du nouveau rectangle source sur sphere. Pour ce faire, nous reprenons le code qui a initialement rempli sphere (voir plus haut), à la différence près que, dans l’appel du constructeur new Rectangle(), le bord gauche du rectangle est placé à sourceX : sphere.bitmapData.copyPixels(textureMap, new Rectangle(sourceX, 0, sphere.width, sphere.height), new Point(0, 0)); Pour rappel, ce code est appelé toutes les 15 millisecondes. Comment l’emplacement du rectangle source change constamment et que les pixels sont copiés sur sphere, à l’écran, la photographie de la lune représentée par sphere semble glisser continuellement. En d’autres termes, la lune semble tourner sur elle-même continuellement. Définition de l’aspect sphérique Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La lune est bien entendu sphérique , ce n’est pas un rectangle. La photographie rectangulaire de la surface lunaire, qui fait l’objet d’une animation constante, doit donc être convertie en sphère. Cette opération comprend deux étapes : un masque cache tout le contenu excepté une partie circulaire de la photographie et un filtre Mappage de déplacement déforme l’apparence de la photographie, lui donnant un aspect tridimensionnel. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 269 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Dans un premier temps, un masque circulaire cache entièrement le contenu de l’objet MoonSphere excepté la sphère créée par le filtre. Le code suivant crée le masque, une occurrence de Shape, et l’applique à l’occurrence de MoonSphere : moonMask = new Shape(); moonMask.graphics.beginFill(0); moonMask.graphics.drawCircle(0, 0, radius); this.addChild(moonMask); this.mask = moonMask; Comme MoonSphere est un objet d’affichage (fondé sur la classe Sprite), il est possible d’appliquer directement le masque à l’occurrence de MoonSphere à l’aide de sa propriété mask héritée. Il ne suffit pas d’occulter des parties de la photographie à l’aide d’un masque circulaire pour créer un effet réaliste de sphère en rotation. En raison de la façon dont la photographie de la surface lunaire a été prise, ses dimensions ne sont pas proportionnelles . les parties supérieures et inférieures de l’image sont déformées et étirées par rapport aux zones équatoriales. Pour déformer l’apparence de la photographie et lui donner un aspect tridimensionnel, nous allons utiliser un filtre Mappage de déplacement. Ce type de filtre permet de déformer une image. En l’occurrence, nous allons déformer la photographie de la lune pour lui donner un aspect plus réaliste, en compressant horizontalement les parties supérieures et inférieures de l’image sans toucher à son milieu. En supposant que le filtre intervienne sur une partie carrée de la photographie, la compression du haut et du bas mais pas du milieu aura pour effet de convertir le carré en cercle. L’animation de cette image déformée a un effet secondaire : la distance en pixels parcourue par le milieu de l’image semble supérieure à celle couverte par les parties supérieure et inférieure, d’où l’impression que le cercle est en fait un objet tridimensionnel (une sphère). Le code suivant permet de créer un filtre Mappage de déplacement appelé displaceFilter : var displaceFilter:DisplacementMapFilter; displaceFilter = new DisplacementMapFilter(fisheyeLens, new Point(radius, 0), BitmapDataChannel.RED, BitmapDataChannel.GREEN, radius, 0); Le premier paramètre, fisheyeLens, est l’image de mappage ; en l’occurrence, un objet BitmapData créé par programmation. La création de cette image est décrite dans « Création d’une image bitmap par définition de la valeur des pixels » à la page 270. Les autres paramètres décrivent l’emplacement d’application du filtre au sein de l’image filtrée, les canaux colorimétriques utilisés pour régir l’effet de déplacement et leur impact sur celui-ci. Une fois le filtre Mappage de déplacement créé, il est appliqué à sphere, toujours dans la méthode imageLoadComplete() : sphere.filters = [displaceFilter]; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 270 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 L’image finale, une fois le masque et le filtre appliqués, se présente comme suit : A chaque cycle du processus d’animation de la lune en rotation, le contenu BitmapData de sphere est remplacé par un nouveau cliché des données d’image source. Il est cependant inutile de réappliquer le filtre à chaque fois car il est appliqué à l’occurrence de Bitmap (l’objet d’affichage) plutôt qu’aux données bitmap (données de pixel brutes). Pour rappel, l’occurrence de Bitmap ne correspond pas aux données bitmap. C’est un objet d’affichage qui affiche ces données à l’écran. Une occurrence de Bitmap peut être assimilée à un projecteur de diapositives, tandis qu’un objet BitmapData serait une diapositive présentée par le biais du projecteur. Il est possible d’appliquer un filtre directement à un objet BitmapData, ce qui reviendrait à dessiner sur une diapositive pour modifier l’image. Vous pouvez aussi appliquer un filtre à tout objet d’affichage, y compris une occurrence de Bitmap, ce qui équivaudrait à placer un filtre devant l’objectif du projecteur pour déformer l’image à l’écran sans modifier la diapositive d’origine. Comme les données bitmap brutes sont accessibles par le biais de la propriété bitmapData d’une occurrence de Bitmap, rien n’empêche de leur appliquer directement le filtre. Dans ce cas, cependant, il est préférable d’appliquer directement le filtre à l’objet d’affichage Bitmap plutôt qu’aux données bitmap. Pour plus d’informations sur l’utilisation du filtre Mappage de déplacement en ActionScript, voir « Filtrage des objets d’affichage » à la page 276. Création d’une image bitmap par définition de la valeur des pixels Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le fait qu’un filtre Mappage de déplacement implique en réalité deux images est un facteur important. L’image source est modifiée par le filtre. Dans cet exemple, il s’agit de l’occurrence de Bitmap sphere. L’autre image utilisée par le filtre est appelée l’image de mappage. Elle n’apparaît pas à l’écran. En revanche, la couleur de ses pixels est utilisée en entrée par la fonction de déplacement : la couleur d’un pixel se trouvant à des coordonnées x, y spécifiques détermine le déplacement (changement physique de position) à appliquer au pixel à ces coordonnées x, y dans l’image source. Dans cet exemple, pour utiliser le filtre Mappage de déplacement en vue de créer un effet sphérique, il est donc nécessaire d’utiliser l’image de mappage appropriée, c’est-à-dire une image au fond gris comportant un cercle rempli d’un dégradé d’une seule couleur (rouge) qui passe, horizontalement, du foncé au clair, comme illustré ci-dessous : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 271 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Comme une image de mappage et un filtre uniques sont utilisés dans cet exemple, l’image de mappage est créée une seule fois, dans la méthode imageLoadComplete() (autrement dit, à l’issue du chargement de l’image externe). L’image de mappage, fisheyeLens, est créée par appel de la méthode createFisheyeMap() de la classe MoonSphere : var fisheyeLens:BitmapData = createFisheyeMap(radius); Au sein de la méthode createFisheyeMap(), l’image de mappage est dessinée pixel par pixel à l’aide de la méthode setPixel() de la classe BitmapData. Vous trouverez le code complet de la méthode createFisheyeMap() cidessous, suivi d’une présentation détaillée de son fonctionnement : private function createFisheyeMap(radius:int):BitmapData { var diameter:int = 2 * radius; var result:BitmapData = new BitmapData(diameter, diameter, false, 0x808080); // Loop through the pixels in the image one by one for (var i:int = 0; i < diameter; i++) { for (var j:int = 0; j < diameter; j++) { // Calculate the x and y distances of this pixel from // the center of the circle (as a percentage of the radius). var pctX:Number = (i - radius) / radius; var pctY:Number = (j - radius) / radius; // Calculate the linear distance of this pixel from // the center of the circle (as a percentage of the radius). var pctDistance:Number = Math.sqrt(pctX * pctX + pctY * pctY); // If the current pixel is inside the circle, // set its color. if (pctDistance < 1) { // Calculate the appropriate color depending on the // distance of this pixel from the center of the circle. var red:int; var green:int; var blue:int; var rgb:uint; red = 128 * (1 + 0.75 * pctX * pctX * pctX / (1 - pctY * pctY)); green = 0; blue = 0; rgb = (red << 16 | green << 8 | blue); // Set the pixel to the calculated color. result.setPixel(i, j, rgb); } } } return result; } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 272 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 En premier lieu, la méthode reçoit un paramètre, radius, qui indique le rayon de l’image circulaire à créer. Le code crée ensuite l’objet BitmapData sur lequel sera tracé le cercle. Cet objet, appelé result, est renvoyé comme valeur résultante de la méthode. Comme illustré par l’extrait de code ci-dessous, la largeur et la hauteur de l’occurrence de BitmapData result créée sont égales au diamètre du cercle. En outre, cette occurrence n’a pas de transparence (le troisième paramètre correspond à false) et elle est pré-remplie par la couleur 0x808080 (gris moyen) : var result:BitmapData = new BitmapData(diameter, diameter, false, 0x808080); Le code utilise ensuite deux boucles pour itérer par-dessus chaque pixel de l’image. La boucle extérieure parcourt de droite à gauche chaque colonne de l’image (la variable i représentant la position horizontale du pixel manipulé), alors que la boucle intérieure intervient sur chaque pixel de la colonne actuelle, de bas en haut (la variable j représentant la position verticale du pixel actuel). Le code des boucles (le contenu de la boucle intérieure étant omis) est illustré cidessous : for (var i:int = 0; i < diameter; i++) { for (var j:int = 0; j < diameter; j++) { ... } } Au fur et à mesure de la manipulation des pixels par les boucles, une valeur est calculée à chacun d’eux (la valeur colorimétrique de ce pixel dans l’image de mappage). Ce processus comporte quatre étapes : 1 Le code calcule la distance séparant le pixel actuel du centre du cercle, le long de l’axe x (i - radius). Cette valeur est divisée par le rayon pour obtenir un pourcentage de celui-ci plutôt qu’une distance absolue ((i - radius) / radius). Ce pourcentage est stocké dans une variable appelée pctX. La valeur équivalente sur l’axe y est calculée et stockée dans la variable pctY, comme illustré dans le code ci-dessous : var pctX:Number = (i - radius) / radius; var pctY:Number = (j - radius) / radius; 2 Une formule trigonométrique standard (le théorème de Pythagore) est utilisée pour calculer la distance linéaire entre le centre du cercle et le point actuel, à partir de pctX et pctY. Cette valeur est stockée dans une variable, pctDistance, comme illustré ci-dessous : var pctDistance:Number = Math.sqrt(pctX * pctX + pctY * pctY); 3 Le code vérifie ensuite si la distance en pourcentage est inférieure à 1 (ou 100 % du rayon ; autrement dit, si le pixel concerné se trouve sur le rayon du cercle). Si le pixel figure dans le cercle, une valeur colorimétrique calculée lui est affectée (voir la description à l’étape 4). Dans le cas contraire, ce pixel ne fait l’objet d’aucune manipulation et conserve la couleur par défaut, c’est-à-dire le gris moyen. if (pctDistance < 1) { ... } 4 Une valeur colorimétrique est calculée pour tout pixel se trouvant dans le cercle. La couleur finale est une nuance de rouge qui va du noir (0 % de rouge) sur le bord gauche du cercle au rouge vif (100 % de rouge) sur le bord droit du cercle. La valeur colorimétrique comprend initialement trois parts de couleur (rouge, vert et bleu), comme illustré ci-dessous) : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 273 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 red = 128 * (1 + 0.75 * pctX * pctX * pctX / (1 - pctY * pctY)); green = 0; blue = 0; Observez que seule la part rouge de la couleur (variable red) possède une valeur. Les valeurs vert et bleu (variables green et blue) sont illustrées ici par souci de clarté, mais il est possible de les omettre. Cette méthode ayant pour but de créer un cercle contenant un dégradé de rouge, les valeurs vertes et bleues sont superflues. Une fois les trois valeurs colorimétriques individuelles déterminées, elles sont conjuguées dans une valeur entière unique à l’aide d’un algorithme de décalage de bits, comme illustré ci-dessous : rgb = (red << 16 | green << 8 | blue); En dernier lieu, la valeur colorimétrique calculée est affectée au pixel actuel à l’aide de la méthode setPixel() de l’objet BitmapData result, comme illustré ci-dessous : result.setPixel(i, j, rgb); Décodage asynchrone des images bitmap Flash Player 11 et les versions ultérieures, Adobe AIR 2.6 et les versions ultérieures Lorsque vous manipulez des images bitmap, vous pouvez décoder et charger ces dernières en mode asynchrone pour optimiser les performances perçues d’une application. Dans de nombreux cas, le décodage asynchrone d’une image bitmap prend autant de temps que le décodage synchrone. L’image bitmap est toutefois décodée dans un thread distinct avant que l’objet Loader associé n’envoie l’événement COMPLETE. Il est par conséquent possible de décoder en mode asynchrone des images de taille supérieure après leur chargement. La classe ImageDecodingPolicy du package flash.system permet de stipuler le modèle de chargement de bitmap. Le modèle de chargement par défaut est synchrone. Traitement du décodage de bitmap Modèle de chargement de bitmap Description ImageDecodingPolicy.ON_DEMAND Synchrone Les images chargées sont décodées lorsque l’utilisateur accède aux données de l’image. Ce traitement est adapté au décodage des images de taille inférieure. Il s’avère également utile lorsque l’application ne nécessite pas d’effets et de transitions complexes. ImageDecodingPolicy.ON_LOAD Asynchrone Les images chargées sont décodées au chargement, avant la distribution de l’événement COMPLETE. Ce mode est parfaitement adapté aux images de taille supérieure (supérieure à 10 MP). Si vous développez une application mobile AIR contenant des transitions de page, faites appel à ce traitement de chargement de bitmap pour optimiser les performances perçues de l’application. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 274 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 Remarque : si le fichier en cours de chargement est une image bitmap et que la méthode de décodage utilisée est ON_LOAD, l’image est décodée de façon asynchrone avant la distribution de l’événement COMPLETE. Le code suivant illustre l’utilisation de la classe ImageDecodingPolicy : var loaderContext:LoaderContext = new LoaderContext(); loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD var loader:Loader = new Loader(); loader.load(new URLRequest("http://www.adobe.com/myimage.png"), loaderContext); Vous pouvez continuer à utiliser le traitement de décodage ON_DEMAND avec les méthodes Loader.load() et Loader.loadBytes(). Néanmoins, toutes les autres méthodes qui prennent un objet LoaderContext comme argument ignorent toutes les valeurs ImageDecodingPolicy transmises. L’exemple suivant illustre la différence entre une image décodée en mode synchrone et en mode asynchrone : package { import flash.display.Loader; import flash.display.Sprite; import flash.events.Event; import flash.net.URLRequest; import flash.system.ImageDecodingPolicy; import flash.system.LoaderContext; public class AsyncTest extends Sprite { private var loaderContext:LoaderContext; private var loader:Loader; private var urlRequest:URLRequest; public function AsyncTest() { //Load the image synchronously loaderContext = new LoaderContext(); //Default behavior. loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_DEMAND; loader = new Loader(); loadImageSync(); //Load the image asynchronously loaderContext = new LoaderContext(); loaderContext.imageDecodingPolicy = ImageDecodingPolicy.ON_LOAD; loader = new Loader(); loadImageASync(); } private function loadImageASync():void{ trace("Loading image asynchronously..."); urlRequest = new URLRequest("http://www.adobe.com/myimage.png"); urlRequest.useCache = false; loader.load(urlRequest, loaderContext); loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onAsyncLoadComplete); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 275 Utilisation des images bitmap Dernière mise à jour le 27/4/2013 } private function onAsyncLoadComplete(event:Event):void{ trace("Async. Image Load Complete"); } private function loadImageSync():void{ trace("Loading image synchronously..."); urlRequest = new URLRequest("http://www.adobe.com/myimage.png"); urlRequest.useCache = false; loader.load(urlRequest, loaderContext); loader.contentLoaderInfo.addEventListener (Event.COMPLETE, onSyncLoadComplete); } private function onSyncLoadComplete(event:Event):void{ trace("Sync. Image Load Complete"); } } } Pour une démonstration de l’effet des diverses stratégies de décodage, voir Thibaud Imbert: Asynchronous bitmap decoding in the Adobe Flash runtimes (disponible en anglais uniquement). 276 Dernière mise à jour le 27/4/2013 Chapitre 14 : Filtrage des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Historiquement, l’application d’effets de filtres à des images bitmap est du domaine des logiciels spécialisés en retouche d’image, comme Adobe Photoshop® et Adobe Fireworks®. ActionScript 3.0 comprend le package flash.filters, qui intègre une série de classes de filtres d’effet d’image bitmap. Ces effets permettent aux développeurs d’appliquer des filtres aux images bitmap et objets d’affichage par le biais d’un programme afin d’obtenir une grande partie des effets disponibles dans les applications de retouche graphique. Principes de base du filtrage des objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’une des façons de rendre une application plus séduisante est de lui ajouter des effets graphiques simples, comme une ombre portée derrière une photo pour créer l’illusion de la 3D, ou un rayonnement autour d’un bouton pour indiquer qu’il s’agit du bouton actif. ActionScript 3.0 comporte dix filtres qui peuvent être appliqués à n’importe quel objet d’affichage ou à une occurrence de BitmapData. Ces filtres vont des effets de base (filtres Ombre portée et Rayonnement) à des effets plus complexes, tels que le filtre Mappage du déplacement et le filtre Convolution matricielle. Remarque : outre les filtres intégrés, vous pouvez programmer des effets et filtres personnalisés par le biais de Pixel Bender (voir « Utilisation des shaders de Pixel Bender » à la page 310). Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs à la création de filtres : Biseau Effet de rebord créé en éclaircissant les pixels de deux côtés contigus et en assombrissant les pixels des deux côtés opposés, afin de créer un effet tridimensionnel de bordure fréquemment utilisé pour donner à des boutons et autres graphiques un effet enfoncé ou sorti. Convolution Distorsion des pixels d’une image obtenue en combinant la valeur de chaque pixel avec celle(s) d’un ou plusieurs des pixels voisins, selon divers pourcentages. Déplacement Décalage des pixels d’une image vers une nouvelle position. Matrice Grille de chiffres utilisée pour effectuer certains calculs mathématiques, en appliquant ces chiffres à diverses valeurs et en combinant le résultat. Voir aussi Package flash.filters flash.display.DisplayObject.filters flash.display.BitmapData.applyFilter() GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 277 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Création et application de filtres Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les filtres permettent d’appliquer divers effets (ombre portée, biseau, flou, etc.) à des images bitmap et à des objets d’affichage. Chaque filtre étant défini sous forme de classe, il suffit pour appliquer un filtre de créer une occurrence d’un objet filtre, ce qui n’est guère différent de la création de tout autre objet. Après avoir créé une occurrence d’un objet filtre, il est facile de l’appliquer à un objet d’affichage à l’aide de la propriété filters de cet objet ou, dans le cas d’un objet BitmapData, de sa méthode applyFilter(). Création d’un filtre Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour créer un objet filtre, il suffit d’appeler la fonction constructeur de la classe du filtre voulu. Par exemple, pour créer un objet DropShadowFilter, utilisez le code suivant : import flash.filters.DropShadowFilter; var myFilter:DropShadowFilter = new DropShadowFilter(); Bien que cela n’apparaisse pas dans cet exemple, le constructeur de DropShadowFilter() (comme tous les autres constructeurs des classes de filtres) accepte plusieurs paramètres facultatifs qui permettent de modifier l’aspect de l’effet du filtre. Application d’un filtre Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque l’objet filtre a été créé, vous pouvez l’appliquer à un objet d’affichage ou à un objet BitmapData, mais le mode d’application du filtre dépend de l’objet concerné. Application d’un filtre à un objet d’affichage Pour appliquer un effet de filtrage à un objet d’affichage, utilisez sa propriété filters. La propriété filters d’un objet d’affichage est une occurrence de l’objet Array, dont les éléments sont les objets filtres appliqués à l’objet d’affichage. Pour appliquer un seul filtre à un objet d’affichage, créez l’occurrence de ce filtre, ajoutez-la à une occurrence d’Array, et affectez cet objet Array à la propriété filters de l’objet d’affichage : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 278 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.Bitmap; import flash.display.BitmapData; import flash.filters.DropShadowFilter; // Create a bitmapData object and render it to screen var myBitmapData:BitmapData = new BitmapData(100,100,false,0xFFFF3300); var myDisplayObject:Bitmap = new Bitmap(myBitmapData); addChild(myDisplayObject); // Create a DropShadowFilter instance. var dropShadow:DropShadowFilter = new DropShadowFilter(); // Create the filters array, adding the filter to the array by passing it as // a parameter to the Array() constructor. var filtersArray:Array = new Array(dropShadow); // Assign the filters array to the display object to apply the filter. myDisplayObject.filters = filtersArray; Pour affecter plusieurs filtres à l’objet, il suffit d’ajouter tous ces filtres à l’occurrence d’Array avant de l’affecter à la propriété filters. Vous pouvez ajouter plusieurs objets à un objet Array en les passant en paramètres à son constructeur. Par exemple, ce code applique un filtre Biseau et un filtre Rayonnement à l’objet d’affichage créé précédemment : import flash.filters.BevelFilter; import flash.filters.GlowFilter; // Create the filters and add them to an array. var bevel:BevelFilter = new BevelFilter(); var glow:GlowFilter = new GlowFilter(); var filtersArray:Array = new Array(bevel, glow); // Assign the filters array to the display object to apply the filter. myDisplayObject.filters = filtersArray; Pour créer le tableau des filtres, vous pouvez utiliser le constructeur new Array() (comme dans les exemples précédents) ou la syntaxe littérale Array, en mettant les filtres entre crochets ([]). Par exemple, cette ligne de code : var filters:Array = new Array(dropShadow, blur); donne un résultat identique à celle-ci : var filters:Array = [dropShadow, blur]; Si vous appliquez plusieurs filtres à des objets d’affichage, ils sont appliqués en séquence, de manière cumulative. Par exemple, si un tableau de filtres comporte deux éléments, le filtre Biseau puis le filtre Ombre portée, ce dernier est appliqué à la fois au filtre Biseau et à l’objet d’affichage lui-même, du fait que le filtre Ombre portée est en seconde position dans le tableau des filtres. Si vous souhaitez appliquer des filtres de manière non cumulative, appliquez chaque filtre à une nouvelle copie de l’objet d’affichage. Pour affecter uniquement un ou quelques filtres à un objet d’affichage, vous pouvez créer l’occurrence du filtre et l’affecter à l’objet dans la même instruction. Par exemple, le code suivant applique un filtre Flou à un objet d’affichage nommé myDisplayObject : myDisplayObject.filters = [new BlurFilter()]; Le code précédent crée une occurrence d’Array en utilisant la syntaxe littérale d’Array (entre crochets), puis crée une nouvelle occurrence de BlurFilter comme élément du tableau, et affecte ce dernier à la propriété filters de l’objet d’affichage myDisplayObject. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 279 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Suppression des filtres appliqués à un objet Pour supprimer tous les filtres d’un objet d’affichage, il suffit d’affecter la valeur null à la propriété filters de celui-ci : myDisplayObject.filters = null; Si vous avez appliqué plusieurs filtres à un objet et souhaitez n’en supprimer qu’un, plusieurs étapes sont nécessaires pour modifier le tableau de la propriété filters. Pour plus d’informations, voir « Problèmes potentiels d’utilisation des filtres » à la page 279. Application d’un filtre à un objet BitmapData L’application d’un filtre à un objet BitmapData nécessite d’utiliser la méthode applyFilter() de l’objet BitmapData : var rect:Rectangle = new Rectangle(); var origin:Point = new Point(); myBitmapData.applyFilter(sourceBitmapData, rect, origin, new BlurFilter()); La méthode applyFilter() applique un filtre à un objet source BitmapData, produisant ainsi une nouvelle image filtrée. Cette méthode ne modifie pas l’image originale, car le résultat de l’application du filtre à celle-ci est enregistré dans l’occurrence de BitmapData pour laquelle la méthode applyFilter() est appelée. Fonctionnement des filtres Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le filtrage des objets d’affichage consiste à mettre en cache une copie de l’objet original sous forme d’un bitmap transparent. Lorsqu’un filtre a été appliqué à un objet d’affichage, le moteur d’exécution conserve en cache l’objet sous forme de bitmap tant que cet objet possède une liste de filtres valide. Le bitmap source est ensuite repris en tant qu’image originale pour les effets de filtrage suivants. Tout objet d’affichage comporte généralement deux bitmaps : le premier avec l’objet d’affichage source non filtré d’origine et un autre pour l’image finale après filtrage. L’image finale est utilisée pour le rendu. Tant que l’objet d’affichage ne change pas, l’image source ne nécessite aucune actualisation. Problèmes potentiels d’utilisation des filtres Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Plusieurs sources potentielles de confusion ou de problèmes peuvent survenir lors de l’utilisation de filtres. Filtres et mise en cache bitmap Pour appliquer un filtre à un objet d’affichage, vous devez activer la mise en cache sous forme de bitmap pour cet objet. Si vous appliquez un filtre à un objet d’affichage dont la propriété cacheAsBitmap est false, la propriété cacheAsBitmap de l’objet est automatiquement définie sur true. Si vous supprimez tous les filtres appliqués à l’objet d’affichage, la propriété cacheAsBitmap retrouve la valeur précédemment définie. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 280 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Modification des filtres à l’exécution Si un ou plusieurs filtres sont déjà appliqués à un objet d’affichage, vous ne pouvez pas modifier le jeu de filtres en ajoutant d’autres filtres ou en supprimant des filtres existants du tableau de la propriété filters. Pour modifier le jeu de filtres appliqué ou lui ajouter des filtres, vous devez plutôt effectuer les modifications requises dans un tableau distinct, puis l’assigner à la propriété filters de l’objet d’affichage pour que les filtres soient appliqués à l’objet. La procédure la plus simple consiste à lire le tableau de la propriété filters dans une variable Array, puis à effectuer les modifications requises dans ce tableau temporaire. Vous réassignez alors ce tableau à la propriété filters de l’objet d’affichage. Dans les cas de figure plus complexes, il peut s’avérer nécessaire de conserver un tableau maître distinct de filtres. Vous effectuez toute modification requise dans ce tableau maître de filtres, puis vous le réassignez à la propriété filters de l’objet d’affichage après chaque modification. Ajout d’un autre filtre Le code suivant illustre le processus d’ajout d’un autre filtre à un objet d’affichage auquel sont déjà appliqués un ou plusieurs filtres. Initialement, un filtre Rayonnement est appliqué à l’objet d’affichage myDisplayObject. Lorsque l’utilisateur clique sur l’objet d’affichage, la fonction addFilters() est appelée. Dans cette fonction, deux filtres supplémentaires sont appliqués à myDisplayObject : import flash.events.MouseEvent; import flash.filters.*; myDisplayObject.filters = [new GlowFilter()]; function addFilters(event:MouseEvent):void { // Make a copy of the filters array. var filtersCopy:Array = myDisplayObject.filters; // Make desired changes to the filters (in this case, adding filters). filtersCopy.push(new BlurFilter()); filtersCopy.push(new DropShadowFilter()); // Apply the changes by reassigning the array to the filters property. myDisplayObject.filters = filtersCopy; } myDisplayObject.addEventListener(MouseEvent.CLICK, addFilters); Suppression d’un filtre dans un jeu de filtres Si plusieurs filtres sont appliqués à un objet d’affichage et que vous souhaitez supprimer l’un des filtres sans affecter les autres filtres appliqués, vous copiez les filtres dans un tableau temporaire, vous supprimez le filtre superflu du tableau, puis vous réassignez le tableau temporaire à la propriété filters de l’objet d’affichage. La section « Récupération des valeurs et suppression des éléments du tableau » à la page 32 décrit plusieurs techniques de suppression d’un ou de plusieurs éléments de tout tableau. La technique la plus simple consiste à supprimer le filtre en tête de pile appliqué à l’objet (en d’autres termes, le dernier filtre appliqué à ce dernier). Vous utilisez la méthode pop() de la classe Array pour supprimer le filtre du tableau : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 281 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 // Example of removing the top-most filter from a display object // named "filteredObject". var tempFilters:Array = filteredObject.filters; // Remove the last element from the Array (the top-most filter). tempFilters.pop(); // Apply the new set of filters to the display object. filteredObject.filters = tempFilters; Pour supprimer le filtre en bas de pile (en d’autres termes, le premier filtre appliqué à l’objet), vous utilisez le même code en substituant la méthode shift() de la classe Array à la méthode pop(). Pour supprimer un filtre figurant au centre d’un tableau de filtres (sous réserve que le tableau contienne plus de deux filtres), vous disposez de la méthode splice(). Vous devez connaître l’index (la position dans le tableau) du filtre à supprimer. Par exemple, le code suivant supprime le deuxième filtre (doté de l’index 1) d’un objet d’affichage : // Example of removing a filter from the middle of a stack of filters // applied to a display object named "filteredObject". var tempFilters:Array = filteredObject.filters; // Remove the second filter from the array. It's the item at index 1 // because Array indexes start from 0. // The first "1" indicates the index of the filter to remove; the // second "1" indicates how many elements to remove. tempFilters.splice(1, 1); // Apply the new set of filters to the display object. filteredObject.filters = tempFilters; Identification de l’index d’un filtre Vous devez connaître l’index du filtre à supprimer du tableau. A cet effet, il est nécessaire d’identifier (selon le mode de conception de l’application) ou de calculer l’index du filtre à supprimer. L’approche recommandée consiste à concevoir votre application de sorte que le filtre à supprimer occupe systématiquement la même position dans le jeu de filtres. Par exemple, si vous disposez d’un objet d’affichage unique auquel sont appliqués un filtre Convolution et un filtre Ombre portée (dans cet ordre) et que vous souhaitez supprimer le filtre Ombre portée tout en conservant le filtre Convolution, vous connaissez la position occupée par le filtre (première). Vous savez donc à l’avance quelle méthode Array utiliser (soit, dans ce cas, Array.pop() pour supprimer le filtre Ombre portée). Si le filtre à supprimer est toujours d’un type déterminé, mais qu’il n’occupe pas systématiquement la même position dans le jeu de filtres, vous pouvez vérifier le type de données de chaque filtre du tableau pour identifier le filtre à supprimer. Par exemple, le code suivant identifie le filtre Rayonnement dans un jeu de filtres et le supprime de ce dernier. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 282 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 // Example of removing a glow filter from a set of filters, where the //filter you want to remove is the only GlowFilter instance applied // to the filtered object. var tempFilters:Array = filteredObject.filters; // Loop through the filters to find the index of the GlowFilter instance. var glowIndex:int; var numFilters:int = tempFilters.length; for (var i:int = 0; i < numFilters; i++) { if (tempFilters[i] is GlowFilter) { glowIndex = i; break; } } // Remove the glow filter from the array. tempFilters.splice(glowIndex, 1); // Apply the new set of filters to the display object. filteredObject.filters = tempFilters; Dans un cas de figure plus complexe (si le filtre à supprimer est sélectionné à l’exécution, par exemple), l’approche recommandée consiste à conserver une copie distincte et permanente du tableau de filtres, qui sert de liste maîtresse de filtres. Lorsque vous modifiez le jeu de filtres, modifiez la liste maîtresse, puis appliquez ce tableau de filtres en tant que propriété filters de l’objet d’affichage. Par exemple, dans le code ci-après, plusieurs filtres Convolution sont appliqués à un objet d’affichage pour créer divers effets visuels et l’un de ces filtres est supprimé ultérieurement dans l’application sans affecter les autres filtres. Dans ce cas de figure, le code conserve une copie maîtresse du tableau de filtres, ainsi qu’une référence au filtre à supprimer. Rechercher et identifier le filtre approprié est similaire à l’approche précédente, excepté qu’au lieu d’effectuer une copie temporaire du tableau de filtres, la copie maîtresse est manipulée, puis appliquée à l’objet d’affichage. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 283 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 // Example of removing a filter from a set of // filters, where there may be more than one // of that type of filter applied to the filtered // object, and you only want to remove one. // A master list of filters is stored in a separate, // persistent Array variable. var masterFilterList:Array; // At some point, you store a reference to the filter you // want to remove. var filterToRemove:ConvolutionFilter; // ... assume the filters have been added to masterFilterList, // which is then assigned as the filteredObject.filters: filteredObject.filters = masterFilterList; // ... later, when it's time to remove the filter, this code gets called: // Loop through the filters to find the index of masterFilterList. var removeIndex:int = -1; var numFilters:int = masterFilterList.length; for (var i:int = 0; i < numFilters; i++) { if (masterFilterList[i] == filterToRemove) { removeIndex = i; break; } } if (removeIndex >= 0) { // Remove the filter from the array. masterFilterList.splice(removeIndex, 1); // Apply the new set of filters to the display object. filteredObject.filters = masterFilterList; } Si vous adoptez cette approche (qui consiste à comparer une référence stockée à un filtre aux éléments que contient le tableau de filtres pour identifier le filtre à supprimer), vous devez conserver une copie distincte du tableau de filtres. En effet, le code ne fonctionne pas si vous comparez la référence stockée au filtre aux éléments d’un tableau temporaire copié dans la propriété filters de l’objet d’affichage. La raison en est simple : lorsque vous assignez un tableau à la propriété filters, le moteur d’exécution effectue une copie de chaque objet filtre du tableau. Ces copies (plutôt que les objets d’origine) sont appliquées à l’objet d’affichage. Lorsque vous lisez la propriété filters dans un tableau temporaire, celui-ci contient des références aux objets filtre copiés plutôt qu’aux objets filtre d’origine. Par conséquent, si vous tentez dans l’exemple précédent de déterminer l’index de filterToRemove en le comparant aux filtres d’un tableau de filtres temporaire, aucune correspondance n’est détectée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 284 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Filtres et transformations d’objets Les zones filtrées (ombres portées, par exemple) situées hors du cadre de sélection d’un objet d’affichage ne sont pas prises en considération pour la détection de clics (chevauchement ou intersection de deux occurrences). La méthode de détection des clics de la classe DisplayObject étant de type vectoriel, il est impossible d’en pratiquer une sur le bitmap résultant. Par exemple, si vous appliquez un filtre Biseau à une occurrence de bouton, la détection des clics n’est pas possible sur la partie biseautée de l’occurrence. Le redimensionnement, la rotation et l’inclinaison ne sont pas pris en charge par les filtres ; si l’objet d’affichage filtré lui-même est redimensionné (scaleX et scaleY différents de 100 %), l’effet de filtre n’est pas redimensionné avec l’occurrence. La forme originale de l’occurrence est certes pivotée, inclinée ou redimensionnée, mais pas le filtre. Vous pouvez animer une occurrence avec un filtre afin de créer des effets réalistes, ou imbriquer des occurrences et utiliser la classe BitmapData pour animer des filtres afin d’obtenir ces effets. Filtres et objets bitmaps Si vous appliquez un filtre à un objet BitmapData, la propriété cacheAsBitmap de cet objet est automatiquement true. Le filtre peut ainsi être appliqué à la copie de l’objet plutôt qu’à ce dernier. Cette copie est alors placée à l’écran par-dessus l’objet original, aussi près que possible, au pixel près. Si les limites du bitmap original changent, la copie à laquelle le filtrage est appliqué est recréée à partir de l’original au lieu d’être étirée. Si vous supprimez tous les filtres de l’objet d’affichage, la propriété cacheAsBitmap retrouve sa valeur d’origine. Filtres d’affichage disponibles Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript 3.0 comprend dix classes de filtre que vous pouvez appliquer aux objets d’affichage et aux objets BitmapData : • filtre Biseau (classe BevelFilter) • filtre Flou (classe BlurFilter) • filtre Ombre portée (classe DropShadowFilter) • filtre Rayonnement (classe GlowFilter) • filtre Biseau dégradé (classe GradientBevelFilter) • filtre Rayonnement dégradé (classe GradientGlowFilter) • filtre Matrice de couleurs (classe ColorMatrixFilter) • filtre Convolution (classe ConvolutionFilter) • filtre Mappage de déplacement (classe DisplacementMapFilter) • filtre Shader (classe ShaderFilter) Les six premiers sont des filtres simples pouvant être utilisés pour des effets spécifiques, avec certains réglages possibles. Ces six filtres peuvent être appliqués en ActionScript, mais aussi à partir du panneau Filtres de Flash Professional. Par conséquent, même si vous appliquez des filtres à l’aide d’ActionScript, sous réserve de disposer de Flash Professional, vous pouvez utiliser son interface visuelle pour vérifier rapidement l’effet des différents filtres et de leurs réglages afin de créer l’effet désiré. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 285 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Les quatre derniers filtres sont uniquement disponibles en ActionScript. Ces filtres (filtre Matrice de couleurs, filtre Convolution, filtre Mappage de déplacement et filtre Shader) permettent de créer des types d’effet beaucoup plus souples. Plutôt que proposer un effet unique optimisé, ils assurent puissance et souplesse. Par exemple, en choisissant différentes valeurs pour sa matrice, il est possible d’utiliser le filtre Convolution pour créer des effets de flou, de gravure, d’accentuation, mais aussi pour des transformations, la détection de contour des couleurs, etc. Chacun de ces filtres, qu’il soit simple ou complexe, dispose de propriétés dont les valeurs peuvent être modifiées. En général, il existe deux possibilités pour définir les propriétés d’un filtre. Tous les filtres permettent de définir leurs propriétés en passant des valeurs en paramètres au constructeur de l’objet filtre. Que les propriétés du filtre soient définies ou non par un passage de paramètres, il est aussi possible de modifier ultérieurement ses réglages en changeant les valeurs des propriétés de l’objet filtre. La plupart des exemples de code définissent directement les propriétés pour faciliter la compréhension de l’exemple. Néanmoins, il est également possible, en général, d’obtenir le même résultat avec moins de lignes de code, en passant les valeurs en paramètres dans le constructeur de l’objet filtre. Pour plus d’informations sur les caractéristiques de chaque filtre, ses propriétés et les paramètres constructeurs correspondants, voir les codes associés au package flash.filters dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Filtre Biseau Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe BevelFilter vous permet d’ajouter une bordure en relief à l’objet filtré. Avec ce filtre, les angles et les côtés des objets semblent ciselés, biseautés. Les propriétés de la classe BevelFilter permettent de modifier l’apparence du biseau. Vous pouvez définir les couleurs des zones claires et sombres, l’adoucissement et les angles des côtés du biseau, ainsi que la tille de ces derniers. Vous pouvez même créer un effet de poinçonnage. L’exemple suivant charge une image externe et lui applique un filtre Biseau. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 286 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.*; import flash.filters.BevelFilter; import flash.filters.BitmapFilterQuality; import flash.filters.BitmapFilterType; import flash.net.URLRequest; // Load an image onto the Stage. var imageLoader:Loader = new Loader(); var url:String = "http://www.helpexamples.com/flash/images/image3.jpg"; var urlReq:URLRequest = new URLRequest(url); imageLoader.load(urlReq); addChild(imageLoader); // Create the bevel filter and set filter properties. var bevel:BevelFilter = new BevelFilter(); bevel.distance = 5; bevel.angle = 45; bevel.highlightColor = 0xFFFF00; bevel.highlightAlpha = 0.8; bevel.shadowColor = 0x666666; bevel.shadowAlpha = 0.8; bevel.blurX = 5; bevel.blurY = 5; bevel.strength = 5; bevel.quality = BitmapFilterQuality.HIGH; bevel.type = BitmapFilterType.INNER; bevel.knockout = false; // Apply filter to the image. imageLoader.filters = [bevel]; Filtre Flou Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe BlurFilter ajoute un effet de flou à un objet d’affichage et son contenu. Les effets de flou permettent de donner l’impression qu’un objet n’est pas dans le plan de mise au point ou de simuler l’effet d’un mouvement rapide (flou de mouvement). En choisissant une valeur faible pour la propriété quality, vous pouvez simuler un effet de photo légèrement floue. Le choix d’une valeur élevée pour la propriété quality permet d’obtenir un effet de flou léger proche de celui d’un flou gaussien. L’exemple suivant crée un objet cercle à l’aide de la méthode drawCircle() de la classe Graphics, puis lui applique un filtre Flou : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 287 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.Sprite; import flash.filters.BitmapFilterQuality; import flash.filters.BlurFilter; // Draw a circle. var redDotCutout:Sprite = new Sprite(); redDotCutout.graphics.lineStyle(); redDotCutout.graphics.beginFill(0xFF0000); redDotCutout.graphics.drawCircle(145, 90, 25); redDotCutout.graphics.endFill(); // Add the circle to the display list. addChild(redDotCutout); // Apply the blur filter to the rectangle. var blur:BlurFilter = new BlurFilter(); blur.blurX = 10; blur.blurY = 10; blur.quality = BitmapFilterQuality.MEDIUM; redDotCutout.filters = [blur]; Filtre Ombre portée Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’ombre portée donne l’impression d’une source lumineuse ponctuelle au-dessus de l’objet cible. Il est possible de modifier la position et l’intensité de cette source lumineuse pour produire divers effets d’ombre portée. La classe DropShadowFilter utilise un algorithme similaire à celui du filtre Flou. La principale différence tient au fait que le filtre Ombre portée possède quelques propriétés supplémentaires qui permettent de simuler diverses caractéristiques d’une source lumineuse (canal alpha, couleur, décalage et luminosité). Le filtre Ombre portée permet aussi d’appliquer des options de transformation au style de l’ombre portée (ombre interne ou externe, ou mode de masquage). Le code suivant crée un objet Sprite carré et lui applique un filtre Ombre portée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 288 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.Sprite; import flash.filters.DropShadowFilter; // Draw a box. var boxShadow:Sprite = new Sprite(); boxShadow.graphics.lineStyle(1); boxShadow.graphics.beginFill(0xFF3300); boxShadow.graphics.drawRect(0, 0, 100, 100); boxShadow.graphics.endFill(); addChild(boxShadow); // Apply the drop shadow filter to the box. var shadow:DropShadowFilter = new DropShadowFilter(); shadow.distance = 10; shadow.angle = 25; // You can also set other properties, such as the shadow color, // alpha, amount of blur, strength, quality, and options for // inner shadows and knockout effects. boxShadow.filters = [shadow]; Filtre Rayonnement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe GlowFilter applique un effet d’éclairage aux objets d’affichage afin de suggérer qu’une lumière est braquée à partir du dessous de l’objet pour créer un faible rayonnement. Comme le filtre Ombre portée, le filtre Rayonnement possède des propriétés qui permettent de modifier la distance, l’angle et la couleur de la source lumineuse en fonction de l’effet désiré. L’objet GlowFilter comporte aussi plusieurs options pour modifier le style de rayonnement, notamment le rayonnement interne ou externe et le mode de masquage. Le code suivant crée un objet Sprite en forme de croix et lui applique un filtre Rayonnement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 289 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.Sprite; import flash.filters.BitmapFilterQuality; import flash.filters.GlowFilter; // Create a cross graphic. var crossGraphic:Sprite = new Sprite(); crossGraphic.graphics.lineStyle(); crossGraphic.graphics.beginFill(0xCCCC00); crossGraphic.graphics.drawRect(60, 90, 100, 20); crossGraphic.graphics.drawRect(100, 50, 20, 100); crossGraphic.graphics.endFill(); addChild(crossGraphic); // Apply the glow filter to the cross shape. var glow:GlowFilter = new GlowFilter(); glow.color = 0x009922; glow.alpha = 1; glow.blurX = 25; glow.blurY = 25; glow.quality = BitmapFilterQuality.MEDIUM; crossGraphic.filters = [glow]; Filtre Biseau dégradé Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe GradientBevelFilter vous permet d’appliquer un effet de biseau optimisé aux objets d’affichage ou aux objets BitmapData. L’utilisation d’un dégradé de couleurs sur le biseau améliore beaucoup l’effet de relief de celui-ci, en donnant aux côtés un aspect 3D plus réaliste. L’exemple suivant crée un objet rectangle à l’aide de la méthode drawRect() de la classe Shape, puis lui applique un filtre Biseau dégradé : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 290 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.Shape; import flash.filters.BitmapFilterQuality; import flash.filters.GradientBevelFilter; // Draw a rectangle. var box:Shape = new Shape(); box.graphics.lineStyle(); box.graphics.beginFill(0xFEFE78); box.graphics.drawRect(100, 50, 90, 200); box.graphics.endFill(); // Apply a gradient bevel to the rectangle. var gradientBevel:GradientBevelFilter = new GradientBevelFilter(); gradientBevel.distance = 8; gradientBevel.angle = 225; // opposite of 45 degrees gradientBevel.colors = [0xFFFFCC, 0xFEFE78, 0x8F8E01]; gradientBevel.alphas = [1, 0, 1]; gradientBevel.ratios = [0, 128, 255]; gradientBevel.blurX = 8; gradientBevel.blurY = 8; gradientBevel.quality = BitmapFilterQuality.HIGH; // Other properties let you set the filter strength and set options // for inner bevel and knockout effects. box.filters = [gradientBevel]; // Add the graphic to the display list. addChild(box); Filtre Rayonnement dégradé Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe GradientGlowFilter vous permet d’appliquer un effet de rayonnement optimisé aux objets d’affichage ou aux objets BitmapData. Cet effet donne davantage de contrôle sur le rayonnement, produisant ainsi un effet plus réaliste. De plus, le filtre Rayonnement dégradé permet d’appliquer un rayonnement aux côtés intérieur, extérieur ou supérieur de l’objet. L’exemple suivant dessine un cercle auquel un filtre Rayonnement dégradé est appliqué. Le montant de flou horizontal et vertical augmente à mesure que le pointeur de la souris s’approche du coin inférieur droit de la scène. Si l’utilisateur clique dans la scène, le niveau de flou augmente. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 291 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.events.MouseEvent; import flash.filters.BitmapFilterQuality; import flash.filters.BitmapFilterType; import flash.filters.GradientGlowFilter; // Create a new Shape instance. var shape:Shape = new Shape(); // Draw the shape. shape.graphics.beginFill(0xFF0000, 100); shape.graphics.moveTo(0, 0); shape.graphics.lineTo(100, 0); shape.graphics.lineTo(100, 100); shape.graphics.lineTo(0, 100); shape.graphics.lineTo(0, 0); shape.graphics.endFill(); // Position the shape on the Stage. addChild(shape); shape.x = 100; shape.y = 100; // Define a gradient glow. var gradientGlow:GradientGlowFilter = new GradientGlowFilter(); gradientGlow.distance = 0; gradientGlow.angle = 45; gradientGlow.colors = [0x000000, 0xFF0000]; gradientGlow.alphas = [0, 1]; gradientGlow.ratios = [0, 255]; gradientGlow.blurX = 10; gradientGlow.blurY = 10; gradientGlow.strength = 2; gradientGlow.quality = BitmapFilterQuality.HIGH; gradientGlow.type = BitmapFilterType.OUTER; // Define functions to listen for two events. function onClick(event:MouseEvent):void { gradientGlow.strength++; shape.filters = [gradientGlow]; } function onMouseMove(event:MouseEvent):void { gradientGlow.blurX = (stage.mouseX / stage.stageWidth) * 255; gradientGlow.blurY = (stage.mouseY / stage.stageHeight) * 255; shape.filters = [gradientGlow]; } stage.addEventListener(MouseEvent.CLICK, onClick); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 292 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Exemple : Combinaison de filtres de base Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple de code suivant applique plusieurs filtres de base, en combinaison avec un timer pour la création d’actions répétitives, pour obtenir la simulation d’un feu de circulation. import flash.display.Shape; import flash.events.TimerEvent; import flash.filters.BitmapFilterQuality; import flash.filters.BitmapFilterType; import flash.filters.DropShadowFilter; import flash.filters.GlowFilter; import flash.filters.GradientBevelFilter; import flash.utils.Timer; var count:Number = 1; var distance:Number = 8; var angleInDegrees:Number = 225; // opposite of 45 degrees var colors:Array = [0xFFFFCC, 0xFEFE78, 0x8F8E01]; var alphas:Array = [1, 0, 1]; var ratios:Array = [0, 128, 255]; var blurX:Number = 8; var blurY:Number = 8; var strength:Number = 1; var quality:Number = BitmapFilterQuality.HIGH; var type:String = BitmapFilterType.INNER; var knockout:Boolean = false; // Draw the rectangle background for the traffic light. var box:Shape = new Shape(); box.graphics.lineStyle(); box.graphics.beginFill(0xFEFE78); box.graphics.drawRect(100, 50, 90, 200); box.graphics.endFill(); // Draw the 3 circles for the three lights. var stopLight:Shape = new Shape(); stopLight.graphics.lineStyle(); stopLight.graphics.beginFill(0xFF0000); stopLight.graphics.drawCircle(145,90,25); stopLight.graphics.endFill(); var cautionLight:Shape = new Shape(); cautionLight.graphics.lineStyle(); cautionLight.graphics.beginFill(0xFF9900); cautionLight.graphics.drawCircle(145,150,25); cautionLight.graphics.endFill(); var goLight:Shape = new Shape(); goLight.graphics.lineStyle(); goLight.graphics.beginFill(0x00CC00); goLight.graphics.drawCircle(145,210,25); goLight.graphics.endFill(); // Add the graphics to the display list. addChild(box); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 293 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 addChild(stopLight); addChild(cautionLight); addChild(goLight); // Apply a gradient bevel to the traffic light rectangle. var gradientBevel:GradientBevelFilter = new GradientBevelFilter(distance, angleInDegrees, colors, alphas, ratios, blurX, blurY, strength, quality, type, knockout); box.filters = [gradientBevel]; // Create the inner shadow (for lights when off) and glow // (for lights when on). var innerShadow:DropShadowFilter = new DropShadowFilter(5, 45, 0, 0.5, 3, 3, 1, 1, true, false); var redGlow:GlowFilter = new GlowFilter(0xFF0000, 1, 30, 30, 1, 1, false, false); var yellowGlow:GlowFilter = new GlowFilter(0xFF9900, 1, 30, 30, 1, 1, false, false); var greenGlow:GlowFilter = new GlowFilter(0x00CC00, 1, 30, 30, 1, 1, false, false); // Set the starting state of the lights (green on, red/yellow off). stopLight.filters = [innerShadow]; cautionLight.filters = [innerShadow]; goLight.filters = [greenGlow]; // Swap the filters based on the count value. function trafficControl(event:TimerEvent):void { if (count == 4) { count = 1; } switch (count) { case 1: stopLight.filters = [innerShadow]; cautionLight.filters = [yellowGlow]; goLight.filters = [innerShadow]; break; case 2: stopLight.filters = [redGlow]; cautionLight.filters = [innerShadow]; goLight.filters = [innerShadow]; break; case 3: stopLight.filters = [innerShadow]; cautionLight.filters = [innerShadow]; goLight.filters = [greenGlow]; break; } count++; } // Create a timer to swap the filters at a 3 second interval. var timer:Timer = new Timer(3000, 9); timer.addEventListener(TimerEvent.TIMER, trafficControl); timer.start(); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 294 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Filtre Matrice de couleurs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe ColorMatrixFilter permet de manipuler les valeurs de couleur et les valeurs alpha des objets filtrés. Il est ainsi possible de créer des changements de saturation, des rotations de teinte (passage d’une palette d’une plage de couleur à une autre), de définir la luminance de la couche alpha et de produire d’autres effets de manipulation des couleurs en utilisant les valeurs d’un canal couleur pour les appliquer aux autres canaux. Le principe de fonctionnement de ce filtre est le suivant : les pixels de l’image source sont analysés un par un et leurs composants rouge, vert, bleu et alpha sont séparés. Les valeurs de la matrice de couleur sont alors multipliées par chacune de ces valeurs, et les résultats sont ajoutés pour déterminer la valeur colorimétrique résultante qui sera affichée à l’écran pour ce pixel. La propriété matrix du filtre est un tableau de 20 nombres qui sont utilisés pour le calcul de la couleur finale. Pour plus d’informations sur l’algorithme utilisé pour calculer les valeurs de couleur, voir la description de la propriété matrix de la classe ColorMatrixFilter dans le manuel Guide de référence ActionScript 3.0 pour la plateforme Adobe Flash. Filtre Convolution Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe ConvolutionFilter permet d’appliquer un large éventail de transformations de traitement d’images aux objets BitmapData ou aux objets d’affichage, tels que la définition du flou, la détection du contour, l’accentuation, l’estampage et le biseautage. Le principe de fonctionnement du filtre Convolution est le suivant : les pixels de l’image source sont analysés un par un pour déterminer la couleur finale de ce pixel sur la base de sa valeur et de celles des pixels adjacents. Une matrice, sous forme d’un tableau de valeurs numériques, indique dans quelle mesure la valeur de chaque pixel adjacent particulier affecte la valeur finale. Le type de matrice le plus fréquemment utilisé est un tableau de trois par trois. La matrice comporte donc neuf valeurs : N N N N P N N N N Lorsque le filtre Convolution est appliqué à un pixel donné, il analyse la valeur colorimétrique du pixel lui-même (« P » dans notre exemple) et celles des pixels environnants (« N » dans l’exemple). Toutefois, le choix des valeurs de la matrice permet de spécifier la priorité de certains pixels pour le calcul de l’image résultante. Par exemple, la matrice suivante, appliquée à un filtre Convolution, laissera l’image intacte, exactement comme l’image originale : 0 0 0 0 1 0 0 0 0 L’image n’a pas été modifiée car la valeur du pixel original a une priorité relative de 1 pour déterminer la couleur du pixel final, alors que les pixels environnants ont une priorité relative de 0 (autrement dit, leur couleur n’affecte pas l’image finale). De même, la matrice suivante provoque un décalage à gauche de tous les pixels d’une image : 0 0 0 0 0 1 0 0 0 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 295 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Notez que dans cet exemple, le pixel lui-même n’a aucun effet sur la valeur finale du pixel affiché au même emplacement dans l’image finale : seule la valeur du pixel de droite est utilisée pour déterminer la valeur résultante de chaque pixel. En ActionScript, la matrice est une combinaison d’une occurrence de l’objet Array contenant les valeurs et deux propriétés spécifiant le nombre de lignes et de colonnes de la matrice. L’exemple suivant charge une image, puis lui applique un filtre Convolution sur la base de la matrice du listing précédent : // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); function applyFilter(event:MouseEvent):void { // Create the convolution matrix. var matrix:Array = [0, 0, 0, 0, 0, 1, 0, 0, 0]; var convolution:ConvolutionFilter = new ConvolutionFilter(); convolution.matrixX = 3; convolution.matrixY = 3; convolution.matrix = matrix; convolution.divisor = 1; loader.filters = [convolution]; } loader.addEventListener(MouseEvent.CLICK, applyFilter); Un point important n’est pas évident dans ce code : l’effet de valeurs autres que 1 ou 0 dans la matrice. Par exemple, la même matrice avec le chiffre 8 au lieu de 1 dans le coin supérieur droit effectuerait la même action (décalage des pixels vers la gauche). Toutefois, les couleurs de l’image seraient 8 fois plus lumineuses. En effet, les valeurs finales de couleur des pixels sont calculées en multipliant les valeurs de la matrice par celles des couleurs originales des pixels, en additionnant ces valeurs, puis en les divisant par celle de la propriété divisor du filtre. Notez que, dans cet exemple, la propriété divisor a la valeur 1. En règle générale, pour que la luminosité des couleurs reste à peu près identique à celle des couleurs de l’image originale, la propriété divisor doit avoir une valeur égale à la somme des valeurs de la matrice. Ainsi, avec une matrice dont la somme des valeurs est 8, et pour un diviseur de 1, l’image résultante sera environ 8 fois plus lumineuse que l’image originale. Bien que l’effet de cette matrice ne soit pas très spectaculaire, d’autres valeurs peuvent être utilisées pour créer divers effets. Voici quelques ensembles standard de valeurs de matrice permettant d’obtenir divers effets avec une matrice de trois sur trois : • Flou de base (diviseur 5) : 0 1 0 1 1 1 0 1 0 • Accentuation (diviseur 1) : 0, -1, 0 -1, 5, -1 0, -1, 0 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 296 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 • Détection des contours (diviseur 1) : 0, -1, 0 -1, 4, -1 0, -1, 0 • Estampage (diviseur 1) : -2, -1, 0 -1, 1, 1 0, 1, 2 Notez qu’avec la plupart de ces effets, le diviseur est 1. En effet, l’addition des valeurs négatives et des valeurs positives dans la matrice donne 1 (ou 0 dans le cas de la détection des contours, mais la valeur de la propriété divisor ne peut pas être 0). Filtre Mappage de déplacement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe DisplacementMapFilter utilise des valeurs de pixel extraites d’un objet BitmapData (appelé image de mappage du déplacement) pour appliquer un effet de déplacement à un nouvel objet. L’image de mappage du déplacement est en général différente de l’occurrence d’objet d’affichage ou BitmapData à laquelle le filtre est appliqué. L’effet de déplacement nécessite de déplacer les pixels de l’image filtrée, autrement dit de les décaler d’un certain niveau. Ce filtre permet de créer un effet de décalage, de gondole ou de marbrure. La direction et la valeur du déplacement appliqué à un pixel donné sont déterminées par la valeur colorimétrique de l’image de mappage du déplacement. Pour utiliser ce filtre, il est nécessaire de spécifier l’image de mappage, ainsi que les valeurs suivantes, qui permettent de contrôler le calcul du déplacement : • Point de mappage : emplacement, dans l’image filtrée, auquel le coin supérieur gauche du filtre de déplacement sera appliqué. Ce paramètre n’est nécessaire que pour appliquer le filtre à une partie de l’image seulement. • Composant X : canal couleur de l’image de mappage qui affecte la position x des pixels. • Composant Y : canal couleur de l’image de mappage qui affecte la position y des pixels. • Echelle X : valeur multiplicatrice qui indique le niveau de déplacement sur l’axe x. • Echelle Y : valeur multiplicatrice qui indique le niveau de déplacement sur l’axe y. • Mode de filtrage : détermine la marche à suivre dans le cas d’espaces vides créés par le décalage des pixels. Les options, définies par des constantes dans la classe DisplacementMapFilterMode, sont d’afficher les pixels originaux (mode IGNORE), de décaler et transférer les pixels de l’autre côté de l’image (mode WRAP, qui est le mode par défaut), d’utiliser le pixel déplacé le plus proche (mode CLAMP) ou de remplir ces espaces vides avec une couleur (mode COLOR). Pour comprendre le fonctionnement d’un filtre de mappage de déplacement, prenons un exemple simple. Dans le code ci-dessous, une image est chargée, puis elle est centrée sur la scène et un filtre Mappage de déplacement lui est appliqué, ce qui déplace horizontalement (vers la gauche) les pixels de toute l’image. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 297 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.BitmapData; import flash.display.Loader; import flash.events.MouseEvent; import flash.filters.DisplacementMapFilter; import flash.geom.Point; import flash.net.URLRequest; // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image3.jpg"); loader.load(url); this.addChild(loader); var mapImage:BitmapData; var displacementMap:DisplacementMapFilter; // This function is called when the image finishes loading. function setupStage(event:Event):void { // Center the loaded image on the Stage. loader.x = (stage.stageWidth - loader.width) / 2; loader.y = (stage.stageHeight - loader.height) / 2; // Create the displacement map image. mapImage = new BitmapData(loader.width, loader.height, false, 0xFF0000); // Create the displacement filter. displacementMap = new DisplacementMapFilter(); displacementMap.mapBitmap = mapImage; displacementMap.mapPoint = new Point(0, 0); displacementMap.componentX = BitmapDataChannel.RED; displacementMap.scaleX = 250; loader.filters = [displacementMap]; } loader.contentLoaderInfo.addEventListener(Event.COMPLETE, setupStage); Les propriétés utilisées pour définir le déplacement sont les suivantes : • Bitmap de mappage : le bitmap de déplacement est une nouvelle occurrence de BitmapData, créée par code. Ses dimensions sont identiques à celles de l’image chargée (le déplacement est donc appliqué à toute l’image). Elle est remplie de pixels rouges opaques. • Point de mappage : cette valeur est définie pour le point 0, 0 (ici encore, le déplacement sera appliqué à toute l’image). • Composant X : cette valeur reçoit la constante BitmapDataChannel.RED, ce qui signifie que c’est la valeur de rouge de l’image bitmap de mappage qui déterminera le niveau de déplacement des pixels sur l’axe x. • Echelle X : cette valeur est réglée sur 250. L’image de mappage étant entièrement rouge, la valeur totale de déplacement ne décale l’image que faiblement (environ un demi-pixel). Si cette valeur était de 1, l’image ne serait donc décalée que de 0,5 pixel horizontalement. En choisissant une valeur de 250, nous déplaçons l’image d’environ 125 pixels. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 298 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Ces valeurs provoquent un déplacement des pixels de l’image filtrée de 250 pixels à gauche. La direction (gauche ou droite) et l’importance du déplacement dépendent de la valeur colorimétrique des pixels de l’image de mappage. Le principe de fonctionnement de ce filtre est le suivant : il analyse un par un les pixels de l’image filtrée (ou tout au moins ceux de la zone à laquelle le filtre est appliqué, ce qui ici signifie toute l’image), et procède comme suit pour chaque pixel : 1 Il détermine le pixel correspondant dans l’image de mappage. Par exemple, pour calculer la valeur de déplacement du pixel du coin supérieur gauche de l’image filtrée, le filtre analyse le pixel correspondant dans le coin supérieur gauche de l’image de mappage. 2 Il détermine la valeur du canal de couleur spécifié dans le pixel de mappage. Dans cet exemple, le canal de couleur du composant x est le rouge. Le filtre recherche donc la valeur du canal rouge au point en question dans l’image de mappage. L’image de mappage étant un rouge opaque, le canal rouge du pixel a la valeur 0xFF, soit 255. Cette valeur est la valeur de déplacement. 3 Ils comparent ensuite la valeur de déplacement à la valeur médiane (127, à mi-chemin entre 0 et 255). Si la valeur de déplacement est inférieure à la valeur médiane, le pixel est déplacé dans une direction positive (vers la droite pour l’axe x, vers le bas pour l’axe y). Par contre, si la valeur de déplacement est supérieure à la valeur médiane (comme dans cet exemple), le pixel est déplacé dans une direction négative (vers la gauche pour l’axe x, vers le haut pour l’axe y). Plus précisément, le filtre soustrait la valeur de déplacement de 127, et le résultat (positif ou négatif) est la valeur relative de déplacement qui est appliquée. 4 Enfin, ils déterminent la valeur réelle de déplacement en calculant le pourcentage de déplacement complet représenté par la valeur de déplacement relatif. Dans cet exemple, un rouge à 100 % provoque un déplacement de 100 %. Ce pourcentage est ensuite multiplié par la valeur de l’échelle x ou de l’échelle y pour déterminer le nombre de pixels de déplacement à appliquer. Dans cet exemple, la valeur de déplacement est 100 % multiplié par un multiple de 250, soit environ 125 pixels à gauche. Comme nous ne spécifions aucune valeur pour les composants x et y, les valeurs par défaut (qui ne provoquent pas de déplacement) sont utilisées. C’est pourquoi l’image n’est pas déplacée dans le sens vertical. Dans cet exemple, le paramètre par défaut de mode de filtrage, WRAP, est utilisé, si bien que lorsque les pixels sont déplacés vers la gauche, l’espace laissé vide à droite est rempli par les pixels qui ont été décalés le long du côté gauche de l’image. Vous pouvez modifier cette valeur pour voir les différents effets ainsi obtenus. Par exemple, si vous ajoutez la ligne suivante dans la partie du code qui définit les propriétés de déplacement (avant la ligne loader.filters = [displacementMap]), l’image semble avoir subi un balayage : displacementMap.mode = DisplacementMapFilterMode.CLAMP; Le code ci-dessous propose un exemple plus complexe, en utilisant un filtre Mappage de déplacement pour créer un effet de loupe dans l’image : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 299 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.GradientType; import flash.display.Loader; import flash.display.Shape; import flash.events.MouseEvent; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.Matrix; import flash.geom.Point; import flash.net.URLRequest; // Create the gradient circles that will together form the // displacement map image var radius:uint = 50; var type:String = GradientType.LINEAR; var redColors:Array = [0xFF0000, 0x000000]; var blueColors:Array = [0x0000FF, 0x000000]; var alphas:Array = [1, 1]; var ratios:Array = [0, 255]; var xMatrix:Matrix = new Matrix(); xMatrix.createGradientBox(radius * 2, radius * 2); var yMatrix:Matrix = new Matrix(); yMatrix.createGradientBox(radius * 2, radius * 2, Math.PI / 2); var xCircle:Shape = new Shape(); xCircle.graphics.lineStyle(0, 0, 0); xCircle.graphics.beginGradientFill(type, redColors, alphas, ratios, xMatrix); xCircle.graphics.drawCircle(radius, radius, radius); var yCircle:Shape = new Shape(); yCircle.graphics.lineStyle(0, 0, 0); yCircle.graphics.beginGradientFill(type, blueColors, alphas, ratios, yMatrix); yCircle.graphics.drawCircle(radius, radius, radius); // Position the circles at the bottom of the screen, for reference. this.addChild(xCircle); xCircle.y = stage.stageHeight - xCircle.height; this.addChild(yCircle); yCircle.y = stage.stageHeight - yCircle.height; yCircle.x = 200; // Load an image onto the Stage. var loader:Loader = new Loader(); var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); loader.load(url); this.addChild(loader); // Create the map image by combining the two gradient circles. var map:BitmapData = new BitmapData(xCircle.width, xCircle.height, false, 0x7F7F7F); map.draw(xCircle); var yMap:BitmapData = new BitmapData(yCircle.width, yCircle.height, false, 0x7F7F7F); yMap.draw(yCircle); map.copyChannel(yMap, yMap.rect, new Point(0, 0), BitmapDataChannel.BLUE, BitmapDataChannel.BLUE); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 300 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 yMap.dispose(); // Display the map image on the Stage, for reference. var mapBitmap:Bitmap = new Bitmap(map); this.addChild(mapBitmap); mapBitmap.x = 400; mapBitmap.y = stage.stageHeight - mapBitmap.height; // This function creates the displacement map filter at the mouse location. function magnify():void { // Position the filter. var filterX:Number = (loader.mouseX) - (map.width / 2); var filterY:Number = (loader.mouseY) - (map.height / 2); var pt:Point = new Point(filterX, filterY); var xyFilter:DisplacementMapFilter = new DisplacementMapFilter(); xyFilter.mapBitmap = map; xyFilter.mapPoint = pt; // The red in the map image will control x displacement. xyFilter.componentX = BitmapDataChannel.RED; // The blue in the map image will control y displacement. xyFilter.componentY = BitmapDataChannel.BLUE; xyFilter.scaleX = 35; xyFilter.scaleY = 35; xyFilter.mode = DisplacementMapFilterMode.IGNORE; loader.filters = [xyFilter]; } // This function is called when the mouse moves. If the mouse is // over the loaded image, it applies the filter. function moveMagnifier(event:MouseEvent):void { if (loader.hitTestPoint(loader.mouseX, loader.mouseY)) { magnify(); } } loader.addEventListener(MouseEvent.MOUSE_MOVE, moveMagnifier); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 301 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Ce code génère d’abord deux cercles en dégradé, qui sont combinés pour former l’image de mappage du déplacement. Le cercle rouge est à l’origine du déplacement sur l’axe x (xyFilter.componentX = BitmapDataChannel.RED) et le cercle bleu est à l’origine du déplacement sur l’axe y (xyFilter.componentY = BitmapDataChannel.BLUE). Pour vous permettre de comprendre plus aisément l’aspect de l’image de mappage du déplacement, le code affiche les cercles originaux, ainsi que le cercle combiné qui fait office d’image de mappage, en bas de l’écran. Le code charge ensuite une image et, en fonction des déplacements de la souris, applique le filtre de déplacement à la partie de l’image qui est sous la souris. Les cercles dégradés utilisés pour l’image de mappage de déplacement provoquent un effet centrifuge dans la zone à laquelle le filtre est appliqué. Notez que les zones en gris de l’image de mappage du déplacement ne provoquent pas de déplacement. En effet, la valeur du gris est 0x7F7F7F. Les canaux bleu et rouge de ce niveau de gris ont donc exactement une valeur médiane, si bien qu’il n’y a pas de déplacement lorsqu’une zone grise apparaît dans l’image de mappage. Il n’y a pas non plus de déplacement au centre du cercle. Bien que cette zone ne soit pas de couleur grise, ses canaux rouge et bleu ont des valeurs identiques à celles des canaux rouge et bleu du gris moyen, et puisque le déplacement est basé sur les valeurs de bleu et de rouge, aucun déplacement n’a lieu. Filtre Shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La classe ShaderFilter vous permet d’utiliser un effet de filtre personnalisé défini en tant que shader de Pixel Bender. Parce que l’effet de filtre est écrit en tant que shader de Pixel Bender, il peut être entièrement personnalisé. Le contenu filtré est transmis au shader en tant qu’image d’entrée et le résultat de l’opération du shader devient le résultat du filtre. Remarque : le filtre Shader est pris en charge dans ActionScript à partir de Flash Player 10 et Adobe AIR 1.5. Pour appliquer un filtre Shader à un objet, vous devez commencer par créer une occurrence de Shader représentant le shader de Pixel Bender en cours d’utilisation. Pour plus d’informations concernant la procédure de création d’une occurrence de Shader et la définition d’une image d’entrée et des paramètres correspondants, voir « Utilisation des shaders de Pixel Bender » à la page 310. Lorsque vous utilisez un shader en tant que filtre, vous devez tenir compte de trois considérations importantes : • Le shader doit être défini pour accepter au moins une image d’entrée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 302 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 • L’objet filtré (objet d’affichage ou objet BitmapData auquel est appliqué le filtre) est transmis au shader en tant que première valeur d’image d’entrée. De ce fait, ne définissez pas manuellement la valeur de la première image d’entrée. • Si le shader définit plusieurs images d’entrée, les autres entrées doivent être stipulées manuellement (en définissant la propriété input de toute occurrence de ShaderInput appartenant à l’occurrence de Shader). Lorsque vous disposez d’un objet Shader pour le shader, vous créez une occurrence de ShaderFilter. Il s’agit de l’objet filtre en tant que tel utilisé comme tout autre filtre. Pour créer un élément ShaderFilter qui utilise un objet Shader, appelez le constructeur ShaderFilter() et transmettez l’objet Shader en tant qu’argument, comme illustré dans le code suivant : var myFilter:ShaderFilter = new ShaderFilter(myShader); Pour disposer d’un exemple complet d’utilisation d’un filtre Shader, voir « Utilisation d’un shader comme filtre » à la page 328. Exemple de filtrage des objets d’affichage : Filter Workbench Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple Filter Workbench comporte une interface utilisateur qui permet d’appliquer divers filtres à des images et autre contenu visuel et de voir le code résultant, qui peut être utilisé pour générer le même effet en ActionScript. Non seulement cette application fournit un outil permettant d’expérimenter avec les filtres, mais elle illustre également les techniques suivantes : • Création d’occurrences de filtres divers • Application de plusieurs filtres à un objet d’affichage Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application Filter Workbench résident dans le dossier Samples/FilterWorkbench. L’application se compose des fichiers suivants : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 303 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Fichier Description com/example/programmingas3/filterWorkbench/FilterWorkbenchController.as Classe qui fournit la principale fonctionnalité de l’application, notamment permuter le contenu auquel sont appliqués les filtres et appliquer les filtres au contenu. com/example/programmingas3/filterWorkbench/IFilterFactory.as Interface qui définit les méthodes courantes et implémentées par chacune des classes usine de filtres. Cette interface définit la fonctionnalité commune utilisée par la classe FilterWorkbenchController pour interagir avec chaque classe usine de filtres. Dans le dossier com/example/programmingas3/filterWorkbench/ : BevelFactory.as BlurFactory.as ColorMatrixFactory.as ConvolutionFactory.as DropShadowFactory.as GlowFactory.as GradientBevelFactory.as GradientGlowFactory.as Jeu de classes, dont chacune implémente l’interface IFilterFactory. Chacune de ces classes permet de créer et de définir les valeurs associées à un type unique de filtre. Les panneaux de propriétés des filtres de l’application utilisent ces classes usine pour créer des occurrences des filtres correspondants, que la classe FilterWorkbenchController extrait et applique au contenu d’image. com/example/programmingas3/filterWorkbench/IFilterPanel.as Interface qui définit les méthodes courantes et implémentées par les classes qui spécifient les panneaux de l’interface utilisateur employés pour manipuler les valeurs de filtre dans l’application. com/example/programmingas3/filterWorkbench/ColorStringFormatter.as Classe d’utilitaires qui comporte une méthode de conversion d’une valeur de couleur numérique au format chaîne hexadécimal. com/example/programmingas3/filterWorkbench/GradientColor.as Classe servant d’objet de valeur, qui combine en un objet unique les trois valeurs (couleur, alpha et rapport) associées à chaque couleur dans GradientBevelFilter et GradientGlowFilter. Interface utilisateur (Flex) FilterWorkbench.mxml Fichier principal qui définit l’interface utilisateur de l’application. flexapp/FilterWorkbench.as Classe qui assure la fonctionnalité de l’interface utilisateur de l’application principale. Elle sert de classe code-behind au fichier MXML de l’application. Dans le dossier flexapp/filterPanels : BevelPanel.mxml BlurPanel.mxml ColorMatrixPanel.mxml ConvolutionPanel.mxml DropShadowPanel.mxml GlowPanel.mxml GradientBevelPanel.mxml GradientGlowPanel.mxml Jeu de composants MXML qui assurent la fonctionnalité de chaque panneau utilisé pour définir les options d’un filtre unique. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 304 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 flexapp/ImageContainer.as Objet d’affichage qui sert de conteneur à l’image chargée à l’écran. flexapp/controls/BGColorCellRenderer.as Composant de rendu de cellule personnalisé permettant de modifier la couleur d’arrière-plan d’une cellule dans le composant DataGrid flexapp/controls/QualityComboBox.as Contrôle personnalisé qui définit une liste déroulante modifiable associée au paramètre Qualité dans plusieurs panneaux de filtre. flexapp/controls/TypeComboBox.as Contrôle personnalisé qui définit une liste déroulante modifiable associée au paramètre Type dans plusieurs panneaux de filtre. Interface utilisateur (Flash) FilterWorkbench.fla Fichier principal qui définit l’interface utilisateur de l’application. flashapp/FilterWorkbench.as Classe qui assure la fonctionnalité de l’interface utilisateur de l’application principale. Elle sert de classe de document au fichier FLA de l’application. Dans le dossier flashapp/filterPanels : BevelPanel.as BlurPanel.as ColorMatrixPanel.as ConvolutionPanel.as DropShadowPanel.as GlowPanel.as GradientBevelPanel.as GradientGlowPanel.as Jeu de classes qui assurent la fonctionnalité de chaque panneau utilisé pour définir les options d’un filtre unique. A chaque classe correspond également un symbole MovieClip dans la bibliothèque du fichier FLA de l’application principale, dont le nom est identique à celui de la classe (par exemple, le symbole « BlurPanel » est lié à la classe définie dans BlurPanel.as). Les composants de l’interface utilisateur sont placés et identifiés par nom dans ces symboles. flashapp/ImageContainer.as Objet d’affichage qui sert de conteneur à l’image chargée à l’écran. flashapp/BGColorCellRenderer.as Composant de rendu de cellule personnalisé permettant de modifier la couleur d’arrière-plan d’une cellule dans le composant DataGrid flashapp/ButtonCellRenderer.as Composant de rendu de cellule personnalisé permettant d’insérer un composant Button dans une cellule du composant DataGrid Contenu d’image filtré com/example/programmingas3/filterWorkbench/ImageType.as Cette classe sert d’objet de valeur contenant le type et l’URL d’un fichier d’image unique, dans lequel l’application peut charger et appliquer des filtres. Cette classe comporte également un jeu de constantes qui représentent les fichiers d’image en tant que tels disponibles. images/sampleAnimation.swf, images/sampleImage1.jpg, images/sampleImage2.jpg Images et autre contenu visuel auxquels sont appliqués des filtres dans l’application. Fichier Description GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 305 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Utilisation des filtres ActionScript Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application Filter Workbench est conçue pour vous aider à expérimenter avec divers effets de filtre et générer le code ActionScript approprié correspondant. Elle vous permet de sélectionner trois fichiers distincts comportant un contenu visuel, tel que des images bitmap et une animation créée par Flash et d’appliquer huit filtres ActionScript distincts à l’image sélectionnée, soit seuls, soit combinés à d’autres filtres. L’application comprend les filtres suivants : • Biseau (flash.filters.BevelFilter) • Flou (flash.filters.BlurFilter) • Matrice de couleurs (flash.filters.ColorMatrixFilter) • Convolution (flash.filters.ConvolutionFilter) • Ombre portée (flash.filters.DropShadowFilter) • Rayonnement (flash.filters.GlowFilter) • Biseau dégradé (flash.filters.GradientBevelFilter) • Rayonnement dégradé (flash.filters.GradientGlowFilter) Lorsqu’un utilisateur a sélectionné une image et un filtre à appliquer à celle-ci, l’application affiche un panneau contenant des contrôles de définition des propriétés du filtre sélectionné. Par exemple, l’image suivante illustre l’application dans laquelle est sélectionné le filtre Biseau : Lorsque l’utilisateur règle les propriétés du filtre, l’aperçu est actualisé en temps réel. L’utilisateur peut également appliquer plusieurs filtres. Pour ce faire, il personnalise un filtre, clique sur le bouton Apply, personnalise un autre filtre, clique sur le bouton Apply, et ainsi de suite. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 306 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Les panneaux de filtre de l’application proposent diverses fonctions et sont soumis à quelques limites : • Le filtre Matrice de couleurs comprend un jeu de contrôles permettant de manipuler directement des propriétés d’image courantes telles que la luminosité, les contrastes, la saturation et la teinte. Il est également possible de définir des valeurs de matrice de couleurs personnalisées. • Le filtre Convolution, qui n’est disponible qu’en ActionScript, comprend un jeu de valeurs de matrice de convolution couramment utilisées. Il est également possible de définir des valeurs personnalisées. Toutefois, bien que la classe ConvolutionFilter gère une matrice de n’importe quelle taille, l’application Filter Workbench utilise une matrice de 3 x 3 fixe, soit la taille de filtre la plus fréquemment utilisée. • Le filtre Mappage de déplacement et le filtre Shader, réservés à ActionScript, ne sont pas disponibles dans l’application Filter Workbench. Création d’occurrences de filtre Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application Filter Workbench comprend un jeu de classes, une par filtre disponible, qui sont utilisées par les divers panneaux pour créer les filtres. Lorsqu’un utilisateur sélectionne un filtre, le code ActionScript associé au panneau de filtre crée une occurrence de la classe de filtres usine appropriée. (Ces classes portent le nom de classes usine, car elles ont pour objet de créer des occurrences d’autres objets, à l’instar d’une vraie usine qui fabrique des produits). Lorsque l’utilisateur modifie la valeur d’une propriété dans le panneau, le code correspondant appelle la méthode appropriée dans la classe usine. Chaque classe usine comporte des méthodes spécifiques utilisées par le panneau pour créer l’occurrence de filtre appropriée. Par exemple, si l’utilisateur sélectionne le filtre Flou, l’application crée une occurrence de BlurFactory. La classe BlurFactory comporte une méthode modifyFilter() qui gère trois paramètres : blurX, blurY et quality. Conjointement, ces paramètres permettent de créer l’occurrence de BlurFilter requise : private var _filter:BlurFilter; public function modifyFilter(blurX:Number = 4, blurY:Number = 4, quality:int = 1):void { _filter = new BlurFilter(blurX, blurY, quality); dispatchEvent(new Event(Event.CHANGE)); } En revanche, si l’utilisateur sélectionne le filtre Convolution, celui-ci étant beaucoup plus souple, il contrôle un nombre supérieur de propriétés. Dans la classe ConvolutionFactory, le code suivant est appelé lorsque l’utilisateur sélectionne une autre valeur dans le panneau des filtres : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 307 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 private var _filter:ConvolutionFilter; public function modifyFilter(matrixX:Number = 0, matrixY:Number = 0, matrix:Array = null, divisor:Number = 1.0, bias:Number = 0.0, preserveAlpha:Boolean = true, clamp:Boolean = true, color:uint = 0, alpha:Number = 0.0):void { _filter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor, bias, preserveAlpha, clamp, color, alpha); dispatchEvent(new Event(Event.CHANGE)); } Notez que dans chaque cas, lorsque les valeurs du filtre sont modifiées, l’objet usine distribue un événement Event.CHANGE pour avertir les écouteurs de la modification. La classe FilterWorkbenchController, qui applique les filtres au contenu filtré, recherche cet événement pour s’assurer qu’elle doit extraire une nouvelle copie du filtre et l’appliquer à nouveau au contenu filtré. La classe FilterWorkbenchController n’a pas besoin de connaître les détails précis de chaque classe usine associé au filtre. Elle doit juste savoir que le filtre a été modifié et être en mesure d’accéder à une copie de ce dernier. A cet effet, l’application comporte une interface, IFilterFactory, qui définit le comportement requis d’une classe usine de filtres pour que l’occurrence de FilterWorkbenchController de l’application soit en mesure de fonctionner correctement. L’interface IFilterFactory définit la méthode getFilter() utilisée par la classe FilterWorkbenchController : function getFilter():BitmapFilter; Notez que la définition de la méthode de l’interface getFilter() stipule de renvoyer une occurrence de BitmapFilter plutôt qu’un type déterminé de filtre. La classe BitmapFilter ne définit pas de type spécifique de filtre. BitmapFilter constitue de fait la classe de base sur laquelle se fondent toutes les classes de filtre. Chaque classe usine de filtres définit une implémentation déterminée de la méthode getFilter(), dans laquelle elle renvoie une référence à l’objet filtre généré. Par exemple, une version abrégée du code source de la classe ConvolutionFactory est illustrée ci-après : public class ConvolutionFactory extends EventDispatcher implements IFilterFactory { // ------- Private vars ------- private var _filter:ConvolutionFilter; ... // ------- IFilterFactory implementation ------- public function getFilter():BitmapFilter { return _filter; } ... } Dans l’implémentation de la classe ConvolutionFactory de la méthode getFilter(), elle renvoie une occurrence de ConvolutionFilter, bien que tout objet qui appelle getFilter() ne sache pas nécessairement que, conformément à la définition de la méthode getFilter() appliquée par ConvolutionFactory, il doit renvoyer toute occurrence de BitmapFilter, soit une occurrence de n’importe quelle classe de filtre ActionScript. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 308 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 Application de filtres aux objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Comme indiqué précédemment, l’application Filter Workbench utilise une occurrence de la classe FilterWorkbenchController (appelée à partir de maintenant l’« occurrence de contrôleur »), chargée d’appliquer les filtres à l’objet visuel sélectionné. Avant que l’occurrence de contrôleur ne puisse appliquer un filtre, elle doit identifier l’image ou le contenu visuel concerné. Lorsque l’utilisateur sélectionne une image, l’application appelle la méthode setFilterTarget() de la classe FilterWorkbenchController et transmet l’une des constantes définies dans la classe ImageType : public function setFilterTarget(targetType:ImageType):void { ... _loader = new Loader(); ... _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, targetLoadComplete); ... } En se référant à ces informations, l’occurrence de contrôleur charge le fichier indiqué, puis le stocke dans une variable d’occurrence appelée _currentTarget : private var _currentTarget:DisplayObject; private function targetLoadComplete(event:Event):void { ... _currentTarget = _loader.content; ... } Lorsque l’utilisateur sélectionne un filtre, l’application appelle la méthode setFilter() de l’occurrence de contrôleur en indiquant au contrôleur une référence à l’objet Filter Factory approprié, qu’elle stocke dans une variable d’occurrence appelée _filterFactory. private var _filterFactory:IFilterFactory; public function setFilter(factory:IFilterFactory):void { ... _filterFactory = factory; _filterFactory.addEventListener(Event.CHANGE, filterChange); } Notez que, comme indiqué précédemment, l’occurrence de contrôleur ne connaît pas le type de données précis de l’occurrence de Filter Factory assigné. Elle ne sait qu’une chose, c’est que l’objet implémente l’occurrence de IFilterFactory, ce qui signifie qu’il possède une méthode getFilter() et distribue un événement change (Event.CHANGE) lorsque le filtre est modifié. Lorsque l’utilisateur modifie les propriétés d’un filtre dans le panneau des filtres, l’occurrence de contrôleur est avertie de la modification par l’événement change de Filter Factory, qui appelle la méthode filterChange() de l’occurrence de contrôleur. Cette méthode appelle alors la méthode applyTemporaryFilter() : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 309 Filtrage des objets d’affichage Dernière mise à jour le 27/4/2013 private function filterChange(event:Event):void { applyTemporaryFilter(); } private function applyTemporaryFilter():void { var currentFilter:BitmapFilter = _filterFactory.getFilter(); // Add the current filter to the set temporarily _currentFilters.push(currentFilter); // Refresh the filter set of the filter target _currentTarget.filters = _currentFilters; // Remove the current filter from the set // (This doesn't remove it from the filter target, since // the target uses a copy of the filters array internally.) _currentFilters.pop(); } L’application du filtre à l’objet d’affichage se produit au sein de la méthode applyTemporaryFilter(). Le contrôleur extrait d’abord une référence à l’objet filtre en appelant la méthode getFilter() de Filter Factory. var currentFilter:BitmapFilter = _filterFactory.getFilter(); L’occurrence de contrôleur possède une variable d’occurrence de Array appelée _currentFilters, dans laquelle elle stocke tous les filtres appliqués à l’objet d’affichage. L’étape suivante consiste à ajouter le filtre mis à jour à ce tableau : _currentFilters.push(currentFilter); Le code assigne ensuite le tableau de filtres à la propriété filters de l’objet d’affichage, qui applique à proprement parler les filtres à l’image : _currentTarget.filters = _currentFilters; Enfin, puisque le filtre appliqué en dernier demeure le filtre de « travail », il ne doit pas être appliqué à titre définitif à l’objet d’affichage. Il est donc supprimé du tableau _currentFilters : _currentFilters.pop(); Supprimer ce filtre du tableau n’affecte pas l’objet d’affichage filtré, car un objet d’affichage effectue une copie du tableau de filtres lorsqu’il est assigné à la propriété filters et utilise ce tableau interne au lieu du tableau initial. De ce fait, toute modification du tableau de filtres n’affecte pas l’objet d’affichage tant que le tableau n’a pas été à nouveau assigné à la propriété filters de l’objet d’affichage. 310 Dernière mise à jour le 27/4/2013 Chapitre 15 : Utilisation des shaders de Pixel Bender Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Adobe Pixel Bender Toolkit permet aux développeurs de composer des shaders qui créent des effets graphiques et autres. Le pseudo-code binaire Pixel Bender peut être exécuté dans ActionScript pour appliquer l’effet aux données de l’image ou au contenu visuel. L’utilisation des shaders de Pixel Bender vous donne la possibilité de créer des effets visuels personnalisés et de traiter des données au-delà des fonctions incorporées à ActionScript. Remarque : Pixel Bender est pris en charge depuis Flash Player 10 et Adobe AIR 1.5. Les fusions, filtres et remplissages Pixel Bender ne sont pas pris en charge en cas de rendu par le processeur graphique. Voir aussi Adobe Pixel Bender Technology Center Pixel Bender Developer’s Guide (disponible en anglais uniquement) Pixel Bender Reference (disponible en anglais uniquement) flash.display.Shader flash.filters.ShaderFilter Pixel Bender basics for Flash (disponible en anglais uniquement) Pixel Bender basics for Flex (disponible en anglais uniquement) Principes de base des shaders de Pixel Bender Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Adobe Pixel Bender est un langage de programmation qui permet de créer ou de manipuler un contenu d’image. Par le biais de Pixel Bender, vous créez un noyau, également appelé un shader. Le shader définit une fonction unique exécutée séparément sur chacun des pixels d’une image. Le résultat de chaque appel à la fonction est la couleur de sortie aux coordonnées de ce pixel dans l’image. Vous pouvez spécifier des valeurs de paramètre et images d’entrée pour personnaliser l’opération. Si un shader est exécuté une seule fois, les valeurs de paramètres et d’entrée sont des constantes. Les seuls éléments qui varient sont les coordonnées du pixel dont la couleur est le résultat de l’appel de la fonction. Dans la mesure du possible, la fonction shader est appelée pour plusieurs coordonnées de pixel de sortie en parallèle. Les performances du shader sont ainsi optimisées et le traitement s’avère souvent particulièrement efficace. ActionScript permet de créer facilement trois types d’effets par le biais d’un shader : • remplissage d’un dessin • mode de fondu • filtre GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 311 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Il est également possible d’exécuter un shader en mode autonome. En mode autonome, vous accédez directement au résultat d’un shader au lieu de prédéfinir l’usage prévu. Le résultat correspond à des données d’image, des données binaires ou des données numériques. Il n’est pas nécessaire que les données soient des données d’image. Vous pouvez ainsi affecter à un shader un jeu de données en entrée. Le shader traite les données et vous accédez au résultat qu’il renvoie. Pixel Bender est pris en charge depuis Flash Player version 10 et Adobe AIR version 1.5. Les fusions, filtres et remplissages Pixel Bender ne sont pas pris en charge en cas de rendu par processeur graphique. Sur un périphérique mobile, les shaders Pixel Bender sont exécutés en cas de rendu par unité centrale. Les performances ne sont toutefois pas à la hauteur de celles d’un poste de travail. De nombreux programmes de shader ne s’exécutent qu’à quelques images par seconde. Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs à la création et à l’utilisation de shaders de Pixel Bender : Noyau Pour Pixel Bender, un noyau est équivalent à un shader. Par le biais de Pixel Bender, votre code définit un noyau, qui définit une fonction unique exécutée séparément sur chacun des pixels d’une image. Pseudo-code binaire Pixel Bender Lorsqu’un noyau Pixel Bender est compilé, il est transformé en pseudo-code binaire Pixel Bender. L’accès au pseudo-code binaire et son exécution se produisent lors de l’exécution. Langage Pixel Bender Langage de programmation utilisé pour créer un noyau Pixel Bender. Pixel Bender Toolkit Application utilisée pour créer un fichier de pseudo-code binaire Pixel Bender à partir du code source Pixel Bender. Elle vous permet d’écrire, de tester et de compiler un code source Pixel Bender. Shader Dans le cadre de ce document, un shader est un jeu de fonctionnalités écrites dans le langage Pixel Bender. Le code d’un shader crée un effet visuel ou effectue un calcul. Dans les deux cas, le shader renvoie un jeu de données (il s’agit en règle générale des pixels d’une image). Le shader exécute la même opération sur chaque point de données, à l’exception des coordonnées du pixel de sortie. Le shader n’est pas écrit en ActionScript. Il est écrit dans le langage Pixel Bender et compilé en pseudo-code binaire Pixel Bender. Il peut être intégré à un fichier SWF lors de la compilation ou chargé en tant que fichier externe lors de l’exécution. Dans les deux cas, pour y accéder dans ActionScript, il est nécessaire de créer un objet Shader et de le lier au pseudo-code binaire du shader. Entrée du shader Entrée complexe, généralement composée de données d’image bitmap, fournie à un shader qui l’utilise dans ses calculs. Pour chaque variable d’entrée définie dans un shader, une valeur unique (une image unique ou un jeu de données binaires) est utilisée pour l’exécution de bout en bout du shader. Paramètre de shader Valeur unique (ou jeu de valeurs limité) fournie à un shader, qui l’utilise dans ses calculs. Chaque valeur de paramètre est définie pour une exécution de shader unique et la même valeur est utilisée de bout en bout lors de l’exécution du shader. Utilisation des exemples de code Il peut s’avérer utile de tester les exemples de code fournis. Cette opération nécessite d’exécuter le code et d’afficher les résultats dans le fichier SWF créé. Tous les exemples créent un contenu par le biais de l’API de dessin qui utilise l’effet de shader ou est modifiée par ce dernier. La plupart des exemples de code se composent de deux parties. La première partie correspond au code source Pixel Bender associé au shader utilisé dans l’exemple. Vous devez commencer par utiliser Pixel Bender Toolkit pour compiler le code source dans un fichier de pseudo-code binaire Pixel Bender. Procédez comme suit pour créer le fichier de pseudo-code binaire Pixel Bender : 1 Ouvrez Adobe Pixel Bender Toolkit. Le cas échéant, dans le menu Build (Développement), choisissez « Turn on Flash Player warnings and errors » (Activer les avertissements et erreurs Flash Player). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 312 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 2 Copiez le code Pixel Bender et collez-le dans le panneau de l’éditeur de code de Pixel Bender Toolkit. 3 Dans le menu File (Fichier), choisissez « Export kernel filter for Flash Player » (Exporter le filtre de noyau associé à Flash Player). 4 Enregistrez le fichier de pseudo-code binaire Pixel Bender dans le même répertoire que le document Flash. Le nom du fichier doit être identique à celui stipulé dans la description de l’exemple. La partie ActionScript de chaque exemple est écrite en tant que fichier de classe. Pour tester l’exemple dans Flash Professional : 1 Créez un document Flash vide et enregistrez-le sur votre ordinateur. 2 Créez un nouveau fichier ActionScript et enregistrez-le dans le même répertoire que le document Flash. Le nom du fichier doit correspondre au nom de la classe du code. Par exemple, si le code définit une classe MyApplication, enregistrez le fichier ActionScript sous le nom MyApplication.as. 3 Copiez le code dans le fichier ActionScript et enregistrez le fichier. 4 Dans le document Flash, cliquez sur une partie vide de la scène ou de l’espace de travail pour activer l’Inspecteur des propriétés du document. 5 Dans l’Inspecteur des propriétés, dans le champ Classe du document, saisissez le nom de la classe ActionScript que vous avez copiée du texte. 6 Exécutez le programme en sélectionnant Contrôle > Tester l’animation. Les résultats de l’exemple s’affichent dans la fenêtre d’aperçu. Ces techniques de test des exemples de code font l’objet d’une description détaillée dans « Utilisation des exemples de code ActionScript » à la page 1145. Chargement ou intégration d’un shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La première étape dans l’utilisation d’un shader de Pixel Bender dans ActionScript consiste à pouvoir accéder au shader en code ActionScript. Comme un shader est créé à l’aide d’Adobe Pixel Bender Toolkit et rédigé dans le langage Pixel Bender, on ne peut pas y accéder directement dans ActionScript. Il faut plutôt créer une occurrence de la classe Shader qui représente le shader de Pixel Bender à ActionScript. L’objet Shader vous permet de trouver les informations concernant le shader : par exemple, s’il prévoit de recevoir des paramètres ou des valeurs pour l’image d’entrée. Vous passez l’objet Shader aux autres objets pour utiliser effectivement le shader. Par exemple, pour utiliser le shader comme filtre, vous affectez l’objet Shader à la propriété shader d’un objet ShaderFilter. Ou bien, afin d’utiliser le shader pour remplir l’écran dans un dessin, vous passez l’objet Shader comme argument à la méthode Graphics.beginShaderFill(). Votre code ActionScript peut accéder à un shader créé par Adobe Pixel Bender Toolkit (un fichier .pbj) de deux façons distinctes : • Chargement lors de l’exécution : le fichier shader peut être chargé comme un élément externe à l’aide d’un objet URLLoader. Cette technique est comparable au chargement d’un élément externe, comme un fichier texte, par exemple. L’exemple suivant montre le chargement à l’exécution d’un fichier de pseudo-code binaire de shader et sa liaison à une occurrence de Shader : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 313 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("myShader.pbj")); var shader:Shader; function onLoadComplete(event:Event):void { // Create a new shader and set the loaded data as its bytecode shader = new Shader(); shader.byteCode = loader.data; // You can also pass the bytecode to the Shader() constructor like this: // shader = new Shader(loader.data); // do something with the shader } • Intégration au fichier SWF : le fichier shader peut être intégré au fichier SWF lors de la compilation à l’aide de la balise de métadonnées [Embed]. La balise de métadonnées [Embed] n’est disponible que si vous utilisez le kit de développement Flex pour compiler le fichier SWF. Le paramètre source de la balise [Embed] pointe vers le fichier du shader et son paramètre mimeType est "application/octet-stream", comme dans l’exemple ci-dessous : [Embed(source="myShader.pbj", mimeType="application/octet-stream")] var MyShaderClass:Class; // ... // create a shader and set the embedded shader as its bytecode var shader:Shader = new Shader(); shader.byteCode = new MyShaderClass(); // You can also pass the bytecode to the Shader() constructor like this: // var shader:Shader = new Shader(new MyShaderClass()); // do something with the shader Dans les deux cas, vous liez le pseudo-code brut du shader (la propriété URLLoader.data ou une occurrence de la classe de données [Embed]) à l’occurrence de Shader. Comme le montrent les exemples précédents, vous pouvez affecter le pseudo-code binaire à l’occurrence du shader de deux façons. Vous pouvez transmettre le pseudo-code binaire du shader sous forme d’argument au constructeur Shader(). Vous pouvez également le définir en tant que propriété byteCode de l’occurrence de Shader. Dès qu’un shader de Pixel Bender est créé et lié à l’objet Shader, vous pouvez utiliser le shader pour créer des effets de plusieurs façons. Vous pouvez l’utiliser en tant que filtre, mode de fondu, remplissage de bitmap ou comme moyen de traitement autonome d’image bitmap ou autres données. Vous pouvez également utiliser la propriété data de l’objet Shader pour accéder aux métadonnées du shader, spécifier les images d’entrée et spécifier les valeurs du paramétrage. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 314 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Accès aux métadonnées du shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Tandis qu’il crée un noyau de shader de Pixel Bender, le programmeur peut spécifier des métadonnées sur le shader dans le code source Pixel Bender. Vous pouvez inspecter le shader et extraire ses métadonnées pendant que vous l’utilisez dans ActionScript. Lorsque vous créez une occurrence de Shader et que vous la liez à un shader de Pixel Bender, un objet ShaderData, qui contient des données sur le shader, est créé et enregistré dans la propriété data de l’objet Shader. La classe ShaderData ne définit aucune de ses propres propriétés. Toutefois, lors de l’exécution, une propriété est ajoutée dynamiquement à l’objet ShaderData pour chaque valeur de métadonnées définie dans le code source du shader. Le nom attribué à chaque propriété est pareil à celui spécifié dans les métadonnées. Par exemple, supposez que le code source d’un shader de Pixel Bender contienne la définition des métadonnées suivante : namespace : "Adobe::Example"; vendor : "Bob Jones"; version : 1; description : "Creates a version of the specified image with the specified brightness."; L’objet ShaderData créé pour ce shader l’est avec les propriétés et valeurs suivantes : • namespace (String): "Adobe::Example" • vendor (String): "Bob Jones" • version (String): "1" • description (String): "Creates a version of the specified image with the specified brightness" Comme les propriétés de métadonnées sont ajoutées dynamiquement à l’objet ShaderData, vous pouvez utiliser une boucle for..in pour inspecter l’objet ShaderData. Cette technique vous permet de vous rendre compte si le shader possède des métadonnées et quelles sont ses valeurs. Outre les propriétés des métadonnées, un objet ShaderData peut avoir des propriétés représentant des entrées et des paramètres qui sont définis dans le shader. Lorsque vous utilisez une boucle for..in pour inspecter un objet ShaderData, vérifiez le type de données de chaque propriété pour vous rendre compte si la propriété est une entrée (une occurrence de ShaderInput), un paramètre (une occurrence de ShaderParameter) ou une valeur de métadonnées (une occurrence de String). L’exemple ci-dessous montre comment utiliser une boucle for..in pour examiner les propriétés dynamiques de la propriété data d’un shader. Chaque valeur de métadonnées est ajoutée à une occurrence de Vector appelée metadata. Remarquez que cet exemple suppose qu’une occurrence de Shader appelée myShader existe déjà : var shaderData:ShaderData = myShader.data; var metadata:Vector. = new Vector.(); for (var prop:String in shaderData) { if (!(shaderData[prop] is ShaderInput) && !(shaderData[prop] is ShaderParameter)) { metadata[metadata.length] = shaderData[prop]; } } // do something with the metadata Pour une version de cet exemple, qui extrait également des entrées et des paramètres de shader, voir « Identification des entrées et des paramètres d’un shader » à la page 315. Pour plus d’informations sur les propriétés des entrées et des paramètres, voir « Spécification des valeurs des entrées et des paramètres d’un shader » à la page 315. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 315 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Spécification des valeurs des entrées et des paramètres d’un shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures De nombreux shaders de Pixel Bender sont définis pour faire appel à une ou plusieurs images utilisées au cours de son traitement. Par exemple, il est courant pour un shader d’accepter une image source et de la produire dotée d’un effet particulier. Suivant l’utilisation du shader, soit la valeur d’entrée est spécifiée automatiquement, soit il faut en fournir une. De la même façon, de nombreux shaders spécifient des paramètres utilisés dans l’individualisation de ce qu’ils produisent. Il faut également définir explicitement une valeur pour chaque paramètre avant d’utiliser le shader. Vous utilisez la propriété data de l’objet Shader pour définir les entrées et les paramètres et pour établir si un shader en particulier prévoit des entrées et des paramètres. La propriété data est une occurrence de ShaderData. Identification des entrées et des paramètres d’un shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La première étape dans la spécification de valeurs d’entrée et de paramètres d’un shader consiste à savoir si celui que vous utilisez prévoit de recevoir des images d’entrée ou des paramètres. Chaque occurrence de Shader possède une propriété data qui contient un objet ShaderData. Si le shader spécifie des entrées ou des paramètres, on y accède en tant que propriétés de cet objet ShaderData. Les noms des propriétés correspondent aux noms spécifiés dans le code source du shader pour les entrées et les paramètres. Par exemple, si un shader spécifie une entrée appelée src, l’objet ShaderData possède une propriété appelée src qui représente cette entrée. Chaque propriété qui représente une entrée est une occurrence de ShaderInput et chaque propriété qui représente un paramètre est une occurrence de ShaderParameter. Idéalement, le programmeur du shader fournit une documentation pour le shader afin de décrire quels sont les paramètres et les valeurs de l’image d’entrée qu’il prévoit, ce qu’ils représentent, les valeurs appropriées, et ainsi de suite. Toutefois, si le shader n’est pas documenté et que vous ne disposez pas du code source, vous pouvez inspecter les données du shader pour identifier ces entrées et paramètres. Les propriétés qui représentent ces entrées et paramètres sont ajoutées dynamiquement à l’objet ShaderData. Par conséquent, vous pouvez utiliser une boucle for..in pour inspecter l’objet ShaderData afin de savoir si le shader qui lui est associé spécifie de tels entrées ou paramètres. Comme le décrit la section « Accès aux métadonnées du shader » à la page 314, on accède également, en tant que propriété dynamique ajoutée à la propriété Shader.data, à toute valeur de métadonnées définie pour un shader. Lorsque vous utilisez cette technique afin d’identifier entrées et paramètres, vérifiez le type de données des propriétés dynamiques. Si une propriété est une occurrence de ShaderInput, elle représente une entrée. S’il s’agit d’une occurrence de ShaderParameter, elle représente un paramètre. Sinon, il s’agit d’une valeur de métadonnées. L’exemple ci-dessous montre comment utiliser une boucle for..in pour examiner les propriétés dynamiques de la propriété data d’un shader. Chaque entrée (objet ShaderInput) est ajoutée à une occurrence de Vector appelée inputs. Chaque paramètre (objet ShaderParameter) est ajouté à une occurrence de Vector appelée parameters. Enfin, toute propriété de métadonnées est ajoutée à une occurrence de Vector appelée metadata. Remarquez que cet exemple suppose qu’une occurrence de Shader appelée myShader existe déjà : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 316 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 var shaderData:ShaderData = myShader.data; var inputs:Vector. = new Vector.(); var parameters:Vector. = new Vector.(); var metadata:Vector. = new Vector.(); for (var prop:String in shaderData) { if (shaderData[prop] is ShaderInput) { inputs[inputs.length] = shaderData[prop]; } else if (shaderData[prop] is ShaderParameter) { parameters[parameters.length] = shaderData[prop]; } else { metadata[metadata.length] = shaderData[prop]; } } // do something with the inputs or properties Spécification des valeurs d’entrée d’un shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures De nombreux shaders prévoient de recevoir une ou plusieurs images d’entrée qui sont utilisées au cours de son traitement. Toutefois, dans nombre de cas, une entrée est automatiquement spécifiée lorsque l’objet Shader est utilisé. Par exemple, supposons qu’un shader ait besoin d’une entrée et qu’il serve de filtre. Lorsque le filtre est appliqué à un objet d’affichage ou BitmapData, cet objet est défini automatiquement comme entrée. Dans ce cas, on ne spécifie pas explicitement une valeur d’entrée. Toutefois, dans certains cas, et plus particulièrement si un shader spécifie plusieurs entrées, il faut définir explicitement une valeur pour l’entrée. Toute entrée définie dans un shader est représentée dans ActionScript par un objet ShaderInput. L’objet ShaderInput est une propriété de l’occurrence de ShaderData dans la propriété data de l’objet Shader (voir « Identification des entrées et des paramètres d’un shader » à la page 315). Par exemple, supposons qu’un shader définisse une entrée appelée src et qu’il soit lié à un objet Shader appelé myShader. Vous accédez alors à l’objet ShaderInput qui correspond à l’entrée src à l’aide de l’identifiant suivant : myShader.data.src Chaque objet ShaderInput possède une propriété input qui est utilisée pour définir la valeur de l’entrée. On définit la propriété input sur une occurrence de BitmapData pour spécifier des données d’image. On peut aussi définir la propriété input sur BitmapData ou Vector.occurrence de pour spécifier des données binaires ou des nombres. Pour plus d’informations sur l’utilisation d’une occurrence de BitmapData ou Vector. en entrée et les restrictions correspondantes, voir ShaderInput.input dans le Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 317 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 En plus de la propriété input, un objet ShaderInput possède des propriétés qui peuvent être utilisées pour déterminer quel type d’image prévoit l’entrée. Ces propriétés contiennent elles-mêmes les propriétés width, height et channels. Chaque objet ShaderInput possède également une propriété index qui est utile afin de déterminer si une valeur explicite doit être fournie pour l’entrée. Si un shader prévoit de recevoir davantage d’entrées que le nombre fixé automatiquement, vous pouvez alors définir des valeurs pour ces entrées. Pour plus de détails sur les différentes façons d’utiliser un shader et pour savoir si oui ou non les valeurs d’entrée sont fixées automatiquement, voir « Utilisation d’un shader » à la page 320. Spécification des valeurs de paramètres dans un shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Certains shaders définissent des valeurs de paramètres qu’ils utilisent dans la création de leur résultat. Par exemple, un shader qui modifie la luminosité d’une image pourrait spécifier un paramètre de luminosité qui détermine dans quelle mesure l’opération affecte cette luminosité. Un paramètre unique défini dans un shader peut prévoir une ou plusieurs valeurs suivant la façon dont il a été spécifié dans le shader. Tout paramètre défini dans un shader est représenté dans ActionScript par un objet ShaderParameter. L’objet ShaderParameter est une propriété de l’occurrence de ShaderData dans la propriété des données de l’objet Shader. Une description se trouve dans la section « Identification des entrées et des paramètres d’un shader » à la page 315. Par exemple, supposons qu’un shader qui définit un paramètre appelé luminosité soit représenté par un objet Shader appelé myShader. Vous accédez alors à l’objet ShaderParameter correspondant au paramètre luminosité à l’aide de l’identifiant suivant : myShader.data.brightness Pour spécifier une ou plusieurs valeurs pour le paramètre, créez un tableau ActionScript contenant la ou les valeurs et affectez-le à la propriété value de l’objet ShaderParameter. La propriété value est définie en tant qu’occurrence d’Array car il est possible qu’un seul paramètre du shader nécessite plusieurs valeurs. Même si le paramètre du shader ne prévoit qu’une seule valeur, il vous faut placer la valeur dans un objet Array pour l’affecter à la propriété ShaderParameter.value. Le code suivant montre comment définir une seule valeur pour la propriété value. myShader.data.brightness.value = [75]; Si le code source Pixel Bender pour le shader spécifie une valeur par défaut pour le paramètre, un tableau contenant la ou les valeurs par défaut est créé et affecté à la propriété value de l’objet ShaderParameter lorsque l’objet Shader est créé. Dès qu’un tableau est affecté à la propriété value, même s’il s’agit de celui par défaut, la valeur du paramètre peut être modifiée en changeant la valeur de l’élément du tableau. Il n’est pas nécessaire de créer un autre tableau et de l’affecter à la propriété value. L’exemple ci-dessous indique comment définir une valeur de paramètre dans un shader avec ActionScript. Dans cet exemple, le shader définit un paramètre appelé color. Ce paramètre color est déclaré en tant que variable float4 dans le code source Pixel Bender, ce qui signifie qu’il s’agit d’un tableau à quatre nombres en virgule flottante. Dans l’exemple, la valeur du paramètre color change constamment. A chaque changement, le shader est utilisé pour dessiner un rectangle coloré à l’écran. Il en résulte un changement de couleur animé. Remarque : le code de cet exemple a été rédigé par Ryan Taylor. Merci Ryan de bien vouloir nous en faire profiter. Vous pouvez accéder aux exemples de Ryan et lire ses commentaires à l’adresse www.boostworthy.com/. Le code ActionScript repose sur l’utilisation de trois méthodes : • init() : dans la méthode init(), le code charge le fichier de pseudo-code binaire Pixel Bender contenant le shader. Lors du chargement du fichier, la méthode onLoadComplete() est appelée. • onLoadComplete() : dans la méthode onLoadComplete(), le code crée l’objet Shader appelé shader. Il crée également une occurrence de Sprite appelée texture. Dans la méthode renderShader(), le code dessine une fois par image le résultat du shader dans texture. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 318 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 • onEnterFrame() : la méthode onEnterFrame() est appelée une fois par image, créant ainsi un effet d’animation. Dans cette méthode, le code définit la valeur du paramètre du shader sur la nouvelle couleur, puis appelle la méthode renderShader() pour dessiner le résultat du shader sous forme de rectangle. • renderShader() : dans la méthode renderShader(), le code appelle la méthode Graphics.beginShaderFill() pour définir un remplissage de shader. Il dessine ensuite un rectangle dont le remplissage est défini par la sortie du shader (la couleur générée). Pour plus d’informations sur ce type d’utilisation d’un shader, voir « Utilisation d’un shader comme outil de remplissage de dessin » à la page 320. Vous trouverez ci-dessous le code ActionScript associé à cet exemple : Utilisez cette classe en tant que classe d’application principale d’un projet ActionScript uniquement dans Flash Builder, ou en tant que classe de document du fichier FLA dans Flash Professional : package { import flash.display.Shader; import flash.display.Sprite; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; public class ColorFilterExample extends Sprite { private const DELTA_OFFSET:Number = Math.PI * 0.5; private var loader:URLLoader; private var shader:Shader; private var texture:Sprite; private var delta:Number = 0; public function ColorFilterExample() { init(); } private function init():void { loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("ColorFilter.pbj")); } private function onLoadComplete(event:Event):void { shader = new Shader(loader.data); texture = new Sprite(); addChild(texture); addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(event:Event):void { GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 319 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 shader.data.color.value[0] = 0.5 + Math.cos(delta - DELTA_OFFSET) * 0.5; shader.data.color.value[1] = 0.5 + Math.cos(delta) * 0.5; shader.data.color.value[2] = 0.5 + Math.cos(delta + DELTA_OFFSET) * 0.5; // The alpha channel value (index 3) is set to 1 by the kernel's default // value. This value doesn't need to change. delta += 0.1; renderShader(); } private function renderShader():void { texture:graphics.clear(); texture.graphics.beginShaderFill(shader); texture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight); texture.graphics.endFill(); } } } Vous trouverez ci-dessous le code source du noyau du shader ColorFilter, utilisé pour la création du fichier « ColorFilter.pbj » de pseudo-code binaire Pixel Bender. kernel ColorFilter < namespace : "boostworthy::Example"; vendor : "Ryan Taylor"; version : 1; description : "Creates an image where every pixel has the specified color value."; > { output pixel4 result; parameter float4 color < minValue:float4(0, 0, 0, 0); maxValue:float4(1, 1, 1, 1); defaultValue:float4(0, 0, 0, 1); >; void evaluatePixel() { result = color; } } Si vous utilisez un shader dont les paramètres ne sont pas documentés, c’est par le contrôle de la propriété type de l’objet ShaderParameter que vous pouvez évaluer le nombre d’éléments et leur type qu’il faut inclure dans le tableau. La propriété type indique le type de données du paramètre tel qu’il est défini dans le shader lui-même. Pour consulter la liste du nombre et du type d’éléments prévus par chaque type de paramètre, voir le code associé à la propriété ShaderParameter.value dans le Guide de référence ActionScript 3.0 pour Flash Professional. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 320 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Chaque objet ShaderParameter possède également une propriété index qui indique l’emplacement du paramètre dans l’ordre des paramètres du shader. En plus de ces propriétés, un objet ShaderParameter peut avoir des propriétés supplémentaires qui contiennent des valeurs de métadonnées fournies par le programmeur du shader. Par exemple, le programmeur peut définir pour un paramètre des valeurs de métadonnées telles que minimum, maximum et des valeurs par défaut. Toutes les valeurs de métadonnées spécifiées par le programmeur sont ajoutées à l’objet ShaderParameter en tant que propriétés dynamiques. Pour passer en revue ces propriétés, utilisez une boucle for..in pour boucler dans les propriétés dynamiques de l’objet ShaderParameter afin d’identifier ses métadonnées. L’exemple ci-dessous montre comment utiliser une boucle for..in afin d’identifier les métadonnées d’un objet ShaderParameter. Chaque valeur de métadonnées est ajoutée à une occurrence de Vector appelée metadata. Remarquez que cet exemple suppose qu’une occurrence de Shader appelée myShader existe déjà et qu’elle possède un paramètre appelé brightness. var brightness:ShaderParameter = myShader.data.brightness; var metadata:Vector. = new Vector.(); for (var prop:String in brightness) { if (brightness[prop] is String) { metadata[metadata.length] = brightness[prop]; } } // do something with the metadata Utilisation d’un shader Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Dès qu’un shader de Pixel Bender est disponible dans ActionScript en tant qu’objet Shader, il peut être utilisé de différentes façons : • Remplissage d’un dessin par le shader : le shader spécifie quelle portion d’une forme dessinée utilise l’api du dessin • Mode de fondu : le shader spécifie le degré de fondu entre deux objets d’affichage superposés • Filtre : le shader définit un filtre qui modifie l’apparence du contenu visuel • Traitement d’un shader autonome : le traitement du shader se fait sans définir l’usage de la sortie. Sur demande, le shader peut tourner en arrière-plan de telle sorte que le résultat devient disponible à la fin du traitement. Cette technique peut être utilisée pour générer des données bitmap et traiter des données non visuelles. Utilisation d’un shader comme outil de remplissage de dessin Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Si vous utilisez un shader pour créer un remplissage de dessin, vous faites appel aux méthodes de l’API de dessin pour créer une forme vectorielle. La sortie du shader permet de remplir la forme, à l’instar de toute image bitmap utilisée en tant que remplissage de bitmap par l’API de dessin. Pour créer un remplissage de dessin, appelez la méthode beginShaderFill() de l’objet Graphics à l’emplacement du code où vous souhaitez commencer à dessiner la forme. Transmettez l’objet Shader en tant que premier argument à la méthode beginShaderFill(), comme illustré dans le code suivant : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 321 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 var canvas:Sprite = new Sprite(); canvas.graphics.beginShaderFill(myShader); canvas.graphics.drawRect(10, 10, 150, 150); canvas.graphics.endFill(); // add canvas to the display list to see the result Lorsque vous utilisez un shader en tant qu’outil de remplissage de dessin, vous définissez les valeurs d’image d’entrée et de paramètre requises par le shader. L’exemple suivant illustre l’utilisation d’un shader en tant qu’outil de remplissage de dessin. Dans cet exemple, le shader crée un dégradé à trois sommets. Ce dégradé possède trois couleurs, une par sommet d’un triangle, séparées des autres par un fondu dégradé. En outre, les couleurs pivotent pour créer un effet de rotation de couleur animé. Remarque : le code de cet exemple a été rédigé par Petri Leskinen. Merci Petri de bien vouloir nous en faire profiter. Vous pouvez consulter d’autres exemples et didacticiels rédigés par Petri à l’adresse http://pixelero.wordpress.com/. Le code ActionScript réside dans trois méthodes : • init() : la méthode init() est appelée lors du chargement de l’application. Dans cette méthode, le code définit les valeurs initiales des objets Point qui représentent les sommets du triangle. Il crée également une occurrence de Sprite appelée canvas. Ultérieurement, dans la méthode updateShaderFill(), le code dessine une fois par image le résultat du shader dans canvas. Enfin, le code charge le fichier de pseudo-code binaire du shader. • onLoadComplete() : dans la méthode onLoadComplete(), le code crée l’objet Shader appelé shader. Il définit également les valeurs initiales des paramètres. Enfin, le code ajoute la méthode updateShaderFill() en tant qu’écouteur de l’événement enterFrame, ce qui signifie qu’il est appelé une fois par image pour créer un effet animé. • onEnterFrame() : la méthode updateShaderFill() est appelée une fois par image, ce qui crée l’effet d’animation. Dans cette méthode, le code calcule et définit les valeurs des paramètres du shader. Il appelle ensuite la méthode beginShaderFill() pour créer un remplissage de shader et appelle d’autres méthodes de l’API de dessin pour dessiner le résultat du shader dans un triangle. Vous trouverez ci-dessous le code ActionScript associé à cet exemple : Utilisez cette classe en tant que classe d’application principale d’un projet ActionScript uniquement dans Flash Builder, ou en tant que classe de document d’un fichier FLA dans Flash Professional : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 322 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 package { import flash.display.Shader; import flash.display.Sprite; import flash.events.Event; import flash.geom.Point; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; public class ThreePointGradient extends Sprite { private var canvas:Sprite; private var shader:Shader; private var loader:URLLoader; private var topMiddle:Point; private var bottomLeft:Point; private var bottomRight:Point; private var colorAngle:Number = 0.0; private const d120:Number = 120 / 180 * Math.PI; // 120 degrees in radians public function ThreePointGradient() { init(); } private function init():void { canvas = new Sprite(); addChild(canvas); var size:int = 400; topMiddle = new Point(size / 2, 10); bottomLeft = new Point(0, size - 10); bottomRight = new Point(size, size - 10); loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("ThreePointGradient.pbj")); } private function onLoadComplete(event:Event):void { shader = new Shader(loader.data); shader.data.point1.value = [topMiddle.x, topMiddle.y]; shader.data.point2.value = [bottomLeft.x, bottomLeft.y]; shader.data.point3.value = [bottomRight.x, bottomRight.y]; addEventListener(Event.ENTER_FRAME, updateShaderFill); } private function updateShaderFill(event:Event):void GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 323 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 { colorAngle += .06; var c1:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle); var c2:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle + d120); var c3:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle - d120); shader.data.color1.value = [c1, c2, c3, 1.0]; shader.data.color2.value = [c3, c1, c2, 1.0]; shader.data.color3.value = [c2, c3, c1, 1.0]; canvas.graphics.clear(); canvas.graphics.beginShaderFill(shader); canvas.graphics.moveTo(topMiddle.x, topMiddle.y); canvas.graphics.lineTo(bottomLeft.x, bottomLeft.y); canvas.graphics.lineTo(bottomRight.x, bottomLeft.y); canvas.graphics.endFill(); } } } Le code source du noyau du shader ThreePointGradient, utilisé pour la création du fichier « ThreePointGradient.pbj » de pseudo-code binaire Pixel Bender, est indiqué ci-dessous : kernel ThreePointGradient < namespace : "Petri Leskinen::Example"; vendor : "Petri Leskinen"; version : 1; description : "Creates a gradient fill using three specified points and colors."; > { parameter float2 point1 // coordinates of the first point < minValue:float2(0, 0); maxValue:float2(4000, 4000); defaultValue:float2(0, 0); >; parameter float4 color1 // color at the first point, opaque red by default < defaultValue:float4(1.0, 0.0, 0.0, 1.0); >; parameter float2 point2 // coordinates of the second point < minValue:float2(0, 0); maxValue:float2(4000, 4000); defaultValue:float2(0, 500); >; parameter float4 color2 // color at the second point, opaque green by default < defaultValue:float4(0.0, 1.0, 0.0, 1.0); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 324 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 >; parameter float2 point3 // coordinates of the third point < minValue:float2(0, 0); maxValue:float2(4000, 4000); defaultValue:float2(0, 500); >; parameter float4 color3 // color at the third point, opaque blue by default < defaultValue:float4(0.0, 0.0, 1.0, 1.0); >; output pixel4 dst; void evaluatePixel() { float2 d2 = point2 - point1; float2 d3 = point3 - point1; // transformation to a new coordinate system // transforms point 1 to origin, point2 to (1, 0), and point3 to (0, 1) float2x2 mtrx = float2x2(d3.y, -d2.y, -d3.x, d2.x) / (d2.x * d3.y - d3.x * d2.y); float2 pNew = mtrx * (outCoord() - point1); // repeat the edge colors on the outside pNew.xy = clamp(pNew.xy, 0.0, 1.0); // set the range to 0.0 ... 1.0 // interpolating the output color or alpha value dst = mix(mix(color1, color2, pNew.x), color3, pNew.y); } } Remarque : si vous utilisez un remplissage de shader alors que le rendu est exécuté par le processeur graphique, la zone remplie s’affiche en cyan. Pour plus d’informations sur le tracé de forme par le biais de l’API de dessin, voir « Utilisation de l’API de dessin » à la page 230. Utilisation d’un shader comme mode de fondu Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Utiliser un shader comme mode de fondu s’apparente à l’utilisation des autres modes de fondu. Le shader définit le résultat de deux objets d’affichage fondus visuellement. Pour utiliser un shader en tant que mode de fondu, affectez à votre objet Shader la propriété blendShader de l’objet d’affichage en premier plan. Affecter une valeur autre que null à la propriété blendShader définit automatiquement la propriété blendMode de l’objet d’affichage sur BlendMode.SHADER. Le code suivant illustre l’utilisation d’un shader en tant que mode de fondu. Notez que cet exemple part du principe qu’un objet d’affichage appelé foreground figure dans le même parent que l’autre contenu d’affichage dans la liste d’affichage, sachant que foreground chevauche l’autre contenu : foreground.blendShader = myShader; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 325 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Lorsque vous utilisez un shader en tant que mode de fondu, deux entrées au moins doivent être spécifiées. Comme indiqué dans l’exemple, vous ne définissez pas les valeurs d’entrée dans le code. Les deux images fondues sont automatiquement utilisées en tant qu’entrées du shader. L’image en premier-plan fait office de seconde image (c’est à cet objet d’affichage qu’est appliqué le mode de fondu). Une image d’arrière-plan est créée à partir du composite de tous les pixels figurant derrière le cadre de sélection de l’image en premier-plan. Cette image en arrière-plan est définie comme la première image d’entrée. Si vous utilisez un shader qui attend plus de deux entrées, vous en indiquez la valeur à partir de la troisième entrée. L’exemple suivant illustre l’utilisation d’un shader en tant que mode de fondu. Cet exemple utilise un mode de fondu Eclaircir basé sur la luminosité. Ce fondu a pour résultat d’afficher le pixel le plus clair de l’un ou l’autre des objets fondus. Remarque : le code de cet exemple a été rédigé par Mario Klingemann. Merci Mario de bien vouloir nous en faire profiter. Pour consulter d’autres exemples de code rédigés par Mario, ainsi que ses commentaires, voir www.quasimondo.com/. Le code ActionScript important figure dans les deux méthodes suivantes : • init() : la méthode init() est appelée lors du chargement de l’application. Dans cette méthode, le code charge le fichier de pseudo-code binaire du shader. • onLoadComplete() : dans la méthode onLoadComplete(), le code crée l’objet Shader appelé shader. Il dessine ensuite trois objets. Le premier, backdrop, est un arrière-plan gris foncé placé derrière les objets fondus. Le deuxième, backgroundShape, est une ellipse dégradée verte. Le troisième, foregroundShape, est une ellipse dégradée orange. L’ellipse foregroundShape est l’objet de premier plan du fondu. L’image d’arrière-plan du fondu est composée de la section de backdrop et de la section de backgroundShape qui sont recouvertes par le cadre de sélection de l’objet foregroundShape. L’objet foregroundShape est affiché en première position dans la liste d’affichage. Il recouvre partiellement backgroundShape et totalement backdrop. En raison de ce chevauchement, sans application d’un mode de fondu, l’ellipse orange (foregroundShape) est entièrement affichée et masque une section de l’ellipse verte (backgroundShape) : Toutefois, si le mode de fondu est affiché, la section la plus lumineuse de l’ellipse verte est visible, car elle est plus claire que la section de foregroundShape qui la recouvre : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 326 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Vous trouverez ci-dessous le code ActionScript associé à cet exemple : Utilisez cette classe en tant que classe d’application principale d’un projet ActionScript uniquement dans Flash Builder, ou en tant que classe de document du fichier FLA dans Flash Professional : package { import flash.display.BlendMode; import flash.display.GradientType; import flash.display.Graphics; import flash.display.Shader; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.geom.Matrix; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; public class LumaLighten extends Sprite { private var shader:Shader; private var loader:URLLoader; public function LumaLighten() { init(); } private function init():void { loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("LumaLighten.pbj")); } private function onLoadComplete(event:Event):void { shader = new Shader(loader.data); var backdrop:Shape = new Shape(); var g0:Graphics = backdrop.graphics; g0.beginFill(0x303030); g0.drawRect(0, 0, 400, 200); g0.endFill(); addChild(backdrop); var backgroundShape:Shape = new Shape(); var g1:Graphics = backgroundShape.graphics; var c1:Array = [0x336600, 0x80ff00]; var a1:Array = [255, 255]; var r1:Array = [100, 255]; var m1:Matrix = new Matrix(); m1.createGradientBox(300, 200); g1.beginGradientFill(GradientType.LINEAR, c1, a1, r1, m1); g1.drawEllipse(0, 0, 300, 200); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 327 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 g1.endFill(); addChild(backgroundShape); var foregroundShape:Shape = new Shape(); var g2:Graphics = foregroundShape.graphics; var c2:Array = [0xff8000, 0x663300]; var a2:Array = [255, 255]; var r2:Array = [100, 255]; var m2:Matrix = new Matrix(); m2.createGradientBox(300, 200); g2.beginGradientFill(GradientType.LINEAR, c2, a2, r2, m2); g2.drawEllipse(100, 0, 300, 200); g2.endFill(); addChild(foregroundShape); foregroundShape.blendShader = shader; foregroundShape.blendMode = BlendMode.SHADER; } } } Le code source du noyau du shader LumaLighten, utilisé pour la création du fichier « LumaLighten.pbj » de pseudocode binaire Pixel Bender, est indiqué ci-dessous : kernel LumaLighten < namespace : "com.quasimondo.blendModes"; vendor : "Quasimondo.com"; version : 1; description : "Luminance based lighten blend mode"; > { input image4 background; input image4 foreground; output pixel4 dst; const float3 LUMA = float3(0.212671, 0.715160, 0.072169); void evaluatePixel() { float4 a = sampleNearest(foreground, outCoord()); float4 b = sampleNearest(background, outCoord()); float luma_a = a.r * LUMA.r + a.g * LUMA.g + a.b * LUMA.b; float luma_b = b.r * LUMA.r + b.g * LUMA.g + b.b * LUMA.b; dst = luma_a > luma_b ? a : b; } } Pour plus d’informations sur l’utilisation des modes de fondu, voir « Application de modes de fondu » à la page 193. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 328 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Remarque : lorsqu’un programme shader Pixel Bender est exécuté en tant que fusion dans Flash Player ou AIR, les fonctions d’échantillonnage et outCoord() ne se comportent pas comme dans les autres contextes. En mode de fusion, une fonction d’échantillonnage renvoie toujours le pixel en cours d’évaluation par le shader. Il est, par exemple, impossible d’ajouter un décalage à outCoord() pour échantillonner un pixel environnant. De même, si vous utilisez la fonction outCoord() dans un contexte autre qu’une fonction d’échantillonnage, ses coordonnées renvoient toujours 0. Il est ainsi impossible de se baser sur la position d’un pixel pour affecter la combinaison des images fusionnées. Utilisation d’un shader comme filtre Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Utiliser un shader comme filtre s’apparente à l’utilisation de tout autre filtre dans ActionScript. Lorsque vous utilisez un shader en tant que filtre, l’image filtrée (un objet d’affichage ou un objet BitmapData) est transmise au shader. Le shader utilise l’image d’entrée pour créer le résultat du filtre, qui correspond généralement à une version modifiée de l’image d’origine. Si l’objet filtré est un objet d’affichage, le résultat du filtre remplace l’objet d’affichage filtré à l’écran. Si l’objet filtré est un objet BitmapData, le résultat du shader devient le contenu de l’objet BitmapData dont la méthode applyFilter() est appelée. Pour utiliser un shader en tant que filtre, vous commencez par créer l’objet Shader, comme indiqué à la section « Chargement ou intégration d’un shader » à la page 312. Vous créez ensuite un objet ShaderFilter lié à l’objet Shader. L’objet ShaderFilter est le filtre appliqué à l’objet filtré. Vous l’appliquez à un objet à l’instar de n’importe quel filtre. Vous le transmettez à la propriété filters d’un objet d’affichage ou vous appelez la méthode applyFilter() sur un objet BitmapData. Par exemple, le code suivant crée un objet ShaderFilter et applique le filtre à un objet d’affichage appelé homeButton. var myFilter:ShaderFilter = new ShaderFilter(myShader); homeButton.filters = [myFilter]; Lorsque vous utilisez un shader en tant que filtre, une entrée au moins doit lui être associée. Comme indiqué dans l’exemple, vous ne définissez pas la valeur d’entrée dans le code. L’objet d’affichage filtré ou l’objet BitmapData est défini en tant qu’image d’entrée. Si vous utilisez un shader qui attend plus d’une entrée, vous en spécifiez la valeur à partir de la deuxième entrée. Dans certains cas, un filtre modifie les dimensions de l’image d’origine. Un effet d’ombre portée standard ajoute par exemple des pixels contenant l’ombre associée à l’image. Lorsque vous utilisez un shader qui modifie les dimensions de l’image, définissez les propriétés leftExtension, rightExtension, topExtension et bottomExtension pour indiquer l’écart approprié. L’exemple suivant illustre l’utilisation d’un shader en tant que filtre. Dans cet exemple, le filtre inverse les valeurs des canaux rouge, vert et bleu d’une image. Il a pour résultat un « négatif » de l’image. Remarque : cet exemple utilise comme shader le noyau invertRGB.pbk Pixel Bender intégré à Pixel Bender Toolkit. Vous pouvez charger le code source du noyau à partir du répertoire d’installation de Pixel Bender Toolkit. Compilez le code source, puis enregistrez le fichier de pseudo-code binaire dans le même répertoire que le code source. Le code ActionScript important figure dans les deux méthodes suivantes : • init() : la méthode init() est appelée lors du chargement de l’application. Dans cette méthode, le code charge le fichier de pseudo-code binaire du shader. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 329 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 • onLoadComplete() : dans la méthode onLoadComplete(), le code crée l’objet Shader appelé shader. Il crée et dessine ensuite le contenu d’un objet appelé target. L’objet target est un rectangle rempli d’un dégradé linéaire rouge sur la gauche, jaune-vert au centre et bleu sur la droite. Si le filtre n’est pas appliqué, l’apparence de l’objet est la suivante : Si le filtre est appliqué, les couleurs sont inversées, auquel cas l’apparence du rectangle est la suivante : Ce code utilise à titre de shader le noyau « invertRGB.pbk » Pixel Bender d’exemple intégré à Pixel Bender Toolkit. Le code source figure dans le fichier « invertRGB.pbk », qui réside dans le répertoire d’installation de Pixel Bender Toolkit. Compilez le code source et enregistrez le fichier de pseudo-code binaire sous le nom « invertRGB.pbj » dans le même répertoire que votre code source ActionScript. Vous trouverez ci-dessous le code ActionScript associé à cet exemple : Utilisez cette classe en tant que classe d’application principale d’un projet ActionScript uniquement dans Flash Builder, ou en tant que classe de document du fichier FLA dans Flash Professional : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 330 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 package { import flash.display.GradientType; import flash.display.Graphics; import flash.display.Shader; import flash.display.Shape; import flash.display.Sprite; import flash.filters.ShaderFilter; import flash.events.Event; import flash.geom.Matrix; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; public class InvertRGB extends Sprite { private var shader:Shader; private var loader:URLLoader; public function InvertRGB() { init(); } private function init():void { loader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.BINARY; loader.addEventListener(Event.COMPLETE, onLoadComplete); loader.load(new URLRequest("invertRGB.pbj")); } private function onLoadComplete(event:Event):void { shader = new Shader(loader.data); var target:Shape = new Shape(); addChild(target); var g:Graphics = target.graphics; var c:Array = [0x990000, 0x445500, 0x007799]; var a:Array = [255, 255, 255]; var r:Array = [0, 127, 255]; var m:Matrix = new Matrix(); m.createGradientBox(w, h); g.beginGradientFill(GradientType.LINEAR, c, a, r, m); g.drawRect(10, 10, w, h); g.endFill(); var invertFilter:ShaderFilter = new ShaderFilter(shader); target.filters = [invertFilter]; } } } Pour plus d’informations sur l’application de filtres, voir « Création et application de filtres » à la page 277. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 331 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Utilisation d’un shader en mode autonome Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Lorsque vous utilisez un shader en mode autonome, son traitement s’exécute indépendamment de l’usage prévu du résultat. Vous spécifiez le shader à exécuter, définissez les valeurs d’entrée et de paramètres, puis stipulez un objet dans lequel seront placées les données résultantes. Vous pouvez utiliser un shader en mode autonome pour deux raisons : • Traitement de données non graphiques : en mode autonome, vous pouvez choisir de transmettre des données binaires ou numériques arbitraires au shader au lieu de données d’image bitmap. Le cas échéant, le résultat du shader peut être renvoyé sous forme de données binaires ou numériques en plus des données d’image bitmap. • Traitement en arrière-plan : lorsque vous exécutez un shader en mode autonome, il est exécuté en mode asynchrone par défaut. Cela signifie que le shader s’exécute en arrière-plan pendant que votre application continue à tourner et que votre code est averti une fois le traitement du shader terminé. Vous pouvez utiliser un shader sans pour autant bloquer l’interface utilisateur de l’application ou tout autre traitement, même si la durée de son exécution est élevée. Un objet ShaderJob permet d’exécuter un shader en mode autonome. Vous commencez par créer un objet ShaderJob et vous le liez à l’objet Shader qui représente le shader à exécuter : var job:ShaderJob = new ShaderJob(myShader); Vous définissez ensuite toute valeur d’entrée ou de paramètre attendue par le shader. Si vous exécutez le shader en arrière-plan, vous enregistrez également un écouteur associé à l’événement complete de l’objet ShaderJob. Votre écouteur est appelé lorsque le shader termine sa tâche : function completeHandler(event:ShaderEvent):void { // do something with the shader result } job.addEventListener(ShaderEvent.COMPLETE, completeHandler); Vous créez ensuite un objet dans lequel est écrit le résultat de l’opération du shader, une fois celle-ci terminée. Vous affectez cet objet à la propriété target de l’objet ShaderJob : var jobResult:BitmapData = new BitmapData(100, 75); job.target = jobResult; Affectez une occurrence de BitmapData à la propriété target si vous utilisez l’objet ShaderJob pour exécuter le traitement de l’image. Si vous traitez des données binaires ou numériques, affectez un objet ByteArray ou une occurrence de Vector. à la propriété target. Si tel est le cas, vous devez définir les propriétés width et height de l’objet ShaderJob pour stipuler le volume de données à créer dans l’objet target. Remarque : vous pouvez définir les propriétés shader, target,width et height de l’objet ShaderJob en une seule étape. Pour ce faire, transmettez les arguments au constructeur ShaderJob(), comme suit :var job:ShaderJob = new ShaderJob(myShader, myTarget, myWidth, myHeight);. Lorsque vous êtes prêt à exécuter le shader, vous appelez la méthode start() de l’objet ShaderJob : job.start(); Par défaut, appeler start() entraîne l’exécution asynchrone de l’objet ShaderJob. Dans ce cas, l’exécution du programme continue et passe immédiatement à la ligne suivante de code au lieu d’attendre que le shader soit terminé. Une fois l’opération du shader terminée, l’objet ShaderJob appelle ses écouteurs d’événement complete et les avertit. A ce stade (en d’autres termes, dans le corps de votre écouteur d’événement complete), l’objet target contient le résultat de l’opération du shader. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 332 Utilisation des shaders de Pixel Bender Dernière mise à jour le 27/4/2013 Remarque : au lieu d’utiliser l’objet propriété target, vous pouvez extraire directement le résultat du shader de l’objet événement qui est transmis à la méthode d’écouteur. L’objet événement est une occurrence de ShaderEvent. L’objet ShaderEvent possède trois propriétés susceptibles d’être utilisées pour accéder au résultat, selon le type de données de l’objet défini en tant que propriété target : ShaderEvent.bitmapData, ShaderEvent.byteArray et ShaderEvent.vector. Vous pouvez également transmettre un argument true à la méthode start(). Dans ce cas, l’opération du shader s’exécute en mode synchrone. Tout le code (y compris l’interaction avec l’interface utilisateur et tout autre événement) est interrompu pendant l’exécution du shader. Une fois le shader terminé, l’objet target en contient le résultat et le programme passe à la ligne de code suivante. job.start(true); 333 Dernière mise à jour le 27/4/2013 Chapitre 16 : Utilisation des clips Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe MovieClip est la classe de base des animations et des symboles de clip créés dans l’environnement de développement Adobe® Flash®. Elle possède tous les comportements et toutes les fonctionnalités des objets d’affichage, mais intègre des propriétés et méthodes supplémentaires qui permettent de contrôler son scénario. Principes de base des clips Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les clips sont un élément capital pour les créateurs de contenu animé dans l’environnement de création Flash et pour contrôler ce contenu avec ActionScript. Lorsque vous créez un symbole de clip dans Flash, le programme ajoute ce symbole à la bibliothèque du document Flash. Par défaut, ce symbole devient une occurrence de la classe MovieClip et, de ce fait, possède les propriétés et méthodes de cette classe. Lorsqu’une occurrence d’un symbole de clip est placée sur la scène, la progression du scénario de ce clip s’effectue automatiquement (si le clip comporte plusieurs images), sauf si cette lecture est modifiée en ActionScript. Le scénario est l’élément distinctif de la classe MovieClip. Il permet de créer des animations par interpolation de mouvement ou de forme via l’interface de Flash. Par contre, un objet d’affichage issu de la classe Sprite peut uniquement être animé par programmation, en modifiant ses valeurs. Dans les versions précédentes d’ActionScript, la classe MovieClip constituait la classe de base de toutes les occurrences de la scène. En ActionScript 3.0, un clip est désormais un objet d’affichage parmi d’autres, tous susceptibles de s’afficher à l’écran. S’il n’est pas nécessaire de définir un scénario pour la fonction d’un objet d’affichage, l’utilisation de la classe Shape au lieu de la classe MovieClip peut accroître les performances d’affichage. Pour plus d’informations sur le choix des objets d’affichage en fonction de la tâche prévue, voir « Sélection d’une sous-classe de DisplayObject » à la page 179. Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs aux clips : Fichier SWF AVM1 Fichier SWF créé en ActionScript 1.0 ou ActionScript 2.0, et généralement destiné aux versions 8 ou antérieures de Flash Player. Fichier SWF AVM2 Fichier SWF créé en ActionScript 3.0 pour Adobe Flash Player 9 ou ultérieur ou Adobe AIR. Fichier SWF externe Fichier SWF créé séparément du fichier SWF du projet, et destiné à être chargé et lu dans celui-ci. Image Elément de base du scénario. Comme les images de films, chaque image est une « photographie » et c’est la lecture rapide des images en séquence qui produit l’effet d’animation. Scénario Métaphore représentant la série d’images qui composent la séquence d’animation d’un clip. Le scénario d’un objet MovieClip est l’équivalent du scénario de cet objet dans l’environnement de création Flash. Tête de lecture Marqueur identifiant la position (l’image) dans le scénario qui est affichée à un moment donné. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 334 Utilisation des clips Dernière mise à jour le 27/4/2013 Utilisation des objets MovieClip Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsque vous publiez un fichier SWF, Flash convertit toutes les occurrences de symboles de clips sur la scène en objets MovieClip. Pour qu’un symbole de clip soit disponible en ActionScript, donnez-lui un nom d’occurrence dans le champ Nom de l’occurrence de l’Inspecteur des Propriétés. Lors de la création du fichier SWF, Flash génère le code qui crée l’occurrence de MovieClip sur la scène et déclare une variable avec ce nom d’occurrence. Si les clips que vous avez nommés sont imbriqués dans d’autres clips nommés, ces clips enfant sont traités comme des propriétés du clip parent : vous pouvez accéder à tous les clips de cette hiérarchie en utilisant la syntaxe à point. Par exemple, si une occurrence de clip appelée childClip est imbriquée dans une autre appelée parentClip, vous pouvez lancer sa lecture en appelant le code suivant : parentClip.childClip.play(); Remarque : les occurrences enfant placées sur la scène dans l’outil de programmation de Flash ne sont pas accessibles par le code depuis l’intérieur du constructeur d’une occurrence parent car, à ce stade de l’exécution du code, elles n’ont pas été créées. Avant d’accéder à l’enfant, le parent doit soit créer l’occurrence enfant par du code, soit retarder l’accès à une fonction de rappel qui écoute l’enfant en vue de la distribution de son événement Event.ADDED_TO_STAGE. Si de nombreuses méthodes et propriétés de la classe MovieClip d’ActionScript 2.0 restent les mêmes, d’autres ont changé. Toutes les propriétés qui étaient préfixées d’un trait de soulignement ont été renommées. Par exemple, les propriétés _width et _height sont désormais accessibles sous le nom width et height, _xscale et _yscale sous le nomscaleX et scaleY. Pour obtenir la liste complète des propriétés et méthodes de la classe MovieClip, voir le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Contrôle de la lecture d’un clip Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Flash utilise la métaphore du scénario pour traduire une animation ou un changement d’état. Tout élément visuel qui a recours à un scénario est soit un objet MovieClip, soit une extension de la classe MovieClip. Bien qu’il soit possible en ActionScript de commander l’arrêt ou la lecture d’un clip et le passage à un autre point du scénario, il n’est pas possible de créer dynamiquement un scénario ni d’ajouter du contenu dans une image spécifique. Seul l’outil de programmation Flash le permet. Pendant la lecture, le clip progresse le long du scénario à une vitesse fixée par la cadence d’image du fichier SWF. Vous pouvez également ignorer ce paramètre et le remplacer par la propriété Stage.frameRate dans ActionScript. Lecture et arrêt des clips Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les méthodes play() et stop() permettent d’effectuer des manipulations simples sur un clip tout au long du scénario. Par exemple, supposons qu’un symbole de clip sur la scène contienne une animation représentant une bicyclette qui traverse l’écran, et dont le nom d’occurrence est bicycle. Si le code suivant est associé à une image-clé du scénario principal, bicycle.stop(); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 335 Utilisation des clips Dernière mise à jour le 27/4/2013 la bicyclette ne se déplace pas (son animation n’est pas mise en lecture). Le mouvement de la bicyclette peut être déclenché par une action de l’utilisateur. Par exemple, avec un bouton nommé startButton, le code suivant (dans une image-clé du scénario principal) déclenche l’animation si l’utilisateur clique sur ce bouton : // This function will be called when the button is clicked. It causes the // bicycle animation to play. function playAnimation(event:MouseEvent):void { bicycle.play(); } // Register the function as a listener with the button. startButton.addEventListener(MouseEvent.CLICK, playAnimation); Avance rapide et rembobinage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les méthodes play() et stop() ne sont pas les seules méthodes commandant l’animation d’un clip. Vous pouvez également avancer et reculer manuellement la tête de lecture à l’aide des méthodes nextFrame() et prevFrame(). L’appel de l’une de ces deux méthodes arrête la lecture et fait avancer le clip ou le rembobine d’une image. L’utilisation de la méthode play() revient à appeler nextFrame() chaque fois qu’un événement enterFrame est déclenché pour cet objet clip. Vous pouvez donc envisager de lire le clip bicycle en arrière en ajoutant un écouteur pour l’événement enterFrame et en indiquant à bicycle, dans la fonction écouteur, de reculer d’une image, comme suit : // This function is called when the enterFrame event is triggered, meaning // it's called once per frame. function everyFrame(event:Event):void { if (bicycle.currentFrame == 1) { bicycle.gotoAndStop(bicycle.totalFrames); } else { bicycle.prevFrame(); } } bicycle.addEventListener(Event.ENTER_FRAME, everyFrame); En lecture normale, si un clip contient plusieurs images, il tourne en boucle lors de la lecture, c’est-à-dire qu’il revient à l’image 1 une fois qu’il a passé la dernière image. Si vous utilisez prevFrame() ou nextFrame(), ce comportement ne se produit pas automatiquement (l’appel de prevFrame() lorsque la tête de lecture est sur l’image 1 ne déplace pas la tête de lecture à la dernière image). Dans l’exemple ci-dessus, la condition if vérifie si le clip est revenu à la première image et fait alors passer le clip à la dernière image, créant ainsi une boucle continue de lecture en arrière. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 336 Utilisation des clips Dernière mise à jour le 27/4/2013 Déplacement vers une autre image et utilisation des étiquettes d’image Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le déplacement d’un clip à une nouvelle image est une opération simple. Il suffit d’appeler gotoAndPlay() ou gotoAndStop() en spécifiant le numéro de l’image cible comme paramètre. Vous pouvez également transmettre une chaîne correspondant au nom de l’étiquette d’image. Il est possible d’attribuer une étiquette à toute image du scénario. Pour ce faire, sélectionnez une image du scénario, puis tapez un nom dans le champ Etiquette d’image de l’Inspecteur des Propriétés. L’utilisation des étiquettes d’image plutôt que des numéros présente des avantages évidents pour créer un clip complexe. Si le nombre d’images, de calques et d’interpolations d’une animation est élevé, envisagez d’étiqueter les images importantes de manière évocatrice, en faisant référence aux changements de comportement dans le clip (par exemple « départ », « marche » ou « course »). Cette technique permet d’améliorer la lisibilité du code et offre plus de souplesse, puisque les appels ActionScript destinés à une image étiquetée pointent sur une référence uniquement (l’étiquette) plutôt que sur une image numérotée. Si vous décidez par la suite de déplacer un segment de l’animation vers une autre image, il ne sera pas nécessaire de modifier le code ActionScript si vous conservez les mêmes étiquettes pour toutes les images au nouvel emplacement. Pour représenter des étiquettes en code, ActionScript 3.0 comporte la classe FrameLabel. Chaque occurrence de cette classe représente une étiquette d’image unique, et possède une propriété name qui représente le nom de l’étiquette tel qu’il a été indiqué dans l’Inspecteur des Propriétés, ainsi qu’une propriété frame qui représente le numéro de l’image pour laquelle l’étiquette est placée dans le scénario. Pour permettre d’accéder aux occurrences de FrameLabel associées à une occurrence de clip, la classe MovieClip comporte deux propriétés qui renvoient directement des objets FrameLabel. La propriété currentLabels renvoie un tableau composé de tous les objets FrameLabel présents sur l’ensemble du scénario d’un clip. La propriété currentLabel renvoie une chaîne contenant le nom de l’étiquette d’image trouvée récemment sur le scénario. Supposons que vous ayez créé un clip nommé Robot et que vous ayez étiqueté les différents états de l’animation. Vous pouvez définir une condition pour vérifier la propriété currentLabel afin d’accéder à l’état actuel de Robot, comme dans le code suivant : if (robot.currentLabel == "walking") { // do something } Flash Player 11.3 et AIR 3.3 ont ajouté l’événement frameLabel à la classe FrameLabel. Vous pouvez affecter un gestionnaire d’événement à l’occurrence de FrameLabel qui représente l’étiquette d’une trame. L’événement est distribué lorsque la tête de lecture accède à la trame. L’exemple suivant crée une occurrence de FrameLabel pour la seconde étiquette de trame dans l’objet Array des étiquettes de trames du MovieClip. Il enregistre ensuite un gestionnaire d’événement pour l’événement frameLabel : var myFrameLabel:FrameLabel = robot.currentLabels[1]; myFrameLabel.addEventListener(Event.FRAME_LABEL, onFrameLabel); function onFrameLabel(e:Event):void { //do something } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 337 Utilisation des clips Dernière mise à jour le 27/4/2013 Utilisation des séquences Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans l’environnement de création Flash, vous pouvez utiliser les séquences pour démarquer une série de scénarios qu’un fichier SWF doit suivre. Grâce au second paramètre de la méthode gotoAndPlay() ou gotoAndStop(), vous pouvez spécifier la séquence sur laquelle la tête de lecture doit se placer. Tous les fichiers FLA commencent par une séquence, à laquelle vous pouvez ajouter le nombre de séquences de votre choix. L’utilisation des séquences n’est pas toujours conseillée, car elle présente un certain nombre d’inconvénients. La maintenance d’un document Flash qui contient de nombreuses séquences peut être difficile, en particulier dans les environnements où plusieurs auteurs interviennent. Un nombre élevé de séquences peut également s’avérer inefficace de point de vue de la bande passante, car le processus de publication implique la fusion de toutes les séquences en un seul scénario. L’ensemble des séquences est alors téléchargé en mode progressif, même si elles ne sont jamais lues. C’est pourquoi l’utilisation de plusieurs séquences est largement déconseillée, à moins qu’elle soit nécessaire à l’organisation de plusieurs animations basées sur des scénarios. La propriété scenes de la classe MovieClip renvoie un tableau des objets Scene représentant toutes les séquences du fichier SWF. La propriété currentScene renvoie un objet Scene représentant la séquence qui est en cours de lecture. La classe Scene a des propriétés qui contiennent des informations sur la séquence. La propriété labels renvoie un tableau des objets FrameLabel utilisés au sein de la séquence. La propriété name renvoie le nom de la séquence sous forme de chaîne. La propriété numFrames renvoie un entier représentant le nombre total d’images dans la séquence. Création d’objets MovieClip à l’aide d’ActionScript Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’ajout de contenu s’effectue dans Flash en faisant glisser des éléments de la bibliothèque sur la scène. Mais il ne s’agit pas là de la seule méthode. Pour des projets plus complexes, les développeurs expérimentés préfèrent souvent créer les clips par programmation. Cette approche présente plusieurs avantages : réutilisation facile du code, vitesse de compilation accrue et disponibilité de modifications plus sophistiquées réservées à ActionScript. La nouvelle API de liste d’affichage d’ActionScript 3.0 simplifie le processus de création dynamique d’objets MovieClip. La possibilité d’instancier directement une occurrence de MovieClip, séparément de son ajout à la liste d’affichage, offre beaucoup de souplesse et de simplicité sans sacrifier tout contrôle. En ActionScript 3.0, lorsqu’une occurrence de clip (ou de tout autre objet d’affichage) est créée par code, elle est invisible tant qu’elle n’a pas été ajoutée à la liste d’affichage à l’aide de la méthode addChild() ou addChildAt() d’un conteneur d’objets d’affichage Vous pouvez ainsi créer un clip et définir ses propriétés, et même appeler ses méthodes, avant qu’il apparaisse à l’écran. Pour plus d’informations sur l’utilisation de la liste d’affichage, voir « Utilisation de conteneurs d’objets d’affichage » à la page 165. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 338 Utilisation des clips Dernière mise à jour le 27/4/2013 Exportation des symboles de bibliothèque pour ActionScript Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Par défaut, il est impossible de créer dynamiquement des occurrences de symboles de clips dans la bibliothèque d’un document Flash (c’est-à-dire de les créer entièrement en ActionScript). En effet, l’exportation de chaque symbole pour une utilisation en ActionScript accroît la taille du fichier SWF. Or, les symboles ne sont pas tous destinés à une utilisation sur la scène. C’est pourquoi, pour qu’un symbole soit disponible en ActionScript, vous devez indiquer spécifiquement que ce symbole doit être exporté pour ActionScript. Pour exporter un symbole pour ActionScript : 1 Sélectionnez le symbole dans le panneau Bibliothèque et ouvrez sa boîte de dialogue Propriétés. 2 Si nécessaire, activez les paramètres avancés. 3 Dans la boîte de dialogue Liaison, activez l’option Exporter pour ActionScript. Les champs Classe et Classe de base sont alors activés. Par défaut, le champ Classe contient le nom du symbole sans espaces (par exemple, un symbole nommé « Maison Rouge » devient « MaisonRouge »). Pour spécifier que le symbole doit utiliser une classe personnalisée pour son comportement, saisissez le nom complet de cette classe, package compris. Si vous voulez avoir la possibilité de créer des occurrences du symbole en ActionScript, sans avoir pour autant besoin de comportements supplémentaires, vous pouvez laisser ce nom de classe tel quel. Par défaut, le champ Classe de base a la valeur flash.display.MovieClip. Si vous voulez que votre symbole étende les fonctionnalités d’une autre classe personnalisée, vous pouvez remplacer cette valeur par le nom de votre classe, sous réserve que celle-ci étende la classe Sprite (ou MovieClip). 4 Cliquez sur OK pour enregistrer les changements. A ce stade, si Flash ne détecte pas de fichier ActionScript externe contenant la définition de la classe spécifiée (par exemple, si vous n’avez pas besoin d’ajouter un comportement supplémentaire pour le symbole), un message d’avertissement apparaît : Le chemin de classe ne contient pas de définition pour cette classe. Une définition sera générée automatiquement dans le fichier SWF lors de l’exportation. Vous pouvez ignorer cet avertissement si le symbole de bibliothèque ne nécessite pas de fonctionnalités en dehors de celles de la classe MovieClip. Si vous n’indiquez aucune classe pour votre symbole, Flash crée pour lui une classe du type de celle-ci : package { import flash.display.MovieClip; public class ExampleMovieClip extends MovieClip { public function ExampleMovieClip() { } } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 339 Utilisation des clips Dernière mise à jour le 27/4/2013 Si vous ne souhaitez pas ajouter des fonctionnalités ActionScript au symbole, ajoutez les propriétés et méthodes nécessaires à la structure de code suivante. Supposons par exemple que vous disposez d’un symbole de clip contenant un cercle de 50 pixels de diamètre, dont le paramètre de liaison est Exporter pour ActionScript et dont la classe est Circle. Le code suivant, lorsqu’il est placé dans un fichier Circle.as, étend la classe MovieClip et fournit au symbole les méthodes supplémentaires getArea() et getCircumference() : package { import flash.display.MovieClip; public class Circle extends MovieClip { public function Circle() { } public function getArea():Number { // The formula is Pi times the radius squared. return Math.PI * Math.pow((width / 2), 2); } public function getCircumference():Number { // The formula is Pi times the diameter. return Math.PI * width; } } } Le code suivant, placé dans une image-clé à l’image 1 du document Flash, crée une occurrence du symbole et l’affiche à l’écran : var c:Circle = new Circle(); addChild(c); trace(c.width); trace(c.height); trace(c.getArea()); trace(c.getCircumference()); Ce code montre comment utiliser l’instanciation ActionScript au lieu de faire glisser des actifs individuels vers la scène. Il crée un cercle qui présente toutes les propriétés d’un clip et possède les méthodes personnalisées définies dans votre classe Circle. Il s’agit d’un exemple tout à fait élémentaire ; un symbole de bibliothèque peut spécifier un nombre illimité de propriétés et de méthodes dans sa classe. L’instanciation en ActionScript est un processus puissant, car il permet de créer dynamiquement de nombreuses occurrences qu’il serait particulièrement laborieux de créer manuellement. Elle vous apporte en outre une grande souplesse, puisque vous pouvez personnaliser les propriétés de chaque occurrence dès sa création. Pour saisir l’importance de ces avantages, vous pouvez utiliser une boucle pour créer dynamiquement plusieurs occurrences de Circle. Après avoir ajouté le symbole Circle et la classe correspondante, décrits précédemment, dans la bibliothèque de votre document Flash, placez le code suivant dans une image-clé à l’image 1 : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 340 Utilisation des clips Dernière mise à jour le 27/4/2013 import flash.geom.ColorTransform; var totalCircles:uint = 10; var i:uint; for (i = 0; i < totalCircles; i++) { // Create a new Circle instance. var c:Circle = new Circle(); // Place the new Circle at an x coordinate that will space the circles // evenly across the Stage. c.x = (stage.stageWidth / totalCircles) * i; // Place the Circle instance at the vertical center of the Stage. c.y = stage.stageHeight / 2; // Change the Circle instance to a random color c.transform.colorTransform = getRandomColor(); // Add the Circle instance to the current timeline. addChild(c); } function getRandomColor():ColorTransform { // Generate random values for the red, green, and blue color channels. var red:Number = (Math.random() * 512) - 255; var green:Number = (Math.random() * 512) - 255; var blue:Number = (Math.random() * 512) - 255; // Create and return a ColorTransform object with the random colors. return new ColorTransform(1, 1, 1, 1, red, green, blue, 0); } Cet exemple illustre la rapidité avec laquelle vous pouvez créer et personnaliser plusieurs occurrences d’un symbole à l’aide de code. Chaque occurrence est positionnée en fonction du compteur de boucle. Ensuite une couleur lui est attribuée au hasard à l’aide de la propriété transform (dont Circle hérite en étendant la classe MovieClip). Chargement d’un fichier SWF externe Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures En ActionScript 3.0, les fichiers SWF sont chargés avec la classe Loader. Pour charger un fichier SWF externe, vous devez définir quatre étapes en ActionScript : 1 Créer un objet URLRequest avec l’adresse URL du fichier. 2 Créer un objet Loader. 3 Appeler la méthode load() de l’objet Loader en lui passant en paramètre l’occurrence de l’objet URLRequest. 4 Appeler la méthode addChild() pour un conteneur d’objet d’affichage (par exemple le scénario principal d’un document Flash) afin d’ajouter l’occurrence de Loader à la liste d’affichage Le code final se présente ainsi : var request:URLRequest = new URLRequest("http://www.[yourdomain].com/externalSwf.swf"); var loader:Loader = new Loader() loader.load(request); addChild(loader); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 341 Utilisation des clips Dernière mise à jour le 27/4/2013 Le même code peut être utilisé pour charger un fichier image externe (image JPEG, GIF ou PNG) en spécifiant l’adresse URL de ce fichier à la place de celle d’un fichier SWF. Contrairement à un fichier image, un fichier SWF peut contenir du code ActionScript. Ainsi, bien que le processus de chargement d’un fichier SWF soit identique à celui d’une image, le fichier SWF à l’origine du chargement et le fichier SWF chargé doivent se trouver dans le même sandbox de sécurité si vous souhaitez utiliser ActionScript pour communiquer avec le fichier SWF externe. En outre, si ce fichier externe contient des classes qui partagent le même espace de noms que les classes du fichier SWF qui le charge, il peut s’avérer nécessaire de créer un domaine d’application pour le fichier chargé afin d’éviter d’éventuels conflits d’espace de nom. Pour plus d’informations sur la sécurité et le domaine d’application, voir « Utilisation de domaines d’application » à la page 152 et « Chargement de contenu » à la page 1104. Une fois que le fichier SWF externe est chargé, il devient accessible via la propriété Loader.content. Si ce fichier est publié en ActionScript 3.0, il s’agira soit d’un clip, soit d’un sprite, selon la classe qu’il étend. Il existe quelques différences entre le chargement d’un fichier SWF dans Adobe AIR pour iOS et le chargement dans d’autres plates-formes. Pour plus d’informations, voir « Chargement de fichiers SWF dans AIR pour iOS » à la page 209. Considérations relatives au chargement de fichiers SWF de version ancienne Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si un fichier SWF externe a été publié dans une version antérieure d’ActionScript, il faut tenir compte de restrictions importantes. Contrairement à un fichier SWF ActionScript 3.0 qui s’exécute dans AVM2 (ActionScript Virtual Machine 2), un fichier SWF publié en ActionScript 1.0 ou 2.0 s’exécute dans AVM1 (ActionScript Virtual Machine 1). Le chargement d’un fichier SWF ActionScript 1.0 ou 2.0 dans un fichier SWF ActionScript 3.0 présente d’importantes différences par rapport au chargement d’un fichier SWF ActionScript 3.0. Flash Player garantit une compatibilité totale avec les versions précédentes et les contenus publiés antérieurement. Tout contenu qui s’exécute dans les versions antérieures de Flash Player s’exécute dans les versions de Flash Player qui gèrent ActionScript 3.0. Tenez cependant compte des restrictions suivantes : • Le code ActionScript 3.0 peut charger un fichier SWF écrit en ActionScript 1.0 ou 2.0. Lorsque le chargement d’un fichier SWF ActionScript 1.0 ou 2.0 aboutit, l’objet chargé (la propriété Loader.content ) est un objet AVM1Movie. Une occurrence d’AVM1Movie n’est pas identique à une occurrence de MovieClip. C’est un objet d’affichage qui, contrairement à un clip, ne comporte pas de méthodes ni de propriétés liées au scénario. Le fichier SWF AVM2 parent ne peut pas accéder aux propriétés, méthodes ou objets de l’objet AVM1Movie chargé. • Les fichiers SWF écrits en ActionScript 1.0 ou 2.0 ne peuvent pas charger les fichiers SWF écrits en ActionScript 3.0. Cela signifie que les fichiers SWF créés dans Flash 8, Flex Builder 1.5 ou une version antérieure ne peuvent pas charger les fichiers SWF écrits en ActionScript 3.0. Il existe une seule exception à cette règle : un fichier SWF écrit en ActionScript 2.0 peut être remplacé par un fichier SWF écrit en ActionScript 3.0, sous réserve que le fichier écrit en ActionScript 2.0 n’ait effectué aucun chargement à quelque niveau que ce soit. Pour ce faire, le fichier SWF écrit en ActionScript 2.0 doit appeler loadMovieNum() et transmettre la valeur 0 au paramètre level. • En règle générale, les fichiers SWF écrits en ActionScript 1.0 ou 2.0 doivent faire l’objet d’une migration pour fonctionner conjointement avec des fichiers SWF écrits en ActionScript 3.0. Supposons, par exemple, que vous ayez créé un lecteur multimédia avec ActionScript 2.0. Ce lecteur multimédia charge des contenus divers également créés en ActionScript 2.0. Il est impossible de créer un contenu en ActionScript 3.0 et de le charger dans le lecteur multimédia. Vous devez effectuer une migration du lecteur vers ActionScript 3.0. Néanmoins, si vous créez un lecteur multimédia en ActionScript 3.0, il peut effectuer de simples chargements de votre contenu en ActionScript 2.0. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 342 Utilisation des clips Dernière mise à jour le 27/4/2013 Le tableau ci-après récapitule les limites des versions précédentes de Flash Player relatives au chargement de contenus plus récents et à l’exécution de code, ainsi que les restrictions liées à la programmation croisée entre les fichiers SWF écrits en différentes versions d’ActionScript. Dans le tableau ci-dessous, « Fonctionnalité prise en charge » fait référence au contenu lisible dans Flash Player 9 ou une version ultérieure. Le contenu lisible dans Flash Player version 8 ou antérieure peut être chargé, affiché, exécuté et programmé avec ActionScript 1.0 et 2.0 uniquement. Exemple de clip : RuntimeAssetsExplorer Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La fonctionnalité Exporter pour ActionScript présente des avantages particuliers lorsque des bibliothèques peuvent être réutilisées sur plusieurs projets. Si Flash Player ou AIR exécute un fichier SWF, les symboles ayant été exportés dans ActionScript sont disponibles pour tous les fichiers SWF au sein du même sandbox de sécurité que le fichier SWF qui le charge. De cette manière, un seul document Flash peut générer un fichier SWF destiné uniquement à accueillir des éléments graphiques. Cette technique est très utile pour les grands projets dans lesquels les concepteurs graphiques chargés des éléments visuels peuvent travailler en parallèle avec les développeurs qui créent une « enveloppe » SWF qui chargera les fichiers SWF des éléments graphiques au moment de l’exécution. Cette méthode peut vous servir dans la maintenance d’un ensemble de versions de fichiers dans lesquelles les actifs graphiques ne sont pas dépendants du développement de la programmation. L’application RuntimeAssetsExplorer charge tout fichier SWF qui est une sous-classe de RuntimeAsset et permet de consulter les éléments disponibles de ce fichier SWF. Cet exemple illustre les points suivants : • Chargement d’un fichier SWF externe à l’aide de Loader.load() • Création dynamique d’un symbole de bibliothèque exporté pour ActionScript • Contrôle de la lecture du MovieClip avec ActionScript Avant de commencer, notez que tous les fichiers SWF devant s’exécuter dans Flash Player doivent se trouver dans le même sandbox de sécurité. Pour plus d’informations, voir « Sandbox de sécurité » à la page 1087. Pour obtenir les fichiers d’application associés à cet exemple, téléchargez les exemples Flash Professional. Les fichiers de l’application RuntimeAssetsExplorer se trouvent dans le dossier Samples/Chapters/RuntimeAssetsExplorer. L’application se compose des fichiers suivants : Fonctionnalité prise en charge Flash Player 7 Flash Player 8 Flash Player 9 et 10 Peut charger les fichiers SWF pour version 7 et antérieure version 8 et antérieure version 9 (ou 10) et antérieure Machine virtuelle incluse AVM1 AVM1 AVM1 et AVM2 Exécute les fichiers SWF écrits en ActionScript 1.0 et 2.0 1.0 et 2.0 1.0, 2.0 et 3.0 Fonctionnalité prise en charge Contenu créé en ActionScript 1.0 et 2.0 Contenu créé en ActionScript 3.0 Peut charger du contenu et exécuter le code de contenus créé dans ActionScript 1.0 et 2.0 uniquement ActionScript 1.0 et 2.0 et ActionScript 3.0 Peut programmer le contenu créé dans ActionScript 1.0 et 2.0 uniquement (ActionScript 3.0 via LocalConnection) ActionScript 1.0 et 2.0 via LocalConnection ActionScript 3.0 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 343 Utilisation des clips Dernière mise à jour le 27/4/2013 Etablissement de l’interface de bibliothèque d’exécution Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour que l’explorateur interagisse convenablement avec une bibliothèque SWF, la structure des bibliothèques d’éléments doit être formalisée. Pour ce faire, nous allons créer une interface, que l’on pourrait comparer à une classe dans la mesure où elle représente un modèle de définition des méthodes qui définissent une structure attendue. Par contre, à l’inverse d’une classe, elle ne comporte pas les corps des méthodes. L’interface est un moyen de communication pour la bibliothèque d’éléments et l’explorateur. Chaque fichier SWF d’éléments chargé dans le navigateur implémentera cette interface. Pour plus d’informations sur l’utilité des interfaces, voir Interfaces dans Formation à ActionScript 3.0. L’interface RuntimeLibrary est très simple, puisque nous avons uniquement besoin d’une fonction qui fournisse à l’explorateur un tableau de chemins de classe pour les symboles à exporter disponibles dans la bibliothèque. Cette interface utilise pour ce faire une seule méthode : getAssets(). package com.example.programmingas3.runtimeassetexplorer { public interface RuntimeLibrary { function getAssets():Array; } } Fichier Description RuntimeAssetsExample.mxml ou RuntimeAssetsExample.fla Interface utilisateur de l’application pour Flex (MXML) ou Flash (FLA). RuntimeAssetsExample.as Classe document pour l’application Flash (FLA). GeometricAssets.as Classe exemple qui implémente l’interface RuntimeAsset. GeometricAssets.fla Fichier FLA lié à la classe GeometricAssets (classe de document du fichier FLA) contenant les symboles exportés pour ActionScript. com/example/programmingas3/runtimeassetexplorer/RuntimeLibrary.as Interface qui définit les méthodes attendues par tous les fichiers SWF d’actifs d’exécution qui seront chargés dans l’explorateur. com/example/programmingas3/runtimeassetexplorer/AnimatingBox.as Classe du symbole de bibliothèque dont la forme est un rectangle pivotant. com/example/programmingas3/runtimeassetexplorer/AnimatingStar.as Classe du symbole de bibliothèque dont la forme est une étoile pivotante. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 344 Utilisation des clips Dernière mise à jour le 27/4/2013 Création de fichiers SWF de bibliothèque d’actifs Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La définition de l’interface RuntimeLibrary permet de créer plusieurs fichiers SWF de bibliothèque d’actifs, qui pourront être chargés dans un autre fichier SWF. L’élaboration d’une bibliothèque SWF d’actifs repose sur quatre tâches : • Création d’une classe pour le fichier SWF de bibliothèque d’actifs • Création de classes pour les différents éléments contenus dans la bibliothèque • Création des éléments graphiques eux-mêmes • Association des éléments graphiques à des classes et publication du fichier SWF de bibliothèque Création d’une classe pour implémenter l’interface RuntimeLibrary Nous allons ensuite créer la classe GeometricAssets qui implémente l’interface RuntimeLibrary, et sera la classe du document FLA. Le code de cette classe est très proche de celui de l’interface RuntimeLibrary, la différence étant que la définition de classe comporte le corps de la méthode getAssets(). package { import flash.display.Sprite; import com.example.programmingas3.runtimeassetexplorer.RuntimeLibrary; public class GeometricAssets extends Sprite implements RuntimeLibrary { public function GeometricAssets() { } public function getAssets():Array { return [ "com.example.programmingas3.runtimeassetexplorer.AnimatingBox", "com.example.programmingas3.runtimeassetexplorer.AnimatingStar" ]; } } } Si nous devions créer une deuxième bibliothèque d’exécution, nous pourrions créer un autre fichier FLA reposant sur une autre classe (AnimationAssets, par exemple) qui assure sa propre implémentation de getAssets(). Création de classes pour chaque élément MovieClip Pour les besoins de cet exemple, nous étendrons simplement la classe MovieClip, sans ajouter de fonctionnalité aux éléments. Le code suivant destiné à AnimatingStar est semblable à celui de AnimatingBox : package com.example.programmingas3.runtimeassetexplorer { import flash.display.MovieClip; public class AnimatingStar extends MovieClip { public function AnimatingStar() { } } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 345 Utilisation des clips Dernière mise à jour le 27/4/2013 Publication de la bibliothèque Nous allons maintenant relier les actifs de classe MovieClip à la nouvelle classe en créant un fichier FLA et en entrant GeometricAssets dans le champ Classe du document de l’Inspecteur des propriétés. Pour les besoins de cet exemple, nous allons créer deux formes très simples qui utilisent une interpolation de scénario pour effectuer une rotation horaire sur 360 images. Les deux symboles animatingBox et animatingStar sont définis pour l’exportation vers ActionScript et leurs champs Classe correspondent aux chemins de classe respectifs spécifiés dans l’implémentation de getAssets(). La classe de base par défaut flash.display.MovieClip est conservée, puisque nous voulons créer des sous-classes pour les méthodes MovieClip standard. Après définition des paramètres d’exportation de votre symbole, publiez le fichier FLA. Vous disposez maintenant de votre première bibliothèque d’exécution. Ce fichier SWF pourrait être chargé dans un autre fichier SWF AVM2, dans lequel les symboles AnimatingBox et AnimatingStar seraient disponibles. Chargement de la bibliothèque dans un autre fichier SWF Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le dernier élément fonctionnel à traiter est l’interface utilisateur de l’explorateur. Dans cet exemple, le chemin d’accès à la bibliothèque d’exécution est codé en dur dans la variable ASSETS_PATH. Vous pourriez également utiliser la classe FileReference, par exemple pour créer une interface qui recherche un fichier SWF particulier sur le disque dur. Une fois que la bibliothèque d’exécution est chargée, Flash Player appelle la méthode runtimeAssetsLoadComplete(). private function runtimeAssetsLoadComplete(event:Event):void { var rl:* = event.target.content; var assetList:Array = rl.getAssets(); populateDropdown(assetList); stage.frameRate = 60; } Dans cette méthode, la variable rl représente le fichier SWF chargé. Le code appelle la méthode getAssets() du fichier SWF chargé, obtient la liste des éléments disponibles et remplit un composant ComboBox avec cette liste en appelant la méthode populateDropDown(). Cette méthode enregistre le chemin de classe complet de chaque élément. Si l’utilisateur clique sur le bouton Ajouter, l’interface déclenche la méthode addAsset() : private function addAsset():void { var className:String = assetNameCbo.selectedItem.data; var AssetClass:Class = getDefinitionByName(className) as Class; var mc:MovieClip = new AssetClass(); ... } qui obtient le chemin de classe de l’élément actuellement sélectionné dans la ComboBox (assetNameCbo.selectedItem.data), et utilise la fonction getDefinitionByName() (du package flash.utils) pour obtenir une référence à la classe de l’élément afin de créer une nouvelle occurrence de celui-ci. 346 Dernière mise à jour le 27/4/2013 Chapitre 17 : Utilisation des interpolations de mouvement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis La section « Animation des objets » à la page 200 décrit la procédure d’implémentation d’une animation pilotée par un script ActionScript. Ce chapitre est consacré à une autre technique de création d’une animation : l’interpolation de mouvement. Cette technique vous permet de créer un mouvement en le configurant en mode interactif dans un document par le biais d’Adobe® Flash® Professional. Vous pouvez ensuite utiliser ce mouvement dans votre animation dynamique à base de code ActionScript lors de l’exécution. Flash Professional génère automatiquement le code ActionScript qui implémente l’interpolation de mouvement et vous permet de le copier et de le réutiliser. Pour créer des interpolations de mouvement, vous devez disposer d’une licence pour Flash Professional. Voir aussi Package fl.motion Principes de base des interpolations de mouvement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis Les interpolations de mouvement permettent de créer aisément une animation. Une interpolation de mouvement modifie les propriétés d’un objet d’affichage, telles que la position ou la rotation, d’une image à l’autre. Elle permet également de modifier l’apparence d’un objet d’affichage en cours de déplacement en lui appliquant divers filtres et propriétés. Vous créez l’interpolation de mouvement en mode interactif dans Flash Professional, ce qui génère le code ActionScript correspondant. Dans Flash, utilisez la commande Copie de mouvement en tant qu’ActionScript 3.0 pour copier le code ActionScript à l’origine de l’interpolation de mouvement. Vous pouvez alors réutiliser le code ActionScript pour créer un mouvement dans votre animation dynamique lors de l’exécution. Pour plus d’informations sur la création d’une interpolation de mouvement, voir la section Interpolations de mouvement du manuel Utilisation de Flash Professional. Concepts importants et terminologie La liste de référence suivante contient un terme important relatif à la fonctionnalité étudiée : Interpolation de mouvement Construction qui génère des images intermédiaires d’un objet d’affichage dans des états et à des moments différents, créant ainsi l’impression que le premier état évolue progressivement vers le second état. Une interpolation de mouvement permet de déplacer un objet d’affichage sur la scène, ainsi que de le faire progressivement grandir, rétrécir, pivoter ou changer de couleur. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 347 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 Copie de scripts d’interpolation de mouvement dans Flash Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis Une interpolation génère des images intermédiaires qui affichent un objet d’affichage dans des états différents dans deux images distinctes d’un scénario. Elle crée l’impression que le contenu de la première image se transforme progressivement en contenu de la seconde image. Dans une interpolation de mouvement, le changement d’apparence implique généralement la modification de la position de l’objet d’affichage, créant ainsi un mouvement. Outre le repositionnement de l’objet d’affichage, une interpolation de mouvement peut faire pivoter, incliner ou redimensionner ce dernier, voire lui appliquer des filtres. Vous créez une interpolation de mouvement dans Flash en déplaçant un objet d’affichage entre des images-clé du scénario. Flash génère automatiquement le code ActionScript qui décrit l’interpolation, que vous pouvez copier et enregistrer dans un fichier. Pour plus d’informations sur la création d’une interpolation de mouvement, voir la section Interpolations de mouvement du manuel Utilisation de Flash Professional. Vous pouvez accéder à la copie de mouvement en tant que commande ActionScript 3.0 dans Flash, de deux façons différentes. La première consiste à utiliser un menu contextuel d’interpolation sur la scène, comme suit : 1 Sélectionnez l’interpolation de mouvement sur la scène. 2 Cliquez dessus avec le bouton droit de la souris (Windows) ou cliquez sur la touche Contrôle (Macintosh). 3 Choisissez Copie de mouvement en tant que ActionScript 3.0 . . . La seconde technique consiste à choisir directement la commande dans le menu Edition de Flash, comme suit : 1 Sélectionnez l’interpolation de mouvement sur la scène. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 348 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 2 Choisissez Edition > Scénario > Copier le mouvement en tant que ActionScript 3.0. Une fois le script copié, collez-le dans un fichier et enregistrez-le. Une fois l’interpolation de mouvement créée et après avoir copié et enregistré le script, vous pouvez la réutiliser sous sa forme actuelle ou la modifier dans votre propre animation dynamique pilotée par un script ActionScript. Incorporation de scripts d’interpolation de mouvement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis L’en-tête du code ActionScript copié à partir de Flash recense tous les modules requis pour prendre en charge l’interpolation de mouvement. Classes d’interpolation de mouvement Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis Les classes principales d’interpolation de mouvement, AnimatorFactory, MotionBase et Motion, appartiennent au package fl.motion. Vous pourriez avoir besoin de classes supplémentaires suivant les propriétés que l’interpolation de mouvement manipule. Par exemple, si l’interpolation de mouvement transforme ou fait pivoter l’objet d’affichage, vous devez importer les classes flash.geom appropriées. Si des filtres sont appliqués, importez les classes flash.filter. Dans ActionScript, une interpolation de mouvement est une occurrence de la classe Motion. La classe Motion stocke une séquence d’animation d’images-clés pouvant s’appliquer à un objet visuel. Les données de l’animation comprennent les éléments suivants : position, échelle, rotation, inclinaison, couleur, filtres et accélération. Le code ActionScript suivant a été copié à partir d’une interpolation de mouvement créée dans Flash en vue d’animer un objet d’affichage portant le nom d’occurrence Symbol1_2. Il déclare une variable associée à un objet MotionBase nommé __motion_Symbol1_2. La classe MotionBase est le parent de la classe Motion. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 349 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 var __motion_Symbol1_2:MotionBase; Le script crée ensuite l’objet Motion : __motion_Symbol1_2 = new Motion(); Noms d’objet Motion Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis Dans le cas précédent, Flash a automatiquement généré le nom __motion_Symbol1_2 de l’objet Motion. Il a associé le préfixe __motion_ au nom de l’objet d’affichage. Ainsi, le nom généré automatiquement est basé sur le nom d’occurrence de l’objet cible de l’interpolation de mouvement dans Flash. La propriété duration de l’objet Motion indique le nombre total d’images dans l’interpolation de mouvement : __motion_Symbol1_2.duration = 200; Par défaut, Flash affecte automatiquement un nom à l’occurrence d’objet d’affichage dont l’interpolation de mouvement est copiée si elle n’en possède pas encore un. Lorsque vous réutilisez un code ActionScript créé par Flash dans votre propre animation, vous pouvez conserver le nom d’interpolation automatiquement généré par Flash ou choisir un autre nom. Si vous modifiez le nom de l’interpolation, n’oubliez pas de répercuter la modification dans l’ensemble du script. Dans Flash, vous pouvez également affecter le nom de votre choix à l’objet cible de l’interpolation de mouvement, puis créer l’interpolation de mouvement et copier le script. Quelle que soit l’approche adoptée, assurez-vous que chaque objet Motion de votre code ActionScript possède un nom unique. Description de l’animation Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis La méthode addPropertyArray() de la classe MotionBase ajoute un tableau de valeurs pour décrire chaque propriété interpolée. Le tableau contient potentiellement un élément par image-clé de l’interpolation de mouvement. Il arrive souvent que certains de ces tableaux contiennent moins d’éléments que le nombre total d’images-clés de l’interpolation de mouvement. Ce cas de figure se produit lorsque la dernière valeur du tableau n’est pas modifiée pour les images restantes. Si la longueur de l’argument array est supérieure à celle de la propriété duration de l’objet Motion, la méthode addPropertyArray() ajuste en conséquence la valeur de la propriété duration. Elle n’ajoute pas d’image-clé pour les propriétés précédemment ajoutées. Les nouvelles images-clés subsistent pendant la durée des images supplémentaires de l’animation. Les propriétés x et y de l’objet Motion décrivent la nouvelle position de l’objet interpolé au fur et à mesure de l’exécution de l’animation. Ces coordonnées correspondent aux valeurs les plus susceptibles de changer dans chaque image-clé si la position de l’objet d’affichage évolue. La méthode addPropertyArray() vous permet d’ajouter d’autres propriétés de mouvement. Par exemple, ajoutez les valeurs scaleX et scaleY si l’objet interpolé est redimensionné. Ajoutez les valeurs skewX et skewY s’il est incliné. Ajoutez la propriété rotationConcat s’il fait l’objet d’une rotation. Utilisez la méthode addPropertyArray() pour définir les propriétés d’interpolation suivantes : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 350 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 Les propriétés ajoutées au script automatiquement généré varient selon les propriétés affectées à l’interpolation de mouvement dans Flash. Vous pouvez ajouter, supprimer ou modifier certaines de ces propriétés lorsque vous personnalisez votre version du script. Le code suivant affecte des valeurs aux propriétés de l’interpolation de mouvement __motion_Wheel. Dans ce cas de figure, l’objet d’affichage interpolé ne change pas d’emplacement, mais pivote sur place dans les 29 images de l’interpolation de mouvement. Les diverses valeurs affectées au tableau rotationConcat définissent la rotation. Les autres valeurs de propriété de cette interpolation de mouvement ne sont pas modifiées. __motion_Wheel = new Motion(); __motion_Wheel.duration = 29; __motion_Wheel.addPropertyArray("x", [0]); __motion_Wheel.addPropertyArray("y", [0]); __motion_Wheel.addPropertyArray("scaleX", [1.00]); __motion_Wheel.addPropertyArray("scaleY", [1.00]); __motion_Wheel.addPropertyArray("skewX", [0]); __motion_Wheel.addPropertyArray("skewY", [0]); __motion_Wheel.addPropertyArray("rotationConcat", [ 0,-13.2143,-26.4285,-39.6428,-52.8571,-66.0714,-79.2857,-92.4999,-105.714, -118.929,-132.143,-145.357,-158.571,-171.786,-185,-198.214,-211.429,-224.643, -237.857,-251.071,-264.286,-277.5,-290.714,-303.929,-317.143,-330.357, -343.571,-356.786,-370 ] ); __motion_Wheel.addPropertyArray("blendMode", ["normal"]); x Position horizontale du point de transformation de l’objet dans l’espace de coordonnées de son objet parent y Position verticale du point de transformation de l’objet dans l’espace de coordonnées de son objet parent z Position de profondeur (axe z) du point de transformation de l’objet dans l’espace de coordonnées de son objet parent scaleX Redimensionnement horizontal, exprimé sous forme de pourcentage de l’objet tel qu’il est appliqué à partir du point de transformation scaleY Redimensionnement vertical, exprimé sous forme de pourcentage de l’objet tel qu’il est appliqué à partir du point de transformation skewX Angle d’inclinaison horizontale de l’objet, en degrés, tel qu’il est appliqué à partir du point de transformation skewY Angle d’inclinaison verticale de l’objet, en degrés, tel qu’il est appliqué à partir du point de transformation rotationX Rotation de l’objet autour de l’axe x à partir de son orientation d’origine rotationY Rotation de l’objet autour de l’axe y à partir de son orientation d’origine rotationConcat Valeurs de rotation (axe z) de l’objet dans le cadre du mouvement par rapport à l’orientation précédente appliquée à partir du point de transformation useRotationConcat Si cette propriété est définie, elle entraîne la rotation de l’objet cible lorsque la méthode addPropertyArray() fournit des données de mouvement. blendMode Valeur de la classe BlendMode qui définit le mélange de couleurs de l’objet sous lequel figurent les graphiques matrix3D Propriété matrix3D si elle a été définie pour l’image-clé. Réservée aux interpolations 3D. Si elle est utilisée, aucune des propriétés de transformation précédentes n’est prise en considération. rotationZ Rotation (en degrés) autour de l’axe z de l’objet, à partir de son orientation d’origine par rapport au conteneur parent 3D. Utilisé pour les interpolations 3D au lieu de rotationConcat. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 351 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 Dans l’exemple suivant, l’objet d’affichage Leaf_1 traverse la scène. Les tableaux de propriétés x et y correspondants contiennent des valeurs différentes pour chacune des 100 images de l’animation. Par ailleurs, l’objet pivote sur son axe z au fur et à mesure qu’il traverse la scène. Les divers éléments du tableau de la propriété rotationZ déterminent la rotation. __motion_Leaf_1 = new MotionBase(); __motion_Leaf_1.duration = 100; __motion_Symbol1_4.addPropertyArray("y", [ 0,5.91999,11.84,17.76,23.68,29.6,35.52,41.44,47.36,53.28,59.2,65.12,71.04, 76.96,82.88,88.8,94.72,100.64,106.56,112.48,118.4,124.32,130.24,136.16,142.08, 148,150.455,152.909,155.364,157.818,160.273,162.727,165.182,167.636,170.091, 172.545,175,177.455,179.909,182.364,184.818,187.273,189.727,192.182,194.636, 197.091,199.545,202,207.433,212.865,218.298,223.73,229.163,234.596,240.028, 245.461,250.893,256.326,261.759,267.191,272.624,278.057,283.489, 288.922,294.354,299.787,305.22,310.652,316.085,321.517,326.95,330.475,334, 337.525,341.05,344.575,348.1,351.625,355.15,358.675,362.2,365.725,369.25, 372.775,376.3,379.825,383.35,386.875,390.4,393.925,397.45,400.975,404.5, 407.5,410.5,413.5,416.5,419.5,422.5,425.5 ] ); __motion_Symbol1_4.addPropertyArray("scaleX", [1.00]); __motion_Symbol1_4.addPropertyArray("scaleY", [1.00]); __motion_Symbol1_4.addPropertyArray("skewX", [0]); __motion_Symbol1_4.addPropertyArray("skewY", [0]); __motion_Symbol1_4.addPropertyArray("z", [ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ] ); __motion_Symbol1_4.addPropertyArray("rotationX", [64.0361]); __motion_Symbol1_4.addPropertyArray("rotationY", [41.9578]); __motion_Symbol1_4.addPropertyArray("rotationZ", [ -18.0336,-17.5536,-17.0736,-16.5936,-16.1136,-15.6336,-15.1536,-14.6736, -14.1936,-13.7136,-13.2336,-12.7536,-12.2736,-11.7936,-11.3136,-10.8336, -10.3536,-9.8736,-9.3936,-8.9136,-8.4336,-7.9536,-7.4736,-6.9936,-6.5136, -6.0336,-7.21542,-8.39723,-9.57905,-10.7609,-11.9427,-13.1245,-14.3063, -15.4881,-16.67,-17.8518,-19.0336,-20.2154,-21.3972,-22.5791,-23.7609, -24.9427,-26.1245,-27.3063,-28.4881,-29.67,-30.8518,-32.0336,-31.0771, -30.1206,-29.164,-28.2075,-27.251,-26.2945,-25.338,-24.3814,-23.4249, -22.4684,-21.5119,-20.5553,-19.5988,-18.6423,-17.6858,-16.7293,-15.7727 -14.8162,-13.8597,-12.9032,-11.9466,-10.9901,-10.0336,-10.9427,-11.8518, -12.7609,-13.67,-14.5791,-15.4881,-16.3972,-17.3063,-18.2154,-19.1245, -20.0336,-20.9427,-21.8518,-22.7609,-23.67,-24.5791,-25.4881,-26.3972, -27.3063,-28.2154,-29.1245,-30.0336,-28.3193,-26.605,-24.8907,-23.1765, -21.4622,-19.7479,-18.0336 ] ); __motion_Symbol1_4.addPropertyArray("blendMode", ["normal"]); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 352 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 Ajout de filtres Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis Si l’objet cible d’une interpolation de mouvement contient des filtres, ces derniers sont ajoutés par le biais des méthodes initFilters() et addFilterPropertyArray() de la classe Motion. Initialisation du tableau de filtres Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis La méthode initFilters() initialise les filtres. Son premier argument est un tableau qui recense les noms de classe entièrement qualifiés de tous les filtres appliqués à l’objet d’affichage. Ce tableau de noms de filtre est généré à partir de la liste de filtres associée à l’interpolation de mouvement dans Flash. Dans votre copie du script, vous pouvez supprimer ou ajouter dans ce tableau n’importe quel filtre du package flash.filters. L’appel suivant initialise la liste de filtres associée à l’objet d’affichage cible. Il applique les filtres DropShadowFilter, GlowFilter et BevelFilter et copie la liste dans chaque image-clé de l’objet Motion. __motion_Box.initFilters(["flash.filters.DropShadowFilter", "flash.filters.GlowFilter", "flash.filters.BevelFilter"], [0, 0, 0]); Ajout de filtres Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis La méthode addFilterPropertyArray() décrit les propriétés d’un filtre initialisé doté des arguments suivants : 1 Son premier argument identifie un filtre en fonction de son index. L’index se réfère à la position du nom de filtre dans le tableau des noms de classe de filtre transmis lors d’un appel précédent d’initFilters(). 2 Le deuxième argument est la propriété à stocker pour le filtre dans chaque image-clé. 3 Le troisième argument est la valeur de la propriété de filtre indiquée. Etant donné l’appel précédent d’initFilters(), les appels suivants de addFilterPropertyArray() affectent la valeur 5 aux propriétés blurX et blurY de DropShadowFilter. DropShadowFilter est le premier élément (index 0)du tableau de filtres initialisés : __motion_Box.addFilterPropertyArray(0, "blurX", [5]); __motion_Box.addFilterPropertyArray(0, "blurY", [5]); Les trois appels suivants affectent des valeurs aux propriétés qualité, alpha et couleur de GlowFilter (le deuxième élément (index 1) du tableau de filtres initialisés) : __motion_Box.addFilterPropertyArray(1, "quality", [BitmapFilterQuality.LOW]); __motion_Box.addFilterPropertyArray(1, "alpha", [1.00]); __motion_Box.addFilterPropertyArray(1, "color", [0xff0000]); Les quatre appels suivants affectent des valeurs aux propriétés shadowAlpha, shadowColor, highlightAlpha et highlightColor de BevelFilter, le troisième élément (index 2) du tableau de filtres initialisés : __motion_Box.addFilterPropertyArray(2, "shadowAlpha", [1.00]); __motion_Box.addFilterPropertyArray(2, "shadowColor", [0x000000]); __motion_Box.addFilterPropertyArray(2, "highlightAlpha", [1.00]); __motion_Box.addFilterPropertyArray(2, "highlightColor", [0xffffff]); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 353 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 Réglage de la couleur à l’aide de ColorMatrixFilter Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis Une fois ColorMatrixFilter initialisé, vous pouvez définir les propriétés AdjustColor appropriées pour régler la luminosité, le contraste, la saturation et la teinte de l’objet d’affichage interpolé. En règle générale, le filtre AdjustColor est appliqué lors de la génération de l’interpolation de mouvement dans Flash. Vous pouvez l’ajuster dans votre copie du code ActionScript. L’exemple suivant transforme la teinte et la saturation de l’objet d’affichage au fur et à mesure qu’il se déplace. __motion_Leaf_1.initFilters(["flash.filters.ColorMatrix"], [0], -1, -1); __motion_Leaf_1.addFilterPropertyArray(0, "adjustColorBrightness", [0], -1, -1); __motion_Leaf_1.addFilterPropertyArray(0, "adjustColorContrast", [0], -1, -1); __motion_Leaf_1.addFilterPropertyArray(0, "adjustColorSaturation", [ 0,-0.589039,1.17808,-1.76712,-2.35616,-2.9452,-3.53424,-4.12328, -4.71232,-5.30136,-5.89041, 6.47945,-7.06849,-7.65753,-8.24657, -8.83561,-9.42465,-10.0137,-10.6027,-11.1918,11.7808,-12.3699, -12.9589,-13.5479,-14.137,-14.726,-15.3151,-15.9041,-16.4931, 17.0822,-17.6712,-18.2603,-18.8493,-19.4383,-20.0274,-20.6164, -21.2055,-21.7945,22.3836,-22.9726,-23.5616,-24.1507,-24.7397, -25.3288,-25.9178,-26.5068,-27.0959,27.6849,-28.274,-28.863,-29.452, -30.0411,-30.6301,-31.2192,-31.8082,-32.3973,32.9863,-33.5753, -34.1644,-34.7534,-35.3425,-35.9315,-36.5205,-37.1096,-37.6986, 38.2877,-38.8767,-39.4657,-40.0548,-40.6438,-41.2329,-41.8219, -42.411,-43 ], -1, -1); __motion_Leaf_1.addFilterPropertyArray(0, "adjustColorHue", [ 0,0.677418,1.35484,2.03226,2.70967,3.38709,4.06451,4.74193,5.41935, 6.09677,6.77419,7.45161,8.12903,8.80645,9.48387,10.1613,10.8387,11.5161, 12.1935,12.871,13.5484,14.2258,14.9032,15.5806,16.2581,16.9355,17.6129, 18.2903,18.9677,19.6452,20.3226,21,22.4286,23.8571,25.2857,26.7143,28.1429, 29.5714,31,32.4286,33.8571,35.2857,36.7143,38.1429,39.5714,41,42.4286,43.8571, 45.2857,46.7143,48.1429,49.5714,51,54,57,60,63,66,69,72,75,78,81,84,87, 90,93,96,99,102,105,108,111,114 ], -1, -1); Association d’une interpolation de mouvement à ses objets d’affichage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures, Flash CS3 ou ultérieur requis La dernière tâche consiste à associer l’interpolation de mouvement aux objets d’affichage qu’elle manipule. La classe AnimatorFactory gère l’association entre une interpolation de mouvement et ses objets d’affichage cible. L’argument du constructeur d’AnimatorFactory correspond à l’objet Motion : var __animFactory_Wheel:AnimatorFactory = new AnimatorFactory(__motion_Wheel); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 354 Utilisation des interpolations de mouvement Dernière mise à jour le 27/4/2013 La méthode addTarget() de la classe AnimatorFactory permet d’associer l’objet d’affichage cible à l’interpolation de mouvement correspondante. Le code ActionScript copié à partir de Flash met la ligne addTarget() en commentaire et n’indique pas de nom d’occurrence : // __animFactory_Wheel.addTarget(, 0); Dans votre copie, stipulez l’objet d’affichage à associer à l’interpolation de mouvement. Dans l’exemple suivant, les cibles spécifiées sont greenWheel et redWheel : __animFactory_Wheel.AnimatorFactory.addTarget(greenWheel, 0); __animFactory_Wheel.AnimationFactory.addTarget(redWheel, 0); Vous pouvez associer plusieurs objets d’affichage à la même interpolation de mouvement en utilisant plusieurs appels de addTarget(). 355 Dernière mise à jour le 27/4/2013 Chapitre 18 : Utilisation de la cinématique inverse Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS4 ou ultérieur requis La cinématique inverse (IK, Inverse kinematics) est une technique de création fantastique de mouvement réaliste. IK vous permet de créer des mouvements coordonnés au sein d’une chaîne de sections connectées appelée squelette IK, de sorte que les sections se déplacent avec réalisme. Les sections du squelette représentent ses os et articulations. A partir de l’extrémité finale du squelette, IK calcule les angles des articulations requises pour atteindre cette dernière. Calculer manuellement ces angles s’avérerait particulièrement complexe. Cette fonctionnalité présente l’avantage de permettre de créer des squelettes en mode interactif dans Adobe® Flash® Professional. Il vous suffit ensuite de les animer par le biais d’ActionScript. Le moteur IK intégré à Flash Professional exécute les calculs requis pour décrire le mouvement du squelette. Vous pouvez restreindre le mouvement à certains paramètres dans votre code ActionScript. La version Flash Professional CS5 de la cinématique inverse (IK) intègre à présent le concept de ressort de segment, généralement réservé aux applications d’animation haut de gamme. Associée au nouveau moteur physique dynamique, cette fonctionnalité permet de configurer des mouvements réalistes. Cet effet est par ailleurs visible lors des phases d’exécution et de création. Pour créer des squelettes de cinématique inverse, vous devez disposer d’une licence pour Flash Professional. Voir aussi Package fl.ik Principes de base de la cinématique inverse Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS4 ou ultérieur requis La cinématique inverse (IK) vous permet de créer une animation réaliste en liant des sections de sorte qu’elles se déplacent les unes par rapport aux autres avec naturel. L’utilisation d’IK vous permet par exemple de déplacer une jambe pour qu’elle occupe une position déterminée en articulant les mouvements des articulations de la jambe nécessaires à l’obtention de la pose appropriée. IK utilise une structure osseuse chaînée portant le nom de squelette IK. Le package fl.ik vous aide à créer des animations qui ressemblent à un mouvement naturel. Il vous permet d’animer plusieurs squelettes IK en toute transparence sans avoir à maîtriser les concepts physiques sur lesquels s’appuient les algorithmes IK. Vous créez le squelette IK et les os et articulations qui le composent dans Flash Professional. Vous pouvez ensuite utiliser les classes IK pour les animer lors de l’exécution. Pour obtenir des instructions détaillées sur la création d’un squelette IK, voir Utilisation de la cinématique inverse dans Utilisation de Flash Professional. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 356 Utilisation de la cinématique inverse Dernière mise à jour le 27/4/2013 Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs à la fonctionnalité étudiée. Squelette Chaîne cinématique composée d’os et d’articulations, utilisée en animation informatique pour simuler un mouvement réaliste. Os Segment rigide d’un squelette, équivalent à un os chez un animal. Cinématique inverse (IK) Processus d’identification des paramètres d’un objet souple articulé appelé squelette ou chaîne cinématique. Articulation Emplacement où deux os s’unissent, conçu pour permettre le mouvement des os ; analogue à une articulation chez un animal. Moteur physique Package d’algorithmes physiques qui permet d’intégrer des actions réalistes à l’animation. Ressort Qualité d’un segment qui se déplace et réagit lorsque le segment parent est déplacé, puis diminue progressivement par incréments. Aperçu de l’animation de squelettes IK Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS4 ou ultérieur requis Une fois le squelette IK créé dans Flash Professional, utilisez les classes fl.ik pour restreindre ses mouvements, suivre les événements correspondants et l’animer lors de l’exécution. La figure ci-dessous illustre le clip Wheel. L’essieu est une occurrence d’un squelette IK appelée Axle. La classe IKMover déplace le squelette en le synchronisant avec la rotation d’une roue. Dans le squelette, IKBone, nommé ikBone2, est rattaché à la roue au niveau de l’articulation arrière. A. Roue B. Essieu C. ikBone2 B A C GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 357 Utilisation de la cinématique inverse Dernière mise à jour le 27/4/2013 Lors de l’exécution, la roue tourne en association avec l’interpolation de mouvement __motion_Wheel étudiée dans « Description de l’animation » à la page 349. Un objet IKMover lance et contrôle le mouvement de l’essieu. La figure suivante propose deux instantanés du squelette de l’essieu connecté à la roue qui tourne sur différentes images de la rotation. Lors de l’exécution, le code ActionScript suivant : • Extrait des informations relatives au squelette et à ses composants. • Instancie un objet IKMover. • Déplace l’essieu en conjonction avec la rotation de la roue. import fl.ik.* var tree:IKArmature = IKManager.getArmatureByName("Axle"); var bone:IKBone = tree.getBoneByName("ikBone2"); var endEffector:IKJoint = bone.tailJoint; var pos:Point = endEffector.position; var ik:IKMover = new IKMover(endEffector, pos); ik.limitByDistance = true; ik.distanceLimit = 0.1; ik.limitByIteration = true; ik.iterationLimit = 10; Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); function frameFunc(event:Event) { if (Wheel != null) { var mat:Matrix = Wheel.transform.matrix; var pt = new Point(90, 0); pt = mat.transformPoint(pt); ik.moveTo(pt); } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 358 Utilisation de la cinématique inverse Dernière mise à jour le 27/4/2013 Les classes IK utilisées pour déplacer l’essieu sont les suivantes : • IKArmature : décrit le squelette (structure arborescente composée d’os et d’articulations). A créer dans Flash Professional. • IKManager : classe qui contient tous les squelettes IK du document, à créer dans Flash Professional. • IKBone : segment d’un squelette IK. • IKJoint : connexion entre deux os IK. • IKMover : lance et contrôle le mouvement IK des squelettes. Pour obtenir une description détaillée de ces classes, voir ik package (Package ik). Obtention d’informations sur un squelette IK Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS4 ou ultérieur requis Commencez par déclarer les variables associées au squelette, à l’os et à l’articulation qui composent les sections à déplacer. Le code suivant utilise la méthode getsqueletteByName() de la classe IKManager pour affecter la valeur du squelette Axle à la variable IKArmature tree. Le squelette Axle a été précédemment généré dans Flash Professional. var tree:IKArmature = IKManager.getArmatureByName("Axle"); De même, le code suivant utilise la méthode getBoneByName() de la classe IKArmature pour affecter à la variable IKBone la valeur de l’os ikBone2. var bone:IKBone = tree.getBoneByName("ikBone2"); L’articulation arrière de l’os ikBone2 correspond à la section du squelette connectée à la roue qui tourne. La ligne suivante déclare la variable endEffector et l’affecte à la propriété tailjoint de l’os ikBone2 : var endEffector:IKJoint = home.tailjoint; La variable pos est un point qui stocke la position actuelle de l’articulation endEffector. var pos:Point = endEffector.position; Dans cet exemple, pos correspond à la position de l’articulation raccordée à la roue à l’extrémité de l’essieu. La valeur d’origine de cette variable est extraite de la propriété position de IKJoint. Instanciation de l’objet IKMover et restriction du mouvement Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS4 ou ultérieur requis Une occurrence de la classe IKMover déplace l’essieu. La ligne suivante instancie l’objet IKMover ik et transmet à son constructeur l’élément à déplacer et le point de départ du mouvement : var ik:IKMover = new IKMover(endEffector, pos); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 359 Utilisation de la cinématique inverse Dernière mise à jour le 27/4/2013 Les propriétés de la classe IKMover vous permettent de restreindre le mouvement d’un squelette. Vous pouvez restreindre le mouvement en fonction de la distance, des itérations et de la durée du mouvement. Les paires de propriétés suivantes imposent ces restrictions. Les paires se composent d’une valeur booléenne qui indique si le mouvement est restreint et d’un entier stipulant la restriction : Toutes les valeurs booléennes étant définies sur false par défaut, le mouvement n’est pas restreint, sauf si vous avez explicitement défini une valeur booléenne sur true. Pour imposer une restriction, définissez la propriété appropriée sur true, puis indiquez la valeur de la propriété Integer correspondante. Si vous définissez la restriction sur une valeur sans définir la propriété Boolean correspondante, elle n’est pas prise en considération. Dans ce cas, le moteur IK continue à déplacer l’objet jusqu’à ce qu’une autre restriction ou la position cible de l’objet IKMover soit atteinte. Dans l’exemple suivant, la distance maximale parcourue par le mouvement du squelette est définie sur 0,1 pixel par itération. Le nombre maximal d’itérations par mouvement est défini sur dix. ik.limitByDistance = true; ik.distanceLimit = 0.1; ik.limitByIteration = true; ik.iterationLimit = 10; Mouvement d’un squelette IK Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS4 ou ultérieur requis L’objet IKMover déplace l’essieu au sein de l’écouteur d’événement associé à la roue. A chaque événement enterFrame de la roue, une nouvelle position cible du squelette est calculée. Par le biais de sa méthode moveTo(), l’objet IKMover place l’articulation arrière sur sa position cible ou parcourt une distance aussi longue que possible sans enfreindre les contraintes définies par ses propriétés limitByDistance, limitByIteration et limitByTime. Wheel.addEventListener(Event.ENTER_FRAME, frameFunc); function frameFunc(event:Event) { if (Wheel != null) { var mat:Matrix = Wheel.transform.matrix; var pt = new Point(90,0); pt = mat.transformPoint(pt); ik.moveTo(pt); } } Propriété Boolean Propriété Integer Restriction définie limitByDistance:Boolean distanceLimit:int Définit la distance maximale en pixels parcourue par le moteur IK par itération. limitByIteration:Boolean iterationLimit:int Définit le nombre maximal d’itérations effectuées par le moteur IK par mouvement. limitByTime:Boolean timeLimit:int Définit la durée maximale, exprimée en millisecondes, affectée au moteur IK pour effectuer le mouvement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 360 Utilisation de la cinématique inverse Dernière mise à jour le 27/4/2013 Utilisation de ressorts Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS5 ou ultérieur requis La cinématique inverse prend en charge le ressort de segment dans Flash Professional CS5. Vous pouvez définir les ressorts de segment lors de la phase de création et ajouter ou modifier les attributs correspondants lors de l’exécution. La propriété Spring se rapporte à un segment et aux liaisons correspondantes. Elle possède deux attributs, IKJoint.springStrength, qui définit l’intensité du ressort, et IKJoint.springDamping, qui ajoute une résistance à la valeur d’intensité et modifie la valeur de décroissance du ressort. L’intensité du ressort est exprimée sous forme de pourcentage compris entre la valeur par défaut, 0 (rigidité absolue) et 100 (élasticité importante contrôlée par les lois de la physique). Les segments à ressort réagissent au mouvement de la liaison correspondante. Si aucune autre translation (rotation, x ou y) n’est activée, les paramètres du ressort n’ont aucun impact. L’amortissement du ressort est exprimé sous forme de pourcentage, compris entre la valeur par défaut, 0 (aucune résistance) et 100 (amortissement important). L’amortissement modifie la durée de l’intervalle qui sépare le mouvement initial d’un segment et son retour à une position de repos. Vérifiez si des ressorts sont associés à un objet IKArmature par le biais de la propriété IKArmature.springsEnabled. Les autres propriétés et méthodes relatives aux ressorts relèvent d’objets IKJoint individuels. Une liaison peut être soumise à une rotation angulaire et à une translation le long des axes x et y. Faites appel à IKJoint.setSpringAngle pour positionner l’angle de rotation d’un ressort de liaison et à IKJoint.setSpringPt pour définir la position par translation d’un ressort de liaison. Cet exemple sélectionne un segment par nom et identifie la propriété tailJoint correspondante. Le code teste le squelette parent pour vérifier si des ressorts sont activés, puis définit les propriétés du ressort de la liaison. var arm:IKArmature = IKManager.getArmatureAt(0); var bone:IKBone = arm.getBoneByName("c"); var joint:IKJoint = bone.tailJoint; if (arm.springsEnabled) { joint.springStrength = 50; //medium spring strength joint.springDamping = 10; //light damping resistance if (joint.hasSpringAngle) { joint.setSpringAngle(30); //set angle for rotational spring } } Utilisation d’événements IK Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures, Flash CS4 ou ultérieur requis La classe IKEvent vous permet de créer un objet événement qui contient des informations sur les événements IK. Une information IKEvent décrit le mouvement qui s’est arrêté car la durée, la distance ou le nombre maximal d’itérations stipulés ont été dépassés. Le code suivant indique un écouteur et un gestionnaire d’événement destinés au suivi des événements de limite de temps. Ce gestionnaire d’événement signale les propriétés de durée, distance, nombre d’itérations et articulations d’un événement déclenché lorsque la durée maximale de l’objet IKMover est dépassée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 361 Utilisation de la cinématique inverse Dernière mise à jour le 27/4/2013 var ikmover:IKMover = new IKMover(endjoint, pos); ikMover.limitByTime = true; ikMover.timeLimit = 1000; ikmover.addEventListener(IKEvent.TIME_LIMIT, timeLimitFunction); function timeLimitFunction(evt:IKEvent):void { trace("timeLimit hit"); trace("time is " + evt.time); trace("distance is " + evt.distance); trace("iterationCount is " + evt.iterationCount); trace("IKJoint is " + evt.joint.name); } 362 Dernière mise à jour le 27/4/2013 Chapitre 19 : Travail en trois dimensions (3D) Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Les moteurs d’exécution de Flash Player et d’AIR prennent en charge les graphiques 3D de deux manières. Vous pouvez utiliser les objets d’affichage tridimensionnels sur la liste d’affichage de Flash. Cette méthode permet d’ajouter des effets tridimensionnels à du contenu Flash et convient aux objets comportant peu de polygones. Dans Flash Player 11 et AIR 3 ou les versions ultérieures, vous pouvez effectuer le rendu de séquences 3D complexes à l’aide de l’API Stage3D. Une fenêtre d’affichage Stage3D n’est pas un objet d’affichage. Les graphiques 3D sont rendus dans une fenêtre d’affichage qui apparaît sous la liste d’affichage de Flash (et au-dessus de tous les plans de fenêtre d’affichage StageVideo). Plutôt que d’utiliser les classes DisplayObject de Flash pour créer une séquence, utilisez un processus 3D programmable (similaire à OpenGL et Direct3D). Ce processus prend les données et les textures comme entrées et effectue le rendu de la séquence à l’aide des programmes de shaders que vous fournissez. L’accélération matérielle est utilisée lorsqu’un processeur graphique (GPU) compatible disposant des pilotes pris en charge est disponible sur l’ordinateur client. Stage3D fournit une API de très bas niveau. Dans une application, vous êtes encouragé à utiliser une structure d’application 3D prenant en charge Stage3D. Vous pouvez créer votre propre structure d’application, ou utiliser l’une des nombreuses structures commerciales et Open Source déjà disponibles. Pour plus d’informations sur le développement d’applications 3D à l’aide de Stage3D et sur les structures d’application 3D disponibles, voir Flash Player Developer Center: Stage 3D. Principes de base des objets d’affichage 3D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La principale différence entre un objet en deux dimensions (2D) et un objet en trois dimensions (3D) projeté sur un écran en deux dimensions consiste en l’ajout d’une troisième dimension à l’objet. La troisième dimension permet à l’objet de se rapprocher et de s’éloigner du point de vue de l’utilisateur. Lorsque vous définissez explicitement la propriété z d’un objet d’affichage sur une valeur numérique, l’objet crée automatiquement une matrice de transformation 3D. Vous pouvez intervenir sur cette matrice pour modifier les paramètres de transformation 3D de l’objet. En outre, la rotation 3D diffère de la rotation 2D. En 2D, l’axe de la rotation est systématiquement perpendiculaire au plan x/y, autrement dit, elle se trouve sur l’axe z. En 3D, l’axe de rotation peut se trouver autour de n’importe lequel des axes, x, y ou z. La définition des propriétés de rotation et de mise à l’échelle d’un objet d’affichage lui permet de se déplacer dans l’espace 3D. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 363 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Concepts importants et terminologie La liste de référence suivante contient des termes importants utilisés dans le cadre de la programmation de graphiques en 3 dimensions : Perspective Dans un plan 2D, représentation de lignes parallèles convergeant vers un point de fuite pour donner une illusion de profondeur et de distance. Projection Génération d’une image 2D d’un objet 3D. La projection 3D mappe des points 3D sur un plan 2D. Rotation Modification de l’orientation (et souvent de la position) d’un objet en faisant décrire un mouvement circulaire à chacun de ses points. Transformation Modification de points 3D ou d’ensemble de points par translation, rotation, mise à l’échelle, inclinaison ou une combinaison de ces actions. Translation Modification de la position d’un objet en déplaçant chacun de ses points sur une distance et dans une direction identiques. Point de fuite Point auquel des lignes parallèles qui s’éloignent semblent se rencontrer lorsqu’elles sont représentées dans une perspective linéaire. Vecteur Un vecteur 3D représente un point ou un emplacement dans l’espace en trois dimensions à l’aide de coordonnées cartésiennes (x,y,z). Sommet Point. Maillage texturé Tout point définissant un objet dans l’espace 3D. Mappage des coordonnées UV Mode d’application d’une texture ou d’une image bitmap à une surface 3D. Le mappage des coordonnées UV affecte des valeurs à des coordonnées sur une image en tant que pourcentages de l’axe horizontal (U) et de l’axe vertical (V). valeur T Facteur de mise à l’échelle permettant de déterminer la taille d’un objet 3D lorsque celui-ci se rapproche ou s’éloigne du point de vue actuel. Culling Rendu, ou non, des surfaces avec un enroulement spécifique. L’utilisation du culling (élimination) permet de masquer des surfaces qui ne sont pas visibles à partir du point de vue actuel. Présentation des objets d’affichage 3D dans les moteurs d’exécution de Flash Player et d’AIR Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Dans les versions de Flash Player antérieures à Flash Player 10 et dans les versions d’Adobe AIR antérieures à Adobe AIR 1.5, les objets d’affichage possèdent deux propriétés, x et y, permettant de positionner ces derniers sur un plan 2D. A partir de Flash Player 10 et Adobe AIR 1.5, tout objet d’affichage ActionScript est doté d’une propriété z permettant de le positionner le long de l’axe z, qui est généralement utilisé pour indiquer la profondeur ou la distance. Flash Player 10 et Adobe AIR 1.5 prennent désormais en charge les effets 3D. Les objets 3D restent cependant essentiellement plats. Tout objet d’affichage, tel qu’un objet MovieClip ou Sprite, effectue en fait son propre rendu en deux dimensions, sur un plan unique. Les fonctions 3D vous permettent de placer, déplacer, faire pivoter et transformer de diverses façons ces objets planaires dans la totalité des trois dimensions. Elles vous permettent également de gérer les points 3D et de les convertir en coordonnées 2D (x et y), afin que vous puissiez projeter les objets 3D sur un affichage 2D. A l’aide de ces fonctions, vous pouvez simuler de nombreux types d’effets 3D. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 364 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Le système de coordonnées 3D utilisé par ActionScript est différent. Lorsque vous utilisez des coordonnées 2D dans ActionScript, la valeur de x augmente au fur et à mesure du déplacement vers la droite le long de l’axe x, et la valeur de y augmente au fur et à mesure du déplacement vers le bas le long de l’axe y. Le système de coordonnées 3D conserve ces conventions et ajoute un axe z dont la valeur augmente au fur et à mesure que vous vous éloignez du point de vue. Directions positives des axes x, y et z dans le système de coordonnées 3D A. + axe Z B. Origine C. + axe X D. + axe Y Remarque : n’oubliez pas que Flash Player et AIR représentent toujours la 3D en calques. Par conséquent, si l’objet A se trouve devant l’objet B dans la liste d’affichage, Flash Player ou AIR rend toujours A devant B, quelles que soient les valeurs sur l’axe z des deux objets. Pour résoudre le conflit entre l’ordre de la liste d’affichage et celui de l’axe z, utilisez la méthode transform.getRelativeMatrix3D() afin d’enregistrer, puis de réorganiser les calques des objets d’affichage 3D. pour plus d’informations, voir « Réorganisation de l’affichage à l’aide d’objets Matrix3D » à la page 374. Les classes ActionScript suivantes prennent en charge les nouvelles fonctions 3D : 1 La classe flash.display.DisplayObject contient la propriété z et de nouvelles propriétés de rotation et de mise à l’échelle permettant de manipuler les objets d’affichage dans l’espace 3D. La méthode DisplayObject.local3DToGlobal() simplifie la projection de géométrie 3D sur un plan 2D. 2 Vous pouvez utiliser la classe flash.geom.Vector3D en tant que structure de données pour la gestion des points 3D. Elle prend aussi en charge la mathématique vectorielle. 3 La classe flash.geom.Matrix3D prend en charge les transformations complexes de géométrie 3D, telles que la rotation, la mise à l’échelle et la translation. 4 La classe flash.geom.PerspectiveProjection contrôle les paramètres de mappage de géométrie 3D sur un affichage 2D. ActionScript propose deux approches différentes pour simuler des images 3D : 1 Agencement et animation d’objets planaires dans l’espace 3D. Cette approche implique l’animation d’objets d’affichage à l’aide de leurs propriétés x, y et z, ou la définition des propriétés de rotation et de mise à l’échelle par le biais de la classe DisplayObject. Il est possible de générer des mouvements plus complexes à l’aide de l’objet DisplayObject.transform.matrix3D. L’objet DisplayObject.transform.perspectiveProjection personnalise le tracé des objets d’affichage dans la perspective 3D. Adoptez cette approche pour animer des objets 3D principalement composés de plans. Elle convient aux galeries d’image 3D ou aux objets d’animation 2D agencés dans l’espace 3D, par exemple. A C B (0,0,0) D GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 365 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 2 Génération de triangles 2D à partir d’une géométrie 3D et rendu de ces triangles avec des textures. Pour ce faire, vous devez d’abord définir et gérer des données relatives aux objets 3D, puis les convertir en triangles 2D à des fins de rendu. Il est possible de mapper des textures bitmap sur ces triangles, qui sont ensuite tracés sur un objet graphique à l’aide de la méthode Graphics.drawTriangles(). Cette approche est appropriée pour le chargement des données d’un modèle 3D à partir d’un fichier et le rendu du modèle à l’écran, ou pour la génération et le tracé d’un terrain 3D en tant que maillages triangulaires, par exemple. Création et déplacement d’objets d’affichage 3D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Pour convertir un objet d’affichage 2D en objet d’affichage 3D, vous devez explicitement définir sa propriété z sur une valeur numérique. Lorsque vous affectez une valeur à la propriété z, un objet Transform est créé pour l’objet d’affichage. La définition des propriétés DisplayObject.rotationX ou DisplayObject.rotationY crée également un objet Transform. Celui-ci contient une propriété Matrix3D qui régit la représentation de l’objet d’affichage dans l’espace 3D. Le code suivant définit les coordonnées d’un objet d’affichage appelé « leaf » (feuille) : leaf.x = 100; leaf.y = 50; leaf.z = -30; Vous pouvez visualiser ces valeurs, ainsi que les propriétés qui en dérivent, dans la propriété matrix3D de l’objet Transform de la feuille : var leafMatrix:Matrix3D = leaf.transform.matrix3D; trace(leafMatrix.position.x); trace(leafMatrix.position.y); trace(leafMatrix.position.z); trace(leafMatrix.position.length); trace(leafMatrix.position.lengthSquared); Pour plus d’informations sur les propriétés de l’objet Transform, voir la classe Transform. Pour plus d’informations sur les propriétés de l’objet Matrix3D, voir la classe Matrix3D. Déplacement d’un objet dans l’espace 3D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez déplacer un objet dans l’espace 3D en modifiant la valeur de ses propriétés x, y ou z. Lorsque vous modifiez la valeur de sa propriété z, l’objet semble se rapprocher ou s’éloigner de l’observateur. Le code suivant modifie la valeur de la propriété z de deux ellipses en réponse à un événement pour leur imprimer un mouvement de va-et-vient le long de leur axe z. ellipse2 se déplace plus rapidement qu’ellipse1 : sa propriété z est incrémentée d’un multiple de 20 sur chaque événement Frame, alors que la propriété z d’ellipse1 est incrémentée d’un multiple de 10 : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 366 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 var depth:int = 1000; function ellipse1FrameHandler(e:Event):void { ellipse1Back = setDepth(e, ellipse1Back); e.currentTarget.z += ellipse1Back * 10; } function ellipse2FrameHandler(e:Event):void { ellipse2Back = setDepth(e, ellipse1Back); e.currentTarget.z += ellipse1Back * 20; } function setDepth(e:Event, d:int):int { if(e.currentTarget.z > depth) { e.currentTarget.z = depth; d = -1; } else if (e.currentTarget.z < 0) { e.currentTarget.z = 0; d = 1; } } Rotation d’un objet dans l’espace 3D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez faire pivoter un objet de trois façons différentes, selon la définition de sa propriété de rotation : rotationX, rotationY et rotationZ. La figure ci-dessous illustre deux carrés qui ne sont pas soumis à une rotation : Dans la figure suivante, la propriété rotationY du conteneur des carrés a été incrémentée pour les faire pivoter sur l’axe y. La rotation du conteneur, ou objet d’affichage parent, des deux carrés fait pivoter ceux-ci : container.rotationY += 10; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 367 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Dans la figure suivante, la propriété rotationX du conteneur des carrés est modifiée : Elle fait pivoter ceux-ci sur l’axe x. Dans la figure suivante, la propriété rotationZ du conteneur des carrés a été incrémentée et ceux-ci pivotent sur l’axe z. Un objet d’affichage peut se déplacer et pivoter simultanément dans l’espace 3D. Projection d’objets 3D sur un affichage 2D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La classe PerspectiveProjection du package flash.geom facilite l’application d’une perspective rudimentaire lors du déplacement d’objets d’affichage dans l’espace 3D. Si vous ne créez pas explicitement une projection de perspective pour votre espace 3D, le moteur 3D utilise un objet PerspectiveProjection par défaut, qui existe sur la racine et est propagé à tous ses enfants. Les trois propriétés qui définissent le mode d’affichage de l’espace 3D par un objet PerspectiveProjection sont les suivantes : • fieldOfView • projectionCenter • focalLength La modification de la valeur de fieldOfView entraîne automatiquement la modification de la valeur de focalLength, et inversement, car ces propriétés sont interdépendantes. La formule permettant de calculer focalLength en fonction de la valeur de fieldOfView est la suivante : focalLength = stageWidth/2 * (cos(fieldOfView/2) / sin(fieldOfView/2) En règle générale, vous modifiez explicitement la propriété fieldOfView. Champ de vision Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures En manipulant la propriété fieldOfView de la classe PerspectiveProjection, vous pouvez faire en sorte qu’un objet d’affichage 3D semble s’agrandir ou diminuer selon qu’il se rapproche ou s’éloigne de l’observateur, respectivement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 368 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 La propriété fieldOfView définit un angle compris entre 0 et 180 degrés qui détermine la puissance de la projection de perspective. Plus la valeur est élevée, plus forte est la distorsion appliquée à un objet d’affichage qui se déplace sur son axe z. Une valeur fieldOfView basse entraîne une mise à l’échelle minimale et les objets ne semblent reculer que très légèrement. Une valeur élevéeentraîne une plus grande distorsion et une impression plus prononcée de mouvement. La valeur maximale, 179,9999... degrés, produit un effet d’objectif oeil-de-poisson extrême. La valeur maximale de fieldOfView est 179,9999..., tandis que 0,00001... est sa valeur minimale. Les valeurs exactes de 0 et 180 sont illégales. Centre de la projection Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La propriété projectionCenterreprésente le point de fuite de la projection de perspective. Elle est appliquée comme décalage du point d’alignement par défaut (0,0) dans l’angle supérieur gauche de la scène. A mesure qu’il semble s’éloigner de l’observateur, un objet s’incline vers le point de fuite et finit par disparaître. Imaginez un couloir extrêmement long. Lorsque vous regardez dans le couloir, les bords des murs convergent vers un point de fuite tout au fond. Si le point de fuite se trouve au centre de la scène, le couloir disparaît vers un point central. La valeur par défaut de la propriété projectionCenter correspond au centre de la scène. Si, par exemple, vous souhaitez que des éléments apparaissent sur la gauche de la scène et une zone 3D sur la droite de la scène, définissez la propriété projectionCenter sur un point situé dans la partie droite de la scène pour en faire le point de fuite de votre zone d’affichage 3D. Distance focale Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La propriété focalLength représente la distance séparant l’origine du point de vue (0,0,0) de l’emplacement de l’objet d’affichage sur son axe z. Une distance focale élevée est similaire à un téléobjectif : le champ de vision est étroit et les distances entre les objets compressées. Une distance focale courte s’assimile à un objectif à grand angle et se caractérise par un champ de vision large et une distorsion prononcée. Une distance focale moyenne correspond approximativement à ce que voit l’oeil humain. En règle générale, la propriété focalLength est recalculée dynamiquement pendant la transformation de perspective au fur et à mesure du déplacement de l’objet d’affichage, mais il est possible de la définir explicitement. Valeurs par défaut de la projection de perspective Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures L’objet PerspectiveProjection par défaut créé sur la racine possède les valeurs suivantes : • fieldOfView : 55 • perspectiveCenter : stagewidth/2, stageHeight/2 • focalLength : stageWidth/ 2 * ( cos(fieldOfView/2) / sin(fieldOfView/2) ) Ces valeurs sont appliquées si vous ne créez pas votre propre objet PerspectiveProjection. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 369 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Vous pouvez instancier votre propre objet PerspectiveProjection dans l’intention de modifier vous-même les propriétés projectionCenter et fieldOfView. Dans ce cas, les valeurs par défaut du nouvel objet sont les suivantes, en supposant que la scène mesure 500 sur 500 par défaut : • fieldOfView : 55 • perspectiveCenter : 250,250 • focalLength : 480.24554443359375 Exemple : Projection de perspective Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures L’exemple suivant illustre l’utilisation de la projection de perspective pour créer l’espace 3D. Il indique comment modifier le point de fuite et la projection de perspective de l’espace par le biais de la propriété projectionCenter. Cette modification force un nouveau calcul des propriétés focalLength et fieldOfView, résultant en une distorsion de l’espace 3D. Cet exemple : 1 crée un sprite appelé center, un cercle avec une mire ; 2 affecte les coordonnées du sprite center à la propriété projectionCenter de la propriété perspectiveProjection de la propriété transform de la racine ; 3 ajoute des écouteurs de l’événement souris qui appellent des gestionnaires qui modifient la propriété projectionCenter afin qu’elle suive l’emplacement de l’objet center ; 4 crée quatre boîtes en accordéon qui forment les murs de l’espace en perspective. Lorsque vous testez cet exemple, ProjectionDragger.swf, faites glisser le cercle à différents emplacements. Le point de fuite suit le cercle et figure là où vous le déposez. Observez comme les boîtes qui délimitent l’espace s’étirent et se distordent plus vous éloignez le centre de projection du centre de la scène. Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application ProjectionDragger résident dans le dossier Samples/ProjectionDragger. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 370 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; import flash.display.Shape; import flash.geom.Point; import flash.events.*; public class ProjectionDragger extends Sprite { private var center : Sprite; private var boxPanel:Shape; private var inDrag:Boolean = false; public function ProjectionDragger():void { createBoxes(); createCenter(); } public function createCenter():void { var centerRadius:int = 20; center = new Sprite(); // circle center.graphics.lineStyle(1, 0x000099); center.graphics.beginFill(0xCCCCCC, 0.5); center.graphics.drawCircle(0, 0, centerRadius); center.graphics.endFill(); // cross hairs center.graphics.moveTo(0, centerRadius); center.graphics.lineTo(0, -centerRadius); center.graphics.moveTo(centerRadius, 0); center.graphics.lineTo(-centerRadius, 0); center.x = 175; center.y = 175; center.z = 0; this.addChild(center); center.addEventListener(MouseEvent.MOUSE_DOWN, startDragProjectionCenter); center.addEventListener(MouseEvent.MOUSE_UP, stopDragProjectionCenter); center.addEventListener( MouseEvent.MOUSE_MOVE, doDragProjectionCenter); root.transform.perspectiveProjection.projectionCenter = new Point(center.x, center.y); } public function createBoxes():void { // createBoxPanel(); var boxWidth:int = 50; var boxHeight:int = 50; var numLayers:int = 12; var depthPerLayer:int = 50; // var boxVec:Vector. = new Vector.(numLayers); for (var i:int = 0; i < numLayers; i++) { this.addChild(createBox(150, 50, (numLayers - i) * depthPerLayer, boxWidth, boxHeight, 0xCCCCFF)); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 371 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 this.addChild(createBox(50, 150, (numLayers - i) * depthPerLayer, boxWidth, boxHeight, 0xFFCCCC)); this.addChild(createBox(250, 150, (numLayers - i) * depthPerLayer, boxWidth, boxHeight, 0xCCFFCC)); this.addChild(createBox(150, 250, (numLayers - i) * depthPerLayer, boxWidth, boxHeight, 0xDDDDDD)); } } public function createBox(xPos:int = 0, yPos:int = 0, zPos:int = 100, w:int = 50, h:int = 50, color:int = 0xDDDDDD):Shape { var box:Shape = new Shape(); box.graphics.lineStyle(2, 0x666666); box.graphics.beginFill(color, 1.0); box.graphics.drawRect(0, 0, w, h); box.graphics.endFill(); box.x = xPos; box.y = yPos; box.z = zPos; return box; } public function startDragProjectionCenter(e:Event) { center.startDrag(); inDrag = true; } public function doDragProjectionCenter(e:Event) { if (inDrag) { root.transform.perspectiveProjection.projectionCenter = new Point(center.x, center.y); } } public function stopDragProjectionCenter(e:Event) { center.stopDrag(); root.transform.perspectiveProjection.projectionCenter = new Point(center.x, center.y); inDrag = false; } } } Pour des projections de perspective plus complexes, utilisez la classe Matrix3D. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 372 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Transformations 3D complexes Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La classe Matrix3D vous permet de transformer des points 3D dans un espace de coordonnées ou de mapper des points 3D d’un espace de coordonnées sur un autre. Il n’est pas nécessaire de comprendre les mathématiques matricielles pour pouvoir utiliser la classe Matrix3D. Ses méthodes permettent de gérer la plupart des opérations de transformation courantes. Il est inutile de vous soucier de la définition explicite ou du calcul de la valeur de chaque élément de la matrice. Une fois la propriété z d’un objet d’affichage définie sur une valeur numérique, vous pouvez récupérer la matrice de transformation de l’objet par le biais de la propriété Matrix3D de l’objet Transform de l’objet d’affichage : var leafMatrix:Matrix3D = this.transform.matrix3D; Les méthodes de l’objet Matrix3D vous permettent d’opérer une translation sur un objet d’affichage, de le faire pivoter et de le mettre à l’échelle, ainsi que de lui appliquer une projection de perspective. Utilisez la classe Vector3D et ses propriétés x, y et z pour gérer les points 3D. Elle peut également représenter en physique un vecteur spatial, doté d’une direction et d’une magnitude. Les méthodes de la classe Vector3D vous permettent d’effectuer des calculs courants portant sur des vecteurs spatiaux : somme, produit scalaire et produit vectoriel, par exemple. Remarque : la classe Vector3D n’a aucun rapport avec la classe Vector d’ActionScript. La classe Vector3D contient des propriétés et des méthodes permettant de définir et de manipuler les points 3D, alors que la classe Vector prend en charge les tableaux d’objets typés. Création d’objets Matrix3D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez créer ou récupérer des objets Matrix3D de trois façons principales : • Utilisez la méthode constructeur Matrix3D() pour instancier une nouvelle matrice. Le constructeur Matrix3D() gère un objet Vector contenant 16 valeurs numériques et place chacune d’elles dans une cellule de la matrice. Exemple : var rotateMatrix:Matrix3D = new Matrix3D(1,0,0,1, 0,1,0,1, 0,0,1,1, 0,0,0,1); • Définissez la valeur de la propriété z d’un objet d’affichage. Récupérez ensuite la matrice de transformation de la propriété transform.matrix3D de cet objet. • Récupérez l’objet Matrix3D qui régit l’affichage des objets 3D sur la scène en appelant la méthode perspectiveProjection.toMatrix3D() sur l’objet d’affichage racine. Application de plusieurs transformations 3D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez appliquer simultanément de nombreuses transformations 3D à l’aide d’un objet Matrix3D. Ainsi, pour faire pivoter, mettre à l’échelle, puis déplacer un cube, vous pourriez appliquer trois transformations distinctes à chacun de ses points. Il est cependant beaucoup plus efficace de précalculer plusieurs transformations dans un même objet Matrix3D et d’appliquer une transformation matricielle unique à chacun des points. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 373 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Remarque : l’ordre d’application des transformations matricielles est important. Les calculs matriciels ne sont pas réversibles. Ainsi, l’application d’une rotation puis d’une translation ne donne pas le même résultat que l’opération inverse. L’exemple suivant illustre deux façons d’appliquer plusieurs transformations 3D. package { import flash.display.Sprite; import flash.display.Shape; import flash.display.Graphics; import flash.geom.*; public class Matrix3DTransformsExample extends Sprite { private var rect1:Shape; private var rect2:Shape; public function Matrix3DTransformsExample():void { var pp:PerspectiveProjection = this.transform.perspectiveProjection; pp.projectionCenter = new Point(275,200); this.transform.perspectiveProjection = pp; rect1 = new Shape(); rect1.x = -70; rect1.y = -40; rect1.z = 0; rect1.graphics.beginFill(0xFF8800); rect1.graphics.drawRect(0,0,50,80); rect1.graphics.endFill(); addChild(rect1); rect2 = new Shape(); rect2.x = 20; rect2.y = -40; rect2.z = 0; rect2.graphics.beginFill(0xFF0088); rect2.graphics.drawRect(0,0,50,80); rect2.graphics.endFill(); addChild(rect2); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 374 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 doTransforms(); } private function doTransforms():void { rect1.rotationX = 15; rect1.scaleX = 1.2; rect1.x += 100; rect1.y += 50; rect1.rotationZ = 10; var matrix:Matrix3D = rect2.transform.matrix3D; matrix.appendRotation(15, Vector3D.X_AXIS); matrix.appendScale(1.2, 1, 1); matrix.appendTranslation(100, 50, 0); matrix.appendRotation(10, Vector3D.Z_AXIS); rect2.transform.matrix3D = matrix; } } } Dans la méthode doTransforms(), le premier bloc de code utilise les propriétés DisplayObject pour modifier la rotation, la mise à l’échelle et la position d’un rectangle. Le second bloc utilise les méthodes de la classe Matrix3D pour effectuer des transformations identiques. L’utilisation des méthodes Matrix3D présente un avantage principal : tous les calculs sont déjà effectués dans la matrice. Ils sont ensuite appliqués une seule fois à l’objet d’affichage, lors de la définition de sa propriété transform.matrix3D. La définition des propriétés DisplayObject améliore quelque peu la lisibilité du code source. Cependant, chaque définition d’une propriété de rotation ou de mise à l’échelle donne lieu à plusieurs calculs et entraîne la modification de plusieurs propriétés de l’objet d’affichage. Si votre code applique plusieurs fois des transformations complexes identiques à des objets d’affichage, enregistrez l’objet Matrix3D en tant que variable, puis réappliquez-le autant de fois que nécessaire. Réorganisation de l’affichage à l’aide d’objets Matrix3D Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Comme indiqué plus haut, l’ordre d’apparition des objets d’affichage dans la liste d’affichage détermine l’ordre d’apparition à l’affichage, quels que soient leurs axes z relatifs. Si votre animation transforme les propriétés d’objets d’affichage dans un ordre différent de celui de la liste d’affichage, l’ordre d’apparition des objets d’affichage ne correspondra peut-être pas à celui des axes z. Un objet qui devrait sembler plus éloigné de l’observateur risque donc d’apparaître devant un objet plus proche. Pour avoir la certitude que l’ordre d’apparition des objets d’affichage 3D correspond à leur profondeur relative, procédez comme suit : 1 A l’aide de la méthode getRelativeMatrix3D() de l’objet Transform, extrayez la profondeur relative (z-axes) des objets d’affichage 3D enfant. 2 Supprimez les objets de la liste d’affichage à l’aide de la méthode removeChild(). 3 Triez les objets d’affichage en fonction de leurs valeurs d’axe z relatives. 4 Ajoutez à nouveau les enfants à la liste d’affichage en ordre inverse, par le biais de la méthode addChild(). Cette réorganisation garantit que vos objets s’affichent conformément à leurs axes z relatifs. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 375 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Le code suivant garantit l’affichage correct d’une boîte 3D à six faces. Il réorganise les faces de la boîte une fois que des rotations lui ont été appliquées. public var faces:Array; . . . public function ReorderChildren() { for(var ind:uint = 0; ind < 6; ind++) { faces[ind].z = faces[ind].child.transform.getRelativeMatrix3D(root).position.z; this.removeChild(faces[ind].child); } faces.sortOn("z", Array.NUMERIC | Array.DESCENDING); for (ind = 0; ind < 6; ind++) { this.addChild(faces[ind].child); } } Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application résident dans le dossier Samples/ReorderByZ. Création d’effets 3D à l’aide de triangles Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Dans ActionScript, vous effectuez des transformations de bitmap à l’aide de la méthode Graphics.drawTriangles(), car les modèles 3D sont représentés par un ensemble de triangles dans l’espace. (Flash Player et AIR ne prennent néanmoins pas en charge une mémoire tampon de profondeur, car les objets d’affichage sont toujours essentiellement plats, ou 2D. Pour plus d'informations, voir « Présentation des objets d’affichage 3D dans les moteurs d’exécution de Flash Player et d’AIR » à la page 363.) La méthode Graphics.drawTriangles() est similaire à la méthode Graphics.drawPath(), en ce qu’elle accepte un ensemble de coordonnées pour tracer un tracé triangulaire. Pour vous familiariser avec l’utilisation de Graphics.drawPath(), voir « Tracés de dessin » à la page 244. La méthode Graphics.drawTriangles() utilise une propriété Vector. pour spécifier l’emplacement des points sur le tracé triangulaire : drawTriangles(vertices:Vector., indices:Vector. = null, uvtData:Vector. = null, culling:String = "none"):void Le premier paramètre de drawTriangles(), vertices, est le seul paramètre obligatoire. C’est un vecteur de nombres définissant les coordonnées par lesquelles vos triangles sont tracés. Trois ensembles de coordonnées (six nombres) représentent un tracé triangulaire. Sans le paramètre indices, la longueur du vecteur doit systématiquement être un facteur de six, car chaque triangle nécessite trois paires de coordonnées (trois ensembles de deux valeurs x/y). Exemple : graphics.beginFill(0xFF8000); graphics.drawTriangles( Vector.([ 10,10, 100,10, 10,100, 110,10, 110,100, 20,100])); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 376 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Ces triangles n’ont pas de points en commun, mais si tel était le cas, le second paramètre de drawTriangles(), indices, permettrait de réutiliser des valeurs du vecteur vertices pour plusieurs triangles. Lorsque vous utilisez le paramètre indices, gardez à l’esprit le fait que les valeurs indices représentent des index de point, pas des index en rapport direct avec les éléments du tableau vertices. En d’autres termes, un index du vecteur vertices tel qu’il est défini par indices correspond en fait à l’index réel divisé par 2. Pour le troisième point d’un vecteur vertices, par exemple, utilisez une valeur indices de 2, même si la première valeur numérique de ce point commence à l’index vectoriel 4. Par exemple, fusionnez deux triangles de sorte qu’ils aient en commun le bord diagonal, par le biais du paramètre indices : graphics.beginFill(0xFF8000); graphics.drawTriangles( Vector.([10,10, 100,10, 10,100, 100,100]), Vector.([0,1,2, 1,3,2])); Vous remarquerez que, bien qu’un carré résulte du tracé de deux triangles, seuls quatre points ont été spécifiés dans le vecteur vertices. Grâce à indices, les deux points partagés par les deux triangles sont réutilisés pour chacun d’eux. Le nombre total de sommets passe donc de 6 (12 nombres) à 4 (8 nombres). Carré tracé à l’aide de deux triangles à l’aide du paramètre vertices Cette technique s’avère utile pour les maillages triangulaires plus grands, dans lesquels la plupart des points sont partagés par plusieurs triangles. Il est possible d’appliquer tous les remplissages aux triangles. Ils sont appliqués au maillage triangulaire résultant comme ils le seraient à toute autre forme. Transformation d’images bitmap Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Les transformations de bitmap donnent une illusion de perspective ou « texture » à un objet en trois dimensions. Vous pouvez notamment distordre une bitmap en direction d’un point de fuite, afin que l’image semble diminuer à mesure qu’elle se rapproche de celui-ci. Vous pouvez aussi utiliser une bitmap en deux dimensions pour créer une surface sur un objet en trois dimensions, donnant ainsi l’impression qu’il possède une texture ou « enveloppe ». 0 1 2 3 GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 377 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Surface en deux dimensions utilisant un point de fuite et objet en trois dimensions enveloppé dans une bitmap Mappage des coordonnées UV Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Lorsque vous commencerez à manipuler les textures, vous souhaiterez utiliser le paramètre uvtData de drawTriangles(). Ce paramètre vous permet de définir le mappage des coordonnées UV pour les remplissages de bitmap. Le mappage des coordonnées UV est une méthode d’application d’une texture à des objets. Il repose sur deux valeurs, une valeur U horizontale (x) et une valeur V verticale (y). Ces valeurs sont basées sur des pourcentages et non sur des valeurs de pixels. 0 U et 0 V correspondent au coin supérieur gauche d’une image, 1 U et 1 V à son coin inférieur droit : Emplacements UV 0 et 1 sur une image bitmap Il est possible d’affecter des coordonnées UV aux vecteurs d’un triangle de sorte qu’ils s’associent aux emplacements respectifs sur une image : Coordonnées UV d’une zone triangulaire sur une image bitmap Les valeurs UV restent en phase avec les points du triangle. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 378 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Les sommets du triangle se déplacent et l’image bitmap se distord pour que les valeurs UV d’un point individuel restent identiques. Au fur et à mesure que des transformations 3D ActionScript sont appliquées au triangle associé à la bitmap, celle-ci est appliquée au triangle en fonction des valeurs UV. Par conséquent, au lieu d’utiliser des calculs matriciels, définissez ou réglez les valeurs UV pour créer un effet tridimensionnel. La méthode Graphics.drawTriangles() accepte également une information facultative pour les transformations tridimensionnelles : la valeur T. La valeur T de uvtData représente la perspective 3D ou, plus spécifiquement, le facteur d’échelle du sommet associé. Le mappage des coordonnées UVT ajoute une correction de perspective au mappage des coordonnées UV. Par exemple, si un objet de l’espace 3D est éloigné du point de vue de telle sorte qu’il semble mesurer 50 % de sa taille « d’origine », sa valeur T correspond à 0,5. Comme les objets de l’espace 3D sont représentés à l’aide de triangles, l’emplacement de ceux-ci le long de l’axe z détermine leur valeur T. L’équation qui représente la valeur T est la suivante : T = focalLength/(focalLength + z); Dans cette équation, focalLength représente une distance focale ou un emplacement à l’« écran » calculé qui détermine la quantité de perspective de l’affichage. Distance focale et valeur z A. point de vue B. écran C. objet 3D D. valeur focalLength E. valeur z La valeur T permet de mettre à l’échelle des formes simples pour donner l’impression qu’elles se trouvent au loin. C’est généralement la valeur utilisée pour convertir les points 3D en points 2D. Dans le cas des données UVT, elle permet aussi de mettre à l’échelle une bitmap entre les points d’un triangle avec perspective. Lorsque vous définissez des valeurs UVT, la valeur T suit directement les valeurs UV définies pour un sommet. Avec l’inclusion de T, chaque trio de valeurs du paramètre uvtData (U, V et T) correspond à chaque paire de valeurs du paramètre vertices (x et y). Avec les valeurs UV seules, uvtData.length == vertices.length. Avec l’inclusion d’une valeur T, uvtData.length = 1,5*vertices.length. D E A B C GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 379 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 L’exemple suivant illustre un plan qui pivote, par le biais de données UVT, dans un espace 3D. Il utilise l’image ocean.jpg et une classe « d’interaction », ImageLoader, qui charge l’image afin qu’il soit possible de l’affecter à l’objet BitmapData. La source de la classe ImageLoader (enregistrez ce code dans le fichier ImageLoader.as) se présente comme suit : package { import flash.display.* import flash.events.*; import flash.net.URLRequest; public class ImageLoader extends Sprite { public var url:String; public var bitmap:Bitmap; public function ImageLoader(loc:String = null) { if (loc != null){ url = loc; loadImage(); } } public function loadImage():void{ if (url != null){ var loader:Loader = new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete); loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoError); var req:URLRequest = new URLRequest(url); loader.load(req); } } private function onComplete(event:Event):void { var loader:Loader = Loader(event.target.loader); var info:LoaderInfo = LoaderInfo(loader.contentLoaderInfo); this.bitmap = info.content as Bitmap; this.dispatchEvent(new Event(Event.COMPLETE)); } private function onIoError(event:IOErrorEvent):void { trace("onIoError: " + event); } } } Le code ActionScript qui utilise des triangles, le mappage des coordonnées UV et des valeurs T pour que l’image semble pivoter et diminuer au fur et à mesure qu’elle se rapproche d’un point de fuite est indiqué ci-dessous. Enregistrez-le dans un fichier que vous nommerez Spinning3dOcean.as : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 380 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 package { import flash.display.* import flash.events.*; import flash.utils.getTimer; public class Spinning3dOcean extends Sprite { // plane vertex coordinates (and t values) var x1:Number = -100,y1:Number = -100,z1:Number = 0,t1:Number = 0; var x2:Number = 100,y2:Number = -100,z2:Number = 0,t2:Number = 0; var x3:Number = 100,y3:Number = 100,z3:Number = 0,t3:Number = 0; var x4:Number = -100,y4:Number = 100,z4:Number = 0,t4:Number = 0; var focalLength:Number = 200; // 2 triangles for 1 plane, indices will always be the same var indices:Vector.; var container:Sprite; var bitmapData:BitmapData; // texture var imageLoader:ImageLoader; public function Spinning3dOcean():void { indices = new Vector.(); indices.push(0,1,3, 1,2,3); container = new Sprite(); // container to draw triangles in container.x = 200; container.y = 200; addChild(container); imageLoader = new ImageLoader("ocean.jpg"); imageLoader.addEventListener(Event.COMPLETE, onImageLoaded); } function onImageLoaded(event:Event):void { bitmapData = imageLoader.bitmap.bitmapData; // animate every frame addEventListener(Event.ENTER_FRAME, rotatePlane); } function rotatePlane(event:Event):void { // rotate vertices over time var ticker = getTimer()/400; z2 = z3 = -(z1 = z4 = 100*Math.sin(ticker)); x2 = x3 = -(x1 = x4 = 100*Math.cos(ticker)); // calculate t values GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 381 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 t1 = focalLength/(focalLength + z1); t2 = focalLength/(focalLength + z2); t3 = focalLength/(focalLength + z3); t4 = focalLength/(focalLength + z4); // determine triangle vertices based on t values var vertices:Vector. = new Vector.(); vertices.push(x1*t1,y1*t1, x2*t2,y2*t2, x3*t3,y3*t3, x4*t4,y4*t4); // set T values allowing perspective to change // as each vertex moves around in z space var uvtData:Vector. = new Vector.(); uvtData.push(0,0,t1, 1,0,t2, 1,1,t3, 0,1,t4); // draw container.graphics.clear(); container.graphics.beginBitmapFill(bitmapData); container.graphics.drawTriangles(vertices, indices, uvtData); } } } Pour tester cet exemple, enregistrez ces deux fichiers de classe dans le même répertoire qu’une image nommée « ocean.jpg ». Vous pouvez constater la transformation appliquée à la bitmap d’origine pour qu’elle semble disparaître au loin et pivoter dans l’espace 3D. Culling Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Le culling est un processus qui détermine quelles surfaces d’un objet en trois dimensions ne doivent pas être rendues par le moteur de rendu car elles ne sont pas visibles à partir du point de vue actuel. Dans l’espace 3D, la surface « arrière » d’un objet en trois dimensions n’est pas visible à partir du point de vue. L’arrière d’un objet 3D n’est pas visible à partir du point de vue. A. point de vue B. objet 3D C. arrière d’un objet en trois dimensions Par essence, tous les triangles sont systématiquement rendus, quelles que soient leur taille, forme et position. Le culling (élimination) garantit que Flash Player ou AIR rend votre objet 3D correctement. En outre, pour éviter les cycles de rendu superflus, il est parfois souhaitable que le moteur de rendu omette certains triangles. Soit un cube en rotation dans l’espace. A tout moment donné, vous ne voyez jamais plus de trois de ses faces car celles qui ne sont pas visibles font face à l’autre direction, de l’autre côté du cube. Comme ces faces ne sont pas visibles, il est inutile que le moteur de rendu les trace. Sans élimination (culling), Flash Player ou AIR rend les faces avant et arrière. A B C GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 382 Travail en trois dimensions (3D) Dernière mise à jour le 27/4/2013 Certaines faces d’un cube ne sont pas visibles à partir du point de vue actuel. C’est pourquoi la méthode Graphics.drawTriangles() gère un quatrième paramètre qui permet de définir une valeur de culling : public function drawTriangles(vertices:Vector., indices:Vector. = null, uvtData:Vector. = null, culling:String = "none"):void Le paramètre culling correspond à une valeur de la classe d’énumération TriangleCulling : TriangleCulling.NONE, TriangleCulling.POSITIVE et TriangleCulling.NEGATIVE. Ces valeurs sont fonction de la direction du tracé triangulaire définissant la surface de l’objet. L’API ActionScript qui permet de déterminer le culling considère comme acquis que tous les triangles orientés vers l’extérieur d’une forme 3D sont tracés dans le même sens. Le retournement d’une face de triangle entraîne un changement de direction du tracé. A ce point, il est possible de supprimer le triangle du rendu. Si la valeur de TriangleCulling est définie sur POSITIVE, les triangles dont le tracé a une direction positive (sens horaire) sont supprimés. Si la valeur de TriangleCulling est définie sur NEGATIVE, les triangles dont le tracé a une direction négative (sens antihoraire) sont supprimés. Dans le cas d’un cube, les surfaces orientées vers l’avant ont un tracé à la direction positive et les surfaces orientées vers l’arrière, un tracé à la direction négative. Cube « déroulé » illustrant le sens du tracé. Lorsque le cube est « enroulé », le sens du tracé de la face arrière est inversé. Pour comprendre le fonctionnement du processus d’élimination (culling), reprenez l’exemple de la section « Mappage des coordonnées UV » à la page 377 et définissez le paramètre de culling de la méthode drawTriangles() sur TriangleCulling.NEGATIVE : container.graphics.drawTriangles(vertices, indices, uvtData, TriangleCulling.NEGATIVE); Vous pouvez constater que la face « arrière » de l’image n’est pas rendue lorsque l’objet pivote. 383 Dernière mise à jour le 27/4/2013 Chapitre 20 : Principes de base de l’utilisation du texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour afficher du texte à l’écran dans Adobe® Flash® Player ou Adobe® AIR™, utilisez une occurrence de la classe TextField ou les classes Text Engine de Flash. Ces classes vous permettent de créer, d’afficher et de mettre en forme du texte. Vous pouvez également utiliser Text Layout Framework (TLF). Il s’agit d’une bibliothèque de composants basée sur les classes Flash Text Engine, mais conçue de manière à offrir une utilisation conviviale. Sur les périphériques mobiles, vous pouvez utiliser la classe StageText pour saisir du texte. Vous pouvez établir le contenu spécifique de champs de texte ou désigner la source du texte, puis en définir l’aspect. Vous pouvez également répondre aux événements utilisateur (saisie de texte ou clic sur un lien hypertexte). Les classes TextField et Flash Text Engine vous permettent d’afficher et de gérer le texte dans Flash Player et AIR. Vous disposez de la classe TextField pour créer des objets texte à des fins d’affichage et d’entrée. La classe TextField sert de base à d’autres composants texte tels que TextArea et TextInput. La classe TextFormat permet de définir la mise en forme de caractère et paragraphe des objets TextField et vous pouvez appliquer des feuilles de style en cascade (CSS) à l’aide de la propriété Textfield.styleSheet et de la classe StyleSheet. Vous pouvez affecter directement à un champ de texte un texte au format HTML, qui peut contenir des médias intégrés (clips, fichiers SWF, fichiers GIF, fichiers PNG et fichiers JPEG). Flash Text Engine (FTE), disponible à partir de Flash Player 10 et Adobe AIR 1.5, propose une prise en charge de bas niveau pour un contrôle sophistiqué des mesures de texte, de la mise en forme et du texte bidirectionnel. Il se caractérise également par un flux de texte optimisé et une prise en charge des langues enrichie. Bien que vous puissiez utiliser Flash Text Engine pour créer et gérer des éléments texte, il est essentiellement destiné à générer des composants de manipulation du texte et nécessite des compétences accrues en matière de programmation. Text Layout Framework, qui comprend un composant de manipulation du texte basé sur Flash Text Engine, facilite l’utilisation des fonctions avancées du nouveau moteur texte. TLF est une bibliothèque extensible reposant entièrement sur ActionScript 3.0. Vous pouvez utiliser le composant TLF existant ou utiliser la structure pour créer votre propre composant de texte. La classe StageText, disponible à partir d’AIR 3, fournit un champ de saisie de texte natif. Etant donné que ce champ est mis à disposition par le système d’exploitation du périphérique, il fournit l’expérience avec laquelle les utilisateurs d’un périphérique sont le plus familiarisés. Une occurrence de StageText n’est pas un objet d’affichage. Plutôt que de l’ajouter à la liste d’affichage, affectez une scène à une occurrence, ainsi qu’une zone d’affichage sur cette scène appelée fenêtre d’affichage. L’occurrence de StageText s’affiche face à tous les objets d’affichage. Pour plus d’informations, voir : • « Utilisation de la classe TextField » à la page 385 • « Utilisation de Flash Text Engine » à la page 410 • « Utilisation de Text Layout Framework » à la page 440 • Native text input with StageText (disponible en anglais uniquement) GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 384 Principes de base de l’utilisation du texte Dernière mise à jour le 27/4/2013 Concepts importants et terminologie La liste de référence suivante contient des termes importants relatifs à la manipulation du texte : Feuilles de style en cascade Syntaxe standardisée permettant de définir les styles et la mise en forme du texte structuré en XML et en HTML. Police de périphérique Police installée sur l’ordinateur de l’utilisateur. Champ de texte dynamique Champ de texte dont le contenu peut être modifié en ActionScript, mais pas par l’utilisateur. Police incorporée Police de caractères dont les données, sous forme vectorielle, sont enregistrées dans le fichier SWF de l’application. Texte HTML Texte inséré dans un champ de texte en ActionScript qui, outre le contenu à proprement parler, comporte des balises HTML de mise en forme. Champ de saisie de texte Champ de texte dont le contenu peut être modifié soit en ActionScript, soit par l’utilisateur. Crénage Réglage de l’espace entre les paires de caractères de sorte à uniformiser l’espacement des mots et à améliorer la lisibilité du texte. Champ de texte statique Champ de texte créé dans l’environnement de création, dont le contenu ne peut pas être modifié pendant l’exécution du fichier SWF. Métrique des lignes de texte Mesure de la taille des diverses parties du texte figurant dans un champ de texte : ligne de base du texte, hauteur du sommet des caractères, taille des jambages (partie de certaines minuscules qui s’étend sous la ligne de base), etc. Interlettrage Réglage de l’espacement entre des groupes de lettres ou des blocs de texte en vue d’augmenter ou de réduire la densité pour améliorer la lisibilité du texte. 385 Dernière mise à jour le 27/4/2013 Chapitre 21 : Utilisation de la classe TextField Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez utiliser une occurrence de la classe TextField pour afficher du texte ou créer un champ de saisie de texte à l’écran dans Adobe® Flash® Player ou Adobe® AIR™. La classe TextField sert de base à d’autres composants de texte tels que TextArea ou TextInput. Le contenu des champs de texte peut être spécifié à l’avance dans le fichier SWF, chargé à partir d’un fichier texte ou d’une base de données, ou saisi par l’utilisateur dans votre application. Au sein du champ lui-même, le texte peut être du contenu HTML, avec des images incorporées. Après avoir créé une occurrence de champ de texte, vous pouvez utiliser les classes flash.text, telles que TextFormat et StyleSheet, pour contrôler l’aspect du texte. Le package flash.text contient la quasi-totalité des classes relatives à la création, à la gestion et au formatage de texte dans ActionScript. Pour mettre en forme du texte, il est nécessaire de créer un objet TextFormat et de l’affecter au champ de texte. Si le champ de texte contient du texte en HTML, vous pouvez lui appliquer un objet StyleSheet pour affecter des styles à des éléments spécifiques du texte. L’objet TextFormat ou StyleSheet contient des propriétés qui définissent l’aspect du texte, par exemple sa couleur, sa taille et sa graisse. L’objet TextFormat attribue des propriétés à l’ensemble du contenu d’un champ de texte, ou à une partie du texte seulement. Par exemple, au sein du même champ de texte, une phrase peut être en gras et en rouge, puis la suivante en italique et en bleu. Outre les classes du package flash.text, la classe flash.events.TextEvent permet de répondre aux actions de l’utilisateur liées au texte. Voir aussi « Attribution de formats texte » à la page 393 « Affichage du texte HTML » à la page 387 « Application de feuilles de style en cascade » à la page 394 Affichage du texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Bien que les outils de programmation tels qu’Adobe Flash Builder et Flash Professional offrent plusieurs options d’affichage du texte (composants liés au texte ou outils texte), la méthode d’affichage de texte par programmation la plus simple consiste à utiliser un champ de texte. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 386 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Types de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le type de texte d’un champ de texte est caractérisé par sa source : • Texte dynamique Le texte dynamique correspond au contenu chargé à partir d’une source externe, telles qu’un fichier texte ou xml, ou un service Web. • Saisie de texte Le texte saisi est le texte entré par l’utilisateur ou du texte dynamique que l’utilisateur peut modifier. Vous pouvez définir une feuille de style pour formater le texte saisi, ou utiliser la classe flash.text.TextFormat pour attribuer au champ de texte des propriétés destinées au texte saisi. Pour plus d’informations, voir « Capture du texte saisi par l’utilisateur » à la page 391. • Texte statique Le texte statique est créé par le biais de Flash Professional uniquement. Vous ne pouvez pas créer une occurrence de texte à l’aide d’ActionScript 3.0. Vous pouvez néanmoins utiliser les classes ActionScript telles que StaticText et TextSnapshot pour manipuler une occurrence de texte statique existante. Pour plus d’informations, voir « Utilisation du texte statique » à la page 399. Modification du contenu d’un champ de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez définir du texte dynamique en affectant une chaîne à la propriété flash.text.TextField.text. La chaîne est directement affectée à la propriété, comme suit : myTextField.text = "Hello World"; Vous pouvez également affecter à la propriété text une valeur issue d’une variable définie dans votre code, comme dans l’exemple suivant : package { import flash.display.Sprite; import flash.text.*; public class TextWithImage extends Sprite { private var myTextBox:TextField = new TextField(); private var myText:String = "Hello World"; public function TextWithImage() { addChild(myTextBox); myTextBox.text = myText; } } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 387 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Vous pouvez également attribuer à la propriété text une valeur issue d’une variable distante. Le chargement de valeurs textuelles à partir de sources distantes peut se faire de trois manières : • Les classes flash.net.URLLoader et flash.net.URLRequest chargent des variables à partir d’emplacements locaux ou distants. • L’attribut FlashVars est incorporé dans la page HTML qui héberge le fichier SWF et peut contenir des valeurs destinées aux variables de texte. • La classe flash.net.SharedObject gère le stockage persistant des valeurs. Pour plus d’informations, voir « Stockage des données locales » à la page 728. Affichage du texte HTML Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La propriété htmlText de la classe flash.text.TextField permet d’indiquer que la chaîne de texte contient des balises HTML de formatage du contenu. Comme le montre l’exemple suivant, vous devez affecter votre chaîne à la propriété htmlText (et non à la propriété text) pour que Flash Player ou AIR puisse afficher le texte sous forme HTML : var myText:String = "

    This is some content to render as HTML text.

    "; myTextBox.htmlText = myText; Pour la propriété htmlText, Flash Player et AIR prennent en charge un sous-ensemble de balises et d’entités HTML. La description de propriété flash.text.TextField.htmlText dans le manuel Guide de référence ActionScript 3.0 pour Flash Professional fournit des informations détaillées sur les balises et entités HTML prises en charge. Une fois que vous avez spécifié votre contenu à l’aide de la propriété htmlText, vous pouvez utiliser des feuilles de style ou la balise textformat pour gérer le formatage. Pour plus d’informations, voir « Mise en forme du texte » à la page 393. Utilisation d’images dans des champs de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’affichage du contenu sous forme de texte HTML présente un autre avantage : vous pouvez inclure des images dans le champ de texte. Il est possible de référencer une image, locale ou distante, grâce à la balise img et de la faire apparaître dans le champ de texte associé. L’exemple suivant crée un champ de texte appelé myTextBox et incorpore au texte une image JPG représentant un oeil, image stockée dans le même répertoire que le fichier SWF : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 388 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; import flash.text.*; public class TextWithImage extends Sprite { private var myTextBox:TextField; private var myText:String = "

    This is some content to test and see

    what can be rendered.

    You should see an eye image and some HTML text.

    "; public function TextWithImage() { myTextBox.width = 200; myTextBox.height = 200; myTextBox.multiline = true; myTextBox.wordWrap = true; myTextBox.border = true; addChild(myTextBox); myTextBox.htmlText = myText; } } } La balise img prend en charge les fichiers JPEG, GIF, PNG et SWF. Défilement du texte dans un champ de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Dans bien des cas, votre texte peut s’avérer plus long que le champ de texte qui le contient. Il se peut également qu’un champ de saisie permette à l’utilisateur de saisir plus de caractères qu’il ne peut en afficher en une seule fois. Les propriétés de défilement de la classe flash.text.TextField permettent de gérer du contenu long, que ce soit verticalement ou horizontalement. Ces propriétés sont les suivantes : TextField.scrollV, TextField.scrollH, maxScrollV et maxScrollH. Utilisezles pour répondre à des événements tels qu’un clic de souris ou une pression sur une touche. L’exemple ci-après crée un champ de texte de taille fixe et contenant plus de texte que le champ ne peut afficher en une seule fois. Lorsque l’utilisateur clique sur le champ de texte, le texte défile verticalement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 389 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; import flash.text.*; import flash.events.MouseEvent; public class TextScrollExample extends Sprite { private var myTextBox:TextField = new TextField(); private var myText:String = "Hello world and welcome to the show. It's really nice to meet you. Take your coat off and stay a while. OK, show is over. Hope you had fun. You can go home now. Don't forget to tip your waiter. There are mints in the bowl by the door. Thank you. Please come again."; public function TextScrollExample() { myTextBox.text = myText; myTextBox.width = 200; myTextBox.height = 50; myTextBox.multiline = true; myTextBox.wordWrap = true; myTextBox.background = true; myTextBox.border = true; var format:TextFormat = new TextFormat(); format.font = "Verdana"; format.color = 0xFF0000; format.size = 10; myTextBox.defaultTextFormat = format; addChild(myTextBox); myTextBox.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownScroll); } public function mouseDownScroll(event:MouseEvent):void { myTextBox.scrollV++; } } } Sélection et manipulation de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous pouvez sélectionner du texte, qu’il soit dynamique ou saisi. Les propriétés et méthodes de sélection de texte de la classe TextField utilisent des positions d’index pour déterminer l’étendue du texte à manipuler. Vous pouvez donc programmer la sélection du texte saisi ou dynamique, même si vous n’en connaissez pas le contenu. Remarque : si vous choisissez l’option sélectionnable associée à un champ de texte statique dans Flash Professional, le champ de texte exporté et placé dans la liste d’affichage est un champ de texte dynamique normal. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 390 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Sélection du texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La propriété flash.text.TextField.selectable a la valeur true par défaut. Vous pouvez en outre sélectionner du texte par code à l’aide de la méthode setSelection(). Par exemple, pour sélectionner un texte spécifique dans un champ de texte lorsque l’utilisateur clique dans ce dernier : var myTextField:TextField = new TextField(); myTextField.text = "No matter where you click on this text field the TEXT IN ALL CAPS is selected."; myTextField.autoSize = TextFieldAutoSize.LEFT; addChild(myTextField); addEventListener(MouseEvent.CLICK, selectText); function selectText(event:MouseEvent):void { myTextField.setSelection(49, 65); } De même, pour que le texte d’un champ de texte soit sélectionné dès son affichage initial, créez une fonction de gestion d’événement qui sera appelée lorsque le champ de texte sera ajouté à la liste d’affichage. Capture du texte sélectionné par l’utilisateur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les propriétés selectionBeginIndex et selectionEndIndex de TextField, qui sont en lecture seule (et ne peuvent donc pas être utilisées à l’aide de code pour sélectionner du texte), permettent également de capturer la sélection actuelle effectuée par l’utilisateur. Par ailleurs, les champs de texte saisis peuvent utiliser la propriété caretIndex. Par exemple, ce code renvoie les valeurs d’index du texte sélectionné par l’utilisateur : var myTextField:TextField = new TextField(); myTextField.text = "Please select the TEXT IN ALL CAPS to see the index values for the first and last letters."; myTextField.autoSize = TextFieldAutoSize.LEFT; addChild(myTextField); addEventListener(MouseEvent.MOUSE_UP, selectText); function selectText(event:MouseEvent):void { trace("First letter index position: " + myTextField.selectionBeginIndex); trace("Last letter index position: " + myTextField.selectionEndIndex); } Vous pouvez également appliquer un ensemble de propriétés de l’objet TextFormat à la sélection pour modifier l’aspect du texte. Pour plus d’informations sur l’application d’un ensemble de propriétés TextFormat au texte sélectionné, voir « Formatage de plages de texte au sein d’un champ de texte » à la page 396. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 391 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Capture du texte saisi par l’utilisateur Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Par défaut, la propriété type d’un champ de texte est définie sur dynamic. Si vous attribuez à cette propriété type la valeur input à l’aide de la classe TextFieldType, vous pouvez recueillir la saisie de l’utilisateur et enregistrer cette valeur pour l’utiliser dans d’autres zones de l’application. Les champs de texte saisi sont utiles dans les formulaires et toute autre application qui attend que l’utilisateur définisse une valeur de texte à utiliser ailleurs dans le programme. Par exemple, le code suivant crée un champ de texte de saisie appelé myTextBox. Lorsque l’utilisateur saisit du texte dans le champ, l’événement textInput est déclenché. Un gestionnaire d’événement appelé textInputCapture capture la chaîne de texte saisie et l’attribue à une variable. Flash Player ou AIR affiche le nouveau texte dans un autre champ de texte appelé myOutputBox. package { import flash.display.Sprite; import flash.display.Stage; import flash.text.*; import flash.events.*; public class CaptureUserInput extends Sprite { private var myTextBox:TextField = new TextField(); private var myOutputBox:TextField = new TextField(); private var myText:String = "Type your text here."; public function CaptureUserInput() { captureText(); } public function captureText():void { myTextBox.type = TextFieldType.INPUT; myTextBox.background = true; addChild(myTextBox); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 392 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 myTextBox.text = myText; myTextBox.addEventListener(TextEvent.TEXT_INPUT, textInputCapture); } public function textInputCapture(event:TextEvent):void { var str:String = myTextBox.text; createOutputBox(str); } public function createOutputBox(str:String):void { myOutputBox.background = true; myOutputBox.x = 200; addChild(myOutputBox); myOutputBox.text = str; } } } Restriction de la saisie de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les champs de texte de saisie sont souvent utilisés dans les formulaires et les boîtes de dialogue des applications. Il peut donc être judicieux de limiter le type de caractères que l’utilisateur peut saisir, ou même de masquer la saisie (pour un mot de passe par exemple). La classe flash.text.TextField possède une propriété displayAsPassword et une propriété restrict qui permettent de contrôler la saisie par l’utilisateur. La propriété displayAsPassword masque simplement le texte (en l’affichant sous forme d’astérisques) à mesure que l’utilisateur le saisit. Lorsque displayAsPassword a la valeur true, les commandes Couper et Copier, ainsi que les raccourcis clavier correspondants ne fonctionnent pas. Comme le montre l’exemple suivant, vous pouvez attribuer la propriété displayAsPassword, comme vous le feriez pour des propriétés d’arrière-plan et de couleur : myTextBox.type = TextFieldType.INPUT; myTextBox.background = true; myTextBox.displayAsPassword = true; addChild(myTextBox); La propriété restrict est légèrement plus compliquée, puisque vous devez spécifier les caractères que l’utilisateur peut saisir dans le champ de texte. Il est possible d’autoriser la saisie de lettres spécifiques et de nombres, mais aussi de plages de lettres, de nombres et de caractères. Le code ci-après permet à l’utilisateur de saisir uniquement des lettres majuscules (pas de nombres, ni de caractères spéciaux) dans le champ de texte : myTextBox.restrict = "A-Z"; ActionScript 3.0 utilise le tiret pour définir les séries et le caractère circonflexe pour exclure des caractères. Pour plus d’informations sur la définition de restrictions associées à un champ de texte de saisie, voir l’entrée flash.text.TextField.restrict dans le Guide de référence ActionScript 3.0 pour Flash Professional. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 393 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Remarque : si vous utilisez la propriété flash.text.TextField.restrict, le moteur d’exécution convertit automatiquement les lettres restreintes en caractères de casse autorisée. Si vous utilisez la propriété fl.text.TLFTextField.restrict (c’est-à-dire si vous utilisez un champ de texte TLF), le moteur d’exécution ignore les lettres restreintes. Mise en forme du texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Plusieurs options permettent de programmer la mise en forme du texte à afficher. Vous pouvez définir ses propriétés directement dans l’occurrence de TextField, par exemple TextFIeld.thickness, TextField.textColor et TextField.textHeight.Vous pouvez aussi désigner le contenu du champ de texte à l’aide de la propriété htmlText et utiliser des balises HTML prises en charge, telles que b, i et u. Vous pouvez enfin appliquer des objets TextFormat aux champs de texte contenant du texte brut, ou des objets StyleSheet aux champs contenant la propriété htmlText. Les objets TextFormat et StyleSheet offrent un meilleur contrôle et davantage de cohérence sur l’aspect du texte pour l’ensemble de l’application. Il est possible de définir un objet TextFormat ou StyleSheet et de l’appliquer à une partie ou à l’ensemble des champs de texte de l’application. Attribution de formats texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe TextFormat permet de définir différentes propriétés d’affichage du texte et de les appliquer à tout le contenu d’un objet TextField, ou à une plage de texte. L’exemple suivant applique un objet TextFormat à un objet TextField complet, puis un second objet TextFormat à une plage de texte de cet objet TextField : var tf:TextField = new TextField(); tf.text = "Hello Hello"; var format1:TextFormat = new TextFormat(); format1.color = 0xFF0000; var format2:TextFormat = new TextFormat(); format2.font = "Courier"; tf.setTextFormat(format1); var startRange:uint = 6; tf.setTextFormat(format2, startRange); addChild(tf); La méthode TextField.setTextFormat() n’affecte que le texte qui est déjà affiché dans le champ de texte. Si le contenu de l’objet TextField change, il peut être nécessaire d’appeler à nouveau la méthode TextField.setTextFormat() pour ré-appliquer la mise en forme. Vous pouvez également utiliser la propriété defaultTextFormat de TextField pour spécifier le format à utiliser pour le texte saisi par l’utilisateur. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 394 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Application de feuilles de style en cascade Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les champs de texte peuvent contenir du texte brut ou du texte au format HTML. Le texte brut est stocké dans la propriété text de l’occurrence, et le texte HTML dans la propriété htmlText. Vous pouvez utiliser des déclarations de styles CSS pour définir des styles de texte à appliquer ensuite à différents champs de texte. Une déclaration de style CSS peut être créée par code ou chargée lors de l’exécution à partir d’un fichier CSS externe. C’est la classe flash.text.StyleSheet qui gère les styles CSS. La classe StyleSheet ne reconnaît qu’un nombre limité de propriétés CSS. La liste détaillée des propriétés de style prises en charge par la classe StyleSheet figure dans l’entrée flash.textStylesheet du Guide de référence ActionScript 3.0 pour Flash Professional. Comme le montre l’exemple suivant, vous pouvez créer des feuilles de style CSS et les appliquer à du texte HTML au moyen de l’objet StyleSheet : var style:StyleSheet = new StyleSheet(); var styleObj:Object = new Object(); styleObj.fontSize = "bold"; styleObj.color = "#FF0000"; style.setStyle(".darkRed", styleObj); var tf:TextField = new TextField(); tf.styleSheet = style; tf.htmlText = "Red apple"; addChild(tf); Après la création de l’objet StyleSheet, le code crée un objet simple pour contenir un jeu de propriétés de déclaration de style. Il appelle ensuite la méthode StyleSheet.setStyle(), qui ajoute le nouveau style à la feuille de style sous le nom « .darkred ». Puis il applique les formats de la feuille de styles en affectant l’objet StyleSheet à la propriété styleSheet de TextField. Pour que les styles CSS puissent prendre effet, il est nécessaire d’appliquer la feuille de style à l’objet TextField avant de définir la propriété htmlText. Par essence, un champ de texte doté d’une feuille de style n’est pas modifiable. Si vous attribuez une feuille de style à un champ de texte de saisie, le champ de texte affiche les propriétés de la feuille de style, mais le champ de texte ne permet pas à l’utilisateur de saisir du texte. En outre, vous ne pouvez pas utiliser les méthodes ActionScript suivantes sur un champ de texte doté d’une feuille de style : • La méthode TextField.replaceText() • La méthode TextField.replaceSelectedText() • La propriété TextField.defaultTextFormat • La méthode TextField.setTextFormat() Si un champ de texte est doté d’une feuille de style mais que par la suite la propriété TextField.styleSheet reçoit la valeur null, TextField.text et TextField.htmlText ajoutent des balises et des attributs à leurs contenus afin d’incorporer le formatage de la feuille de style précédemment attribuée. Pour préserver la propriété htmlText d’origine, enregistrez-la dans une variable avant d’attribuer la valeur null à la feuille de style. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 395 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Chargement de fichiers CSS externes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’utilisation de feuilles de style CSS pour la mise en forme offre plus de possibilités s’il est possible de charger les informations de CSS à partir d’un fichier externe lors de l’exécution. Si les données CSS sont externes à l’application, il est possible de changer le style visuel du texte sans devoir modifier le code source ActionScript 3.0. En effet, après le déploiement de l’application, vous pouvez encore modifier le fichier CSS externe pour obtenir un nouvel aspect, sans devoir redéployer le fichier SWF de l’application. La méthode StyleSheet.parseCSS() convertit une chaîne contenant des données CSS en déclarations de style dans l’objet StyleSheet. L’exemple suivant montre comment lire un fichier CSS externe et appliquer ses déclarations de style à un objet TextField. Voici le contenu du fichier CSS à charger. Il est appelé « example.css » : p { font-family: Times New Roman, Times, _serif; font-size: 14; } h1 { font-family: Arial, Helvetica, _sans; font-size: 20; font-weight: bold; } .bluetext { color: #0000CC; } Voici maintenant le code ActionScript d’une classe qui charge le fichier example.css et en applique les styles au contenu de l’objet TextField : package { import flash.display.Sprite; import flash.events.Event; import flash.net.URLLoader; import flash.net.URLRequest; import flash.text.StyleSheet; import flash.text.TextField; import flash.text.TextFieldAutoSize; public class CSSFormattingExample extends Sprite { var loader:URLLoader; var field:TextField; var exampleText:String = "

    This is a headline

    " + "

    This is a line of text. " + "This line of text is colored blue.

    "; public function CSSFormattingExample():void { field = new TextField(); field.width = 300; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 396 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 field.autoSize = TextFieldAutoSize.LEFT; field.wordWrap = true; addChild(field); var req:URLRequest = new URLRequest("example.css"); loader = new URLLoader(); loader.addEventListener(Event.COMPLETE, onCSSFileLoaded); loader.load(req); } public function onCSSFileLoaded(event:Event):void { var sheet:StyleSheet = new StyleSheet(); sheet.parseCSS(loader.data); field.styleSheet = sheet; field.htmlText = exampleText; } } } Lorsque les données de CSS sont chargées, la méthode onCSSFileLoaded() s’exécute et appelle la méthode StyleSheet.parseCSS() pour transférer les déclarations de style à l’objet StyleSheet. Formatage de plages de texte au sein d’un champ de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe flash.text.TextField contient une méthode particulièrement utile, setTextFormat(). La méthode setTextFormat() permet d’affecter des propriétés spécifiques à une partie du contenu d’un champ de texte en réponse à une action de l’utilisateur, par exemple pour rappeler à l’utilisateur que certains champs d’un formulaire doivent être renseignés, ou encore pour changer l’aspect d’un passage de texte si l’utilisateur sélectionne une partie de ce texte. L’exemple suivant utilise la méthode TextField.setTextFormat() sur une plage de caractères pour modifier l’aspect d’une partie du contenu de myTextField lorsque l’utilisateur clique dans ce champ de texte : var myTextField:TextField = new TextField(); myTextField.text = "No matter where you click on this text field the TEXT IN ALL CAPS changes format."; myTextField.autoSize = TextFieldAutoSize.LEFT; addChild(myTextField); addEventListener(MouseEvent.CLICK, changeText); var myformat:TextFormat = new TextFormat(); myformat.color = 0xFF0000; myformat.size = 18; myformat.underline = true; function changeText(event:MouseEvent):void { myTextField.setTextFormat(myformat, 49, 65); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 397 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Fonctions avancées d’affichage de texte Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le package flash.text d’ActionScript 3.0 offre plusieurs classes qui permettent de contrôler les propriétés du texte affiché, notamment les polices intégrées, les paramètres d’anticrènelage, le canal alpha et autres paramètres spécifiques. Le Guide de référence ActionScript 3.0 pour Flash Professional fournit des descriptions détaillées de ces classes et de leurs propriétés, notamment des classes CSMSettings, Font et TextRenderer. Utilisation de polices incorporées Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si vous spécifiez une police précise pour un objet TextField de votre application, Flash Player ou AIR recherche une police résidente du même nom sur l’ordinateur de l’utilisateur. Si cette police n’est pas chargée sur cet ordinateur, ou s’il existe une police de ce nom mais dans une version légèrement différente, le texte peut apparaître très différent de ce que vous aviez prévu. Par défaut, le texte s’affiche dans la police Times Roman. Pour que l’utilisateur voie exactement la police voulue, vous pouvez incorporer cette police dans le fichier SWF de votre application. Les polices intégrées présentent de nombreux avantages : • Les caractères des polices incorporées sont anticrènelés, ce qui les rend plus agréables à lire, en particulier pour les grandes tailles de texte. • Il est possible de faire pivoter les polices incorporées. • Il est possible de rendre transparent ou semi-transparent le texte des polices incorporées. • Il est possible d’utiliser le style CSS kerning (crénage) avec les polices incorporées. Le principal inconvénient des polices incorporées est l’augmentation de la taille du fichier de l’application. La méthode exacte à utiliser pour intégrer un fichier de police dans le fichier SWF de l’application varie selon l’environnement de développement. Une fois la police intégrée, il est possible de faire en sorte que l’objet TextField utilise la police correcte : • Mettez la propriété embedFonts de l’objet TextField sur true. • Créez un objet TextFormat, donnez à sa propriété fontFamily le nom de la police incorporée, et appliquez l’objet TextFormat au TextField. Dans le cas d’une police incorporée, la propriété fontFamily ne doit contenir qu’un seul nom. Elle ne peut pas utiliser une liste de polices séparées par des virgules. • Si vous utilisez des styles CSS pour les polices d’objets TextFields, donnez à la propriété CSS font-family le nom de la police incorporée. Si vous voulez utiliser une police incorporée, la propriété font-family ne doit contenir qu’un seul nom, et non pas une liste de noms. Intégration d’une police dans Flash Flash Professional vous permet d’intégrer pratiquement toutes les polices installées sur votre système, notamment les polices TrueType et les polices Postscript Type 1. Il existe plusieurs façons d’intégrer des polices dans une application. Vous pouvez par exemple : • définir la police et les propriétés de style d’un objet TextField sur la Scène, puis en cocher la case Incorporer les polices ; • créer et référencer un symbole de police ; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 398 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 • créer et utiliser une bibliothèque d’exécution partagée contenant les symboles de la police intégrée. Pour plus d’informations sur l’intégration de polices dans les applications, voir « Polices intégrées pour champs de texte dynamique ou de saisie » dans Utilisation de Flash. Intégration d’une police dans Flex Il existe plusieurs façons d’intégrer des polices dans une application Flex. Vous pouvez par exemple : • utiliser la balise de métadonnées [Embed] dans un script ; • utiliser la déclaration de style @font-face ; • définir la classe de la police et l’intégrer par le biais de la balise [Embed]. Seules les polices TrueType peuvent directement être intégrées dans une application Flex. Les polices dans un autre format, telles que les polices Postscript Type 1, doivent tout d’abord être intégrées dans un fichier SWF à l’aide de Flash Professional ; vous pouvez ensuite utiliser ce fichier SWF dans votre application Flex. Pour plus d’informations sur l’utilisation de polices intégrées dans Flex à partir de fichiers SWF, voir « Intégration de polices à partir de fichiers SWF » dans le manuel Utilisation de Flex 4. Voir aussi Incorporation de polices pour assurer la cohérence de l’apparence du texte Peter deHaan : Embedding fonts (disponible en anglais uniquement) Divillysausages.com : AS3 Font embedding masterclass (disponible en anglais uniquement) Contrôle de la netteté, de l’épaisseur et de l’anticrènelage Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Par défaut, Flash Player ou AIR détermine les paramètres de contrôle d’affichage du texte (netteté, épaisseur et anticrènelage) qui s’appliquent lorsque le texte change de taille et de couleur ou s’affiche sur différents arrière-plans. Dans certains cas, vous pouvez définir ces paramètres, par exemple si le texte est très petit ou très gros, ou s’il s’affiche sur plusieurs arrière-plans. La classe flash.text.TextRenderer et les classes associées, telles que CSMSettings, permettent de remplacer les paramètres de Flash Player ou d’AIR. Elles offrent un contrôle précis de la qualité d’affichage du texte incorporé. Pour plus d’informations sur les polices intégrées, voir « Utilisation de polices incorporées » à la page 397. Remarque : la propriété .antiAliasType de la classe flash.text.TextField doit avoir la valeur AntiAliasType.ADVANCED pour que vous puissiez définir la netteté, l’épaisseur ou la propriété gridFitType, ou pour que vous puissiez utiliser la méthode TextRenderer.setAdvancedAntiAliasingTable(). L’exemple suivant applique des propriétés personnalisées de modulation continue du trait (CSM) et de mise en forme au texte affiché, en utilisant la police incorporée myFont. Lorsque l’utilisateur clique sur le texte affiché, Flash Player ou Adobe AIR applique ces paramètres personnalisés : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 399 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 var format:TextFormat = new TextFormat(); format.color = 0x336699; format.size = 48; format.font = "myFont"; var myText:TextField = new TextField(); myText.embedFonts = true; myText.autoSize = TextFieldAutoSize.LEFT; myText.antiAliasType = AntiAliasType.ADVANCED; myText.defaultTextFormat = format; myText.selectable = false; myText.mouseEnabled = true; myText.text = "Hello World"; addChild(myText); myText.addEventListener(MouseEvent.CLICK, clickHandler); function clickHandler(event:Event):void { var myAntiAliasSettings = new CSMSettings(48, 0.8, -0.8); var myAliasTable:Array = new Array(myAntiAliasSettings); TextRenderer.setAdvancedAntiAliasingTable("myFont", FontStyle.ITALIC, TextColorType.DARK_COLOR, myAliasTable); } Utilisation du texte statique Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Le texte statique est créé dans Flash Professional uniquement. Il est impossible d’instancier du texte statique en ActionScript. Le texte statique est utile si le contenu textuel est court et ne doit pas changer (contrairement au texte dynamique). Vous pouvez assimiler le texte statique à un élément graphique comparable à un cercle ou un carré dessiné sur la Scène dans Flash Professional. Bien que le texte statique offre moins de possibilités que le texte dynamique, ActionScript 3.0 permet de lire les valeurs des propriétés du texte statique à l’aide de la classe StaticText. En outre, vous pouvez utiliser la classe TextSnapshot pour extraire des valeurs du texte statique. Accès aux champs de texte statique à l’aide de la classe StaticText Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vous utilisez généralement la classe flash.text.StaticText dans le panneau Actions de Flash Professional pour agir sur une occurrence de texte statique placée sur la scène. Vous pouvez également travailler dans des fichiers ActionScript qui interagissent avec le fichier SWF contenant le texte statique. Dans les deux cas, il est impossible de créer par code une occurrence de texte statique. Le texte statique est créé dans Flash Professional. Pour créer une référence à un champ de texte statique existant, vous pouvez effectuer une itération sur les éléments de la liste d’affichage et affecter une variable. Exemple : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 400 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 for (var i = 0; i < this.numChildren; i++) { var displayitem:DisplayObject = this.getChildAt(i); if (displayitem instanceof StaticText) { trace("a static text field is item " + i + " on the display list"); var myFieldLabel:StaticText = StaticText(displayitem); trace("and contains the text: " + myFieldLabel.text); } } Lorsque vous disposez d’une référence à un champ de texte statique, vous pouvez utiliser les propriétés de ce champ dans ActionScript 3.0. Le code suivant est associé à une image du scénario et suppose qu’une variable appelée myFieldLabel est affectée à une référence à un champ de texte statique. Un champ de texte dynamique myField est positionné relativement aux valeurs x et y de myFieldLabel et affiche à nouveau la valeur de myFieldLabel. var myField:TextField = new TextField(); addChild(myField); myField.x = myFieldLabel.x; myField.y = myFieldLabel.y + 20; myField.autoSize = TextFieldAutoSize.LEFT; myField.text = "and " + myFieldLabel.text Utilisation de la classe TextSnapshot Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour travailler par programmation avec une occurrence de texte statique existante, utilisez la classe flash.text.TextSnapshot pour modifier la propriété textSnapshot d’un objet flash.display.DisplayObjectContainer. En d’autres termes, créez une occurrence de TextSnapshot à partir de la propriété DisplayObjectContainer.textSnapshot. Vous pouvez alors appliquer des méthodes à cette occurrence afin d’extraire des valeurs ou de sélectionner des portions du texte statique. Par exemple, placez un champ de texte statique contenant le texte « TextSnapshot Example » sur la scène. Ajoutez le code ActionScript suivant à l’image 1 du scénario : var mySnap:TextSnapshot = this.textSnapshot; var count:Number = mySnap.charCount; mySnap.setSelected(0, 4, true); mySnap.setSelected(1, 2, false); var myText:String = mySnap.getSelectedText(false); trace(myText); La classe TextSnapshot est utile pour extraire le texte des champs de texte statique dans un fichier SWF chargé, au cas où vous souhaiteriez utiliser ce texte comme valeur dans une autre zone de l’application. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 401 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 Exemple TextField : mise en forme du texte dans le style « article de journal » Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple « Article de journal » met en forme le texte pour lui donner l’aspect d’un article de journal. Le texte saisi peut contenir un gros titre, un intertitre et le corps de l’article. En fonction d’une largeur et d’une hauteur d’affichage, cet exemple met en forme le gros titre et l’intertitre pour qu’ils occupent toute la largeur disponible. Le texte de l’article est réparti sur plusieurs colonnes. Cet exemple illustre les techniques de programmation en ActionScript suivantes : • Extension de la classe TextField • Chargement et application d’un fichier CSS externe • Conversion de styles CSS en objets TextFormat • Utilisation de la classe TextLineMetrics pour obtenir des informations sur la taille d’affichage du texte Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers de l’application News Layout se trouvent dans le dossier Samples/NewsLayout. L’application se compose des fichiers suivants : Lecture du fichier CSS externe Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application News Layout commence par récupérer le texte de l’article à partir d’un fichier XML local. Elle lit ensuite un fichier CSS externe contenant les informations de mise en forme pour le gros titre, l’intertitre et le texte. Ce fichier CSS définit trois styles, un style de paragraphe standard pour l’article et les styles h1 et h2, respectivement pour le gros titre et l’intertitre. Fichier Description NewsLayout.mxml ou NewsLayout.fla Interface utilisateur de l’application pour Flex (MXML) ou Flash (FLA). com/example/programmingas3/ne wslayout/StoryLayoutComponent.a s Classe Flex UIComponent qui place l’occurrence de StoryLayout. com/example/programmingas3/ne wslayout/StoryLayout.as Principale classe ActionScript chargée d’organiser les composants d’un article pour leur affichage. com/example/programmingas3/ne wslayout/FormattedTextField.as Sous-classe de la classe TextField qui gère son propre objet TextFormat. com/example/programmingas3/ne wslayout/HeadlineTextField.as Sous-classe de la classe FormattedTextField qui ajuste la taille des polices en fonction de la largeur voulue. com/example/programmingas3/ne wslayout/MultiColumnTextField.as Classe ActionScript qui répartit le texte de l’article sur plusieurs colonnes. story.css Fichier CSS définissant les styles du texte pour la mise en page. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 402 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 p { font-family: Georgia, "Times New Roman", Times, _serif; font-size: 12; leading: 2; text-align: justify; indent: 24; } h1 { font-family: Verdana, Arial, Helvetica, _sans; font-size: 20; font-weight: bold; color: #000099; text-align: left; } h2 { font-family: Verdana, Arial, Helvetica, _sans; font-size: 16; font-weight: normal; text-align: left; } La technique utilisée pour lire le fichier CSS externe est identique à celle décrite à la section « Chargement de fichiers CSS externes » à la page 395. Après le chargement du fichier CSS, l’application exécute la méthode onCSSFileLoaded(), représentée ci-dessous. public function onCSSFileLoaded(event:Event):void { this.sheet = new StyleSheet(); this.sheet.parseCSS(loader.data); h1Format = getTextStyle("h1", this.sheet); if (h1Format == null) { h1Format = getDefaultHeadFormat(); } h2Format = getTextStyle("h2", this.sheet); if (h2Format == null) { h2Format = getDefaultHeadFormat(); h2Format.size = 16; } pFormat = getTextStyle("p", this.sheet); if (pFormat == null) { pFormat = getDefaultTextFormat(); pFormat.size = 12; } displayText(); } La méthode onCSSFileLoaded() crée un objet StyleSheet qui analyse les données du fichier CSS. Le texte principal de l’article est affiché dans un objet MultiColumnTextField, qui peut utiliser directement un objet StyleSheet. Toutefois, les champs du gros titre utilisent la classe HeadlineTextField, qui utilise un objet TextFormat pour sa mise en forme. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 403 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 La méthode onCSSFileLoaded() appelle deux fois la méthode getTextStyle() pour convertir une déclaration de style CSS en un objet TextFormat destiné aux deux objets HeadlineTextField. public function getTextStyle(styleName:String, ss:StyleSheet):TextFormat { var format:TextFormat = null; var style:Object = ss.getStyle(styleName); if (style != null) { var colorStr:String = style.color; if (colorStr != null && colorStr.indexOf("#") == 0) { style.color = colorStr.substr(1); } format = new TextFormat(style.fontFamily, style.fontSize, style.color, (style.fontWeight == "bold"), (style.fontStyle == "italic"), (style.textDecoration == "underline"), style.url, style.target, style.textAlign, style.marginLeft, style.marginRight, style.indent, style.leading); if (style.hasOwnProperty("letterSpacing")) { format.letterSpacing = style.letterSpacing; } } return format; } Les noms de propriétés et la signification de leurs valeurs diffèrent entre les déclarations de style CSS et les objets TextFormat. La méthode getTextStyle() transforme donc les valeurs des propriétés CSS dans les valeurs attendues par l’objet TextFormat. Disposition des éléments de l’article sur la page Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe StoryLayout formate et met en page les champs de texte dévolus au gros titre, à l’intertitre et à l’article dans le style d’une page de journal. La méthode displayText() crée et place les divers champs. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 404 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 public function displayText():void { headlineTxt = new HeadlineTextField(h1Format); headlineTxt.wordWrap = true; headlineTxt.x = this.paddingLeft; headlineTxt.y = this.paddingTop; headlineTxt.width = this.preferredWidth; this.addChild(headlineTxt); headlineTxt.fitText(this.headline, 1, true); subtitleTxt = new HeadlineTextField(h2Format); subtitleTxt.wordWrap = true; subtitleTxt.x = this.paddingLeft; subtitleTxt.y = headlineTxt.y + headlineTxt.height; subtitleTxt.width = this.preferredWidth; this.addChild(subtitleTxt); subtitleTxt.fitText(this.subtitle, 2, false); storyTxt = new MultiColumnText(this.numColumns, 20, this.preferredWidth, 400, true, this.pFormat); storyTxt.x = this.paddingLeft; storyTxt.y = subtitleTxt.y + subtitleTxt.height + 10; this.addChild(storyTxt); storyTxt.text = this.content; ... Chaque champ est placé sous le champ précédent en effectuant le calcul suivant : la propriété y du champ est égale à la propriété y du champ précédent, plus sa hauteur. Ce calcul dynamique de position est nécessaire, car les objets HeadlineTextField et MultiColumnTextField peuvent changer de hauteur en fonction de leur contenu. Modification de la taille de la police en fonction de la taille du champ Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Sur la base d’une largeur en pixels et d’un nombre maximum de lignes à afficher, l’objet HeadlineTextField modifie la taille de la police pour adapter le texte aux dimensions du champ. Si le texte est court, la police est de grande taille, créant ainsi un gros titre de style tabloïde. Si le texte est long, la police est de plus petite taille. La méthode HeadlineTextField.fitText() reproduite ci-dessous est chargée du redimensionnement du texte : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 405 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 public function fitText(msg:String, maxLines:uint = 1, toUpper:Boolean = false, targetWidth:Number = -1):uint { this.text = toUpper ? msg.toUpperCase() : msg; if (targetWidth == -1) { targetWidth = this.width; } var pixelsPerChar:Number = targetWidth / msg.length; var pointSize:Number = Math.min(MAX_POINT_SIZE, Math.round(pixelsPerChar * 1.8 * maxLines)); if (pointSize < 6) { // the point size is too small return pointSize; } this.changeSize(pointSize); if (this.numLines > maxLines) { return shrinkText(--pointSize, maxLines); } else { return growText(pointSize, maxLines); } } public function growText(pointSize:Number, maxLines:uint = 1):Number { if (pointSize >= MAX_POINT_SIZE) { return pointSize; } this.changeSize(pointSize + 1); if (this.numLines > maxLines) { // set it back to the last size this.changeSize(pointSize); return pointSize; } else { return growText(pointSize + 1, maxLines); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 406 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 } public function shrinkText(pointSize:Number, maxLines:uint=1):Number { if (pointSize <= MIN_POINT_SIZE) { return pointSize; } this.changeSize(pointSize); if (this.numLines > maxLines) { return shrinkText(pointSize - 1, maxLines); } else { return pointSize; } } La méthode HeadlineTextField.fitText() utilise une technique récursive simple pour dimensionner le texte. Elle estime d’abord un nombre moyen de pixels par caractère pour le texte, puis calcule une taille de départ. Elle change alors la taille de la police et vérifie si le texte a renvoyé des mots à la ligne et si le nombre maximal de lignes est dépassé. Si c’est le cas, elle appelle la méthode shrinkText() pour réduire la taille du texte, et teste à nouveau. Si le nombre de lignes n’est pas trop important, elle appelle la méthode growText() pour augmenter la taille du texte, et teste à nouveau. Ce processus s’interrompt lorsque l’augmentation de taille du texte d’un seul point crée un nombre de lignes trop élevé. Répartition du texte sur plusieurs colonnes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe MultiColumnTextField répartit le texte entre plusieurs objets TextField qui sont organisés comme des colonnes de texte sur une page de journal. Le constructeur de MultiColumnTextField() crée tout d’abord un tableau d’objets TextField, un pour chaque colonne : for (var i:int = 0; i < cols; i++) { var field:TextField = new TextField(); field.multiline = true; field.autoSize = TextFieldAutoSize.NONE; field.wordWrap = true; field.width = this.colWidth; field.setTextFormat(this.format); this.fieldArray.push(field); this.addChild(field); } Chaque objet TextField est ajouté au tableau et à la liste d’affichage à l’aide de la méthode addChild(). Si la propriété text ou styleSheet de StoryLayout change, la méthode layoutColumns() est appelée pour réafficher le texte. La méthode layoutColumns() appelle la méthode getOptimalHeight() pour déterminer la hauteur correcte en pixels nécessaire pour adapter tout le texte en fonction de la largeur disponible. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 407 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 public function getOptimalHeight(str:String):int { if (field.text == "" || field.text == null) { return this.preferredHeight; } else { this.linesPerCol = Math.ceil(field.numLines / this.numColumns); var metrics:TextLineMetrics = field.getLineMetrics(0); this.lineHeight = metrics.height; var prefHeight:int = linesPerCol * this.lineHeight; return prefHeight + 4; } } La méthode getOptimalHeight() calcule d’abord la largeur de chaque colonne. Elle définit ensuite la propriété htmlText du premier objet TextField du tableau. La méthode getOptimalHeight() utilise ce premier objet TextField pour connaître le nombre total de lignes renvoyées à la ligne, et en déduit donc le nombre de lignes optimal pour chaque colonne. Elle appelle ensuite la méthode TextField.getLineMetrics() pour obtenir un objet TextLineMetrics contenant des informations sur la taille du texte de la première ligne. La propriété TextLineMetrics.height représente la hauteur totale (en pixels) d’une ligne de texte, avec les mesures ascendantes, descendantes et l’interligne. La hauteur optimale de l’objet MultiColumnTextField est donc la hauteur de ligne multipliée par le nombre de lignes par colonne, plus 4 pour tenir compte de la bordure de deux pixels en haut et en bas de l’objet TextField. Voici le code complet de la méthode layoutColumns() : public function layoutColumns():void { if (this._text == "" || this._text == null) { return; } var field:TextField = fieldArray[0] as TextField; field.text = this._text; field.setTextFormat(this.format); this.preferredHeight = this.getOptimalHeight(field); var remainder:String = this._text; var fieldText:String = ""; var lastLineEndedPara:Boolean = true; var indent:Number = this.format.indent as Number; for (var i:int = 0; i < fieldArray.length; i++) { field = this.fieldArray[i] as TextField; field.height = this.preferredHeight; field.text = remainder; field.setTextFormat(this.format); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 408 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 var lineLen:int; if (indent > 0 && !lastLineEndedPara && field.numLines > 0) { lineLen = field.getLineLength(0); if (lineLen > 0) { field.setTextFormat(this.firstLineFormat, 0, lineLen); } } field.x = i * (colWidth + gutter); field.y = 0; remainder = ""; fieldText = ""; var linesRemaining:int = field.numLines; var linesVisible:int = Math.min(this.linesPerCol, linesRemaining); for (var j:int = 0; j < linesRemaining; j++) { if (j < linesVisible) { fieldText += field.getLineText(j); } else { remainder +=field.getLineText(j); } } field.text = fieldText; field.setTextFormat(this.format); if (indent > 0 && !lastLineEndedPara) { lineLen = field.getLineLength(0); if (lineLen > 0) { field.setTextFormat(this.firstLineFormat, 0, lineLen); } } var lastLine:String = field.getLineText(field.numLines - 1); var lastCharCode:Number = lastLine.charCodeAt(lastLine.length - 1); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 409 Utilisation de la classe TextField Dernière mise à jour le 27/4/2013 if (lastCharCode == 10 || lastCharCode == 13) { lastLineEndedPara = true; } else { lastLineEndedPara = false; } if ((this.format.align == TextFormatAlign.JUSTIFY) && (i < fieldArray.length - 1)) { if (!lastLineEndedPara) { justifyLastLine(field, lastLine); } } } } Lorsque la propriété preferredHeight a été définie par un appel à la méthode getOptimalHeight, la méthode layoutColumns() parcourt les objets TextField et définit la hauteur de chacun avec la valeur preferredHeight. La méthode layoutColumns() distribue ensuite le nombre de lignes de texte adapté à chaque champ, de sorte qu’aucun défilement ne se produise dans l’un d’eux et que le texte de chaque champ enchaîne sur celui du champ précédent. Si le style d’alignement du texte a été défini sur « justifier », la méthode justifyLastLine() est appelée pour justifier la ligne finale du texte dans un champ. Dans le cas contraire, la dernière ligne est considérée comme une ligne de fin de paragraphe et n’est donc pas justifiée. 410 Dernière mise à jour le 27/4/2013 Chapitre 22 : Utilisation de Flash Text Engine Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Adobe® Flash® Text Engine (FTE), disponible à partir de Flash Player 10 et Adobe® AIR™1.5, propose une prise en charge de bas niveau pour un contrôle sophistiqué des mesures de texte, de la mise en forme et du texte bidirectionnel. Il se caractérise par un flux de texte optimisé et une prise en charge des langues enrichie. Bien qu’il puisse être utilisé pour créer et gérer de simples éléments de texte, FTE est l’outil de base pour les développeurs qui souhaitent créer des composants d’édition de texte. En tant que tel, Flash Text Engine nécessite des connaissances avancées en programmation. Pour afficher des éléments de texte simples, voir « Utilisation de la classe TextField » à la page 385. Text Layout Framework (TLF), qui comprend un composant de manipulation de texte basé sur FTE, propose une méthode d’utilisation de ses fonctions avancées plus conviviale. TLF est une bibliothèque extensible reposant entièrement sur ActionScript 3.0. Vous pouvez utiliser le composant TLF existant ou utiliser la structure pour créer votre propre composant de texte. Pour plus d’informations, voir « Utilisation de Text Layout Framework » à la page 440. Voir aussi Package flash.text.engine Création et affichage de texte Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Les classes qui constituent Flash Text Engine vous permettent de créer, de mettre en forme et de contrôler le texte. Les classes suivantes constituent les éléments de base pour la création et l’affichage de texte avec Flash Text Engine : • TextElement/GraphicElement/GroupElement : renferment le contenu d’une occurrence de TextBlock • ElementFormat : spécifie les attributs de mise en forme du contenu d’une occurrence de TextBlock • TextBlock : classe usine pour la création d’un paragraphe de texte • TextLine : ligne de texte créée à partir de TextBlock Pour afficher du texte, créez un objet TextElement à partir d’un élément String en utilisant un objet ElementFormat pour définir les caractéristiques de mise en forme. Affectez l’objet TextElement à la propriété content d’un objet TextBlock. Créez les lignes de texte à afficher en appelant la méthode TextBlock.createTextLine(). La méthode createTextLine() renvoie un objet TextLine qui contient le nombre de caractères de la chaîne correspondant à la largeur spécifiée. Appelez plusieurs fois la méthode jusqu’à ce que la chaîne entière s’affiche sous forme de lignes. Une fois toutes les lignes créées, la valeur TextLineCreationResult.COMPLETE est affectée à la propriété textLineCreationResult de l’objet TextBlock. Pour afficher les lignes, ajoutez-les à la liste d’affichage (associées aux valeurs de position x et y appropriées). Par exemple, le code suivant utilise ces classes FTE pour afficher « Hello World! This is Flash Text Engine! ».à l’aide du format et de la police par défaut. Dans cet exemple simple, une seule ligne de texte est générée. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 411 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package { import flash.text.engine.*; import flash.display.Sprite; public class HelloWorldExample extends Sprite { public function HelloWorldExample() { var str = "Hello World! This is Flash Text Engine!"; var format:ElementFormat = new ElementFormat(); var textElement:TextElement = new TextElement(str, format); var textBlock:TextBlock = new TextBlock(); textBlock.content = textElement; var textLine1:TextLine = textBlock.createTextLine(null, 300); addChild(textLine1); textLine1.x = 30; textLine1.y = 30; } } } Les paramètres requis pour createTextLine() spécifient la ligne où doit commencer la nouvelle ligne et la largeur de celle-ci en pixels. La ligne où doit commencer la nouvelle ligne correspond généralement à la ligne précédente, mais dans le cas de la première ligne, la valeur est null. Ajout d’objets GraphicElement et GroupElement Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez affecter un objet GraphicElement à un objet TextBlock en vue d’afficher une image ou un élément graphique. Il vous suffit pour cela de créer une occurrence de la classe GraphicElement à partir d’un graphique ou d’une image, puis d’affecter l’occurrence à la propriété TextBlock.content. Créez la ligne de texte en appelant la méthode TextBlock.createTextline() selon la procédure habituelle. L’exemple suivant crée deux lignes de texte : une avec un objet GraphicElement, l’autre avec un objet TextElement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 412 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package { import flash.text.engine.*; import flash.display.Sprite; import flash.display.Shape; import flash.display.Graphics; public class GraphicElementExample extends Sprite { public function GraphicElementExample() { var str:String = "Beware of Dog!"; var triangle:Shape = new Shape(); triangle.graphics.beginFill(0xFF0000, 1); triangle.graphics.lineStyle(3); triangle.graphics.moveTo(30, 0); triangle.graphics.lineTo(60, 50); triangle.graphics.lineTo(0, 50); triangle.graphics.lineTo(30, 0); triangle.graphics.endFill(); var format:ElementFormat = new ElementFormat(); format.fontSize = 20; var graphicElement:GraphicElement = new GraphicElement(triangle, triangle.width, triangle.height, format); var textBlock:TextBlock = new TextBlock(); textBlock.content = graphicElement; var textLine1:TextLine = textBlock.createTextLine(null, triangle.width); textLine1.x = 50; textLine1.y = 110; addChild(textLine1); var textElement:TextElement = new TextElement(str, format); textBlock.content = textElement; var textLine2 = textBlock.createTextLine(null, 300); addChild(textLine2); textLine2.x = textLine1.x - 30; textLine2.y = textLine1.y + 15; } } } Vous pouvez créer un objet GroupElement pour créer un groupe d’objets TextElement et GraphicElement ou d’autres objets GroupElement. Vous pouvez affecter un objet GroupElement à la propriété content d’un objet TextBlock. Le paramètre au constructeur GroupElement() est un vecteur qui pointe vers le texte, le graphique et les éléments qui constituent le groupe. L’exemple suivant regroupe deux éléments graphiques et un élément de texte, et les affecte comme une unité à un bloc de texte. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 413 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package { import flash.text.engine.*; import flash.display.Sprite; import flash.display.Shape; import flash.display.Graphics; public class GroupElementExample extends Sprite { public function GroupElementExample() { var str:String = "Beware of Alligators!"; var triangle1:Shape = new Shape(); triangle1.graphics.beginFill(0xFF0000, 1); triangle1.graphics.lineStyle(3); triangle1.graphics.moveTo(30, 0); triangle1.graphics.lineTo(60, 50); triangle1.graphics.lineTo(0, 50); triangle1.graphics.lineTo(30, 0); triangle1.graphics.endFill(); var triangle2:Shape = new Shape(); triangle2.graphics.beginFill(0xFF0000, 1); triangle2.graphics.lineStyle(3); triangle2.graphics.moveTo(30, 0); triangle2.graphics.lineTo(60, 50); triangle2.graphics.lineTo(0, 50); triangle2.graphics.lineTo(30, 0); triangle2.graphics.endFill(); var format:ElementFormat = new ElementFormat(); format.fontSize = 20; var graphicElement1:GraphicElement = new GraphicElement(triangle1, triangle1.width, triangle1.height, format); var textElement:TextElement = new TextElement(str, format); var graphicElement2:GraphicElement = new GraphicElement(triangle2, triangle2.width, triangle2.height, format); var groupVector:Vector. = new Vector.(); groupVector.push(graphicElement1, textElement, graphicElement2); var groupElement = new GroupElement(groupVector); var textBlock:TextBlock = new TextBlock(); textBlock.content = groupElement; var textLine:TextLine = textBlock.createTextLine(null, 800); addChild(textLine); textLine.x = 100; textLine.y = 200; } } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 414 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 Remplacement du texte Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez remplacer du texte dans une occurrence de TextBlock en appelant la méthode TextElement.replaceText() en vue de remplacer le texte dans l’objet TextElement que vous avez affecté à la propriété TextBlock.content. L’exemple suivant utilise replaceText() pour d’abord insérer du texte au début de la ligne, puis pour ajouter du texte à la fin de la ligne et, enfin, pour remplacer du texte au milieu de la ligne. package { import flash.text.engine.*; import flash.display.Sprite; public class ReplaceTextExample extends Sprite { public function ReplaceTextExample() { var str:String = "Lorem ipsum dolor sit amet"; var fontDescription:FontDescription = new FontDescription("Arial"); var format:ElementFormat = new ElementFormat(fontDescription); format.fontSize = 14; var textElement:TextElement = new TextElement(str, format); var textBlock:TextBlock = new TextBlock(); textBlock.content = textElement; createLine(textBlock, 10); textElement.replaceText(0, 0, "A text fragment: "); createLine(textBlock, 30); textElement.replaceText(43, 43, "..."); createLine(textBlock, 50); textElement.replaceText(23, 28, "(ipsum)"); createLine(textBlock, 70); } function createLine(textBlock:TextBlock, y:Number):void { var textLine:TextLine = textBlock.createTextLine(null, 300); textLine.x = 10; textLine.y = y; addChild(textLine); } } } La méthode replaceText() remplace le texte spécifié à l’aide des paramètres beginIndex et endIndex par le texte spécifié à l’aide du paramètre newText. Si les valeurs des paramètres beginIndex et endIndex sont les mêmes, la méthode replaceText() insère le texte spécifié à cet emplacement. Dans le cas contraire, elle remplace les caractères spécifiés à l’aide des paramètres beginIndex et endIndex par le nouveau texte. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 415 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 Gestion des événements dans FTE Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Comme c’est le cas pour d’autres objets d’affichage, vous pouvez ajouter des écouteurs d’événement à une occurrence de TextLine. Par exemple, vous pouvez savoir à quel moment un utilisateur passe la souris sur une ligne de texte ou clique sur la ligne. L’exemple suivant détecte ces deux événements. Lorsque vous passez la souris sur une ligne, le curseur prend la forme d’un bouton et lorsque vous cliquez sur la ligne, il change de couleur. package { import flash.text.engine.*; import flash.ui.Mouse; import flash.display.Sprite import flash.events.MouseEvent; import flash.events.EventDispatcher; public class EventHandlerExample extends Sprite { var textBlock:TextBlock = new TextBlock(); public function EventHandlerExample():void { var str:String = "I'll change color if you click me."; var fontDescription:FontDescription = new FontDescription("Arial"); var format:ElementFormat = new ElementFormat(fontDescription, 18); var textElement = new TextElement(str, format); textBlock.content = textElement; createLine(textBlock); } private function createLine(textBlock:TextBlock):void { var textLine:TextLine = textBlock.createTextLine(null, 500); textLine.x = 30; textLine.y = 30; addChild(textLine); textLine.addEventListener("mouseOut", mouseOutHandler); textLine.addEventListener("mouseOver", mouseOverHandler); textLine.addEventListener("click", clickHandler); } private function mouseOverHandler(event:MouseEvent):void { Mouse.cursor = "button"; } private function mouseOutHandler(event:MouseEvent):void { Mouse.cursor = "arrow"; } function clickHandler(event:MouseEvent):void { if(textBlock.firstLine) removeChild(textBlock.firstLine); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 416 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 var newFormat:ElementFormat = textBlock.content.elementFormat.clone(); switch(newFormat.color) { case 0x000000: newFormat.color = 0xFF0000; break; case 0xFF0000: newFormat.color = 0x00FF00; break; case 0x00FF00: newFormat.color = 0x0000FF; break; case 0x0000FF: newFormat.color = 0x000000; break; } textBlock.content.elementFormat = newFormat; createLine(textBlock); } } } Copie miroir d’événements Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez également matérialiser les événements d’un bloc de texte (ou d’une portion d’un bloc de texte) dans un diffuseur d’événements. Vous devez tout d’abord créer une occurrence de EventDispatcher, puis l’affecter à la propriété eventMirror d’une occurrence de TextElement. Si le bloc de texte n’est constitué que d’un seul élément de texte, le moteur de saisie effectue une copie miroir des événements pour l’intégralité du bloc de texte. Si le bloc de texte est constitué de plusieurs éléments de texte, le moteur de saisie effectue une copie miroir des événements uniquement pour les occurrences de TextElement dont la propriété eventMirror est définie. Dans l’exemple suivant, le texte est constitué de trois éléments : le mot « Click », le mot « here » et la chaîne « to see me in italic ». L’exemple affecte un diffuseur d’événements au deuxième élément de texte, le mot « here », et ajoute un écouteur d’événement, la méthode clickHandler(). La méthode clickHandler() met le texte en italique. Elle modifie également le contenu du troisième élément de texte et le remplace par la chaîne suivante : « Click here to see me in normal font! ». GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 417 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package { import flash.text.engine.*; import flash.ui.Mouse; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.EventDispatcher; public class EventMirrorExample extends Sprite { var fontDescription:FontDescription = new FontDescription("Helvetica", "bold"); var format:ElementFormat = new ElementFormat(fontDescription, 18); var textElement1 = new TextElement("Click ", format); var textElement2 = new TextElement("here ", format); var textElement3 = new TextElement("to see me in italic! ", format); var textBlock:TextBlock = new TextBlock(); public function EventMirrorExample() { var myEvent:EventDispatcher = new EventDispatcher(); myEvent.addEventListener("click", clickHandler); myEvent.addEventListener("mouseOut", mouseOutHandler); myEvent.addEventListener("mouseOver", mouseOverHandler); textElement2.eventMirror=myEvent; var groupVector:Vector. = new Vector.; groupVector.push(textElement1, textElement2, textElement3); var groupElement:GroupElement = new GroupElement(groupVector); textBlock.content = groupElement; createLines(textBlock); } private function clickHandler(event:MouseEvent):void { var newFont:FontDescription = new FontDescription(); newFont.fontWeight = "bold"; var newFormat:ElementFormat = new ElementFormat(); newFormat.fontSize = 18; if(textElement3.text == "to see me in italic! ") { newFont.fontPosture = FontPosture.ITALIC; textElement3.replaceText(0,21, "to see me in normal font! "); } else { newFont.fontPosture = FontPosture.NORMAL; textElement3.replaceText(0, 26, "to see me in italic! "); } newFormat.fontDescription = newFont; textElement1.elementFormat = newFormat; textElement2.elementFormat = newFormat; textElement3.elementFormat = newFormat; createLines(textBlock); } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 418 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 private function mouseOverHandler(event:MouseEvent):void { Mouse.cursor = "button"; } private function mouseOutHandler(event:MouseEvent):void { Mouse.cursor = "arrow"; } private function createLines(textBlock:TextBlock):void { if(textBlock.firstLine) removeChild (textBlock.firstLine); var textLine:TextLine = textBlock.createTextLine (null, 300); textLine.x = 15; textLine.y = 20; addChild (textLine); } } } Grâce aux fonctions mouseOverHandler() et mouseOutHandler(), le curseur prend la forme d’un bouton lorsqu’il est placé sur le mot « here » et reprend la forme d’une flèche lorsqu’il ne l’est pas. Mise en forme du texte Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Un objet TextBlock est un objet usine pour la création de lignes de texte. Le contenu d’un objet TextBlock est affecté via l’objet TextElement. Un objet ElementFormat gère la mise en forme du texte. La classe ElementFormat définit certaines propriétés, telles que l’alignement sur la ligne de base, le crénage, l’interlettrage, la rotation du texte, la taille et la couleur des polices, ainsi que la casse. Elle comprend également la méthode FontDescription, décrite en détail à la section « Utilisation des polices » à la page 422. Utilisation de l’objet ElementFormat Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Le constructeur de l’objet ElementFormat prend des nombreux paramètres facultatifs, dont FontDescription. Vous pouvez également définir ces propriétés en dehors du constructeur. L’exemple suivant illustre la relation des différents objets lors de la définition et de l’affichage d’une ligne de texte simple : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 419 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; import flash.text.*; public class ElementFormatExample extends Sprite { private var tb:TextBlock = new TextBlock(); private var te:TextElement; private var ef:ElementFormat; private var fd:FontDescription = new FontDescription(); private var str:String; private var tl:TextLine; public function ElementFormatExample() { fd.fontName = "Garamond"; ef = new ElementFormat(fd); ef.fontSize = 30; ef.color = 0xFF0000; str = "This is flash text"; te = new TextElement(str, ef); tb.content = te; tl = tb.createTextLine(null,600); addChild(tl); } } } Couleur de police et transparence (alpha) Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La propriété color de l’objet ElementFormat définit la couleur de police. La valeur est un entier représentant les composants RVB de la couleur, par exemple : 0xFF0000 pour le rouge et 0x00FF00 pour le vert. La valeur par défaut est noir (0x000000). La propriété alpha définit la valeur de transparence alpha d’un élément (TextElement et GraphicElement). La plage des valeurs est comprise entre 0 (complètement transparent) et 1 (complètement opaque), qui est la valeur par défaut. Les éléments dont la propriété alpha est de 0 sont invisibles, mais restent actifs. Cette valeur est multipliée par l’une des valeurs alpha héritées, ce qui rend l’élément plus transparent. var ef:ElementFormat = new ElementFormat(); ef.alpha = 0.8; ef.color = 0x999999; Alignement et décalage de la ligne de base Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La police et la taille du plus grand texte dans une ligne déterminent sa ligne de base dominante. Vous pouvez écraser ces valeurs en définissant TextBlock.baselineFontDescription et TextBlock.baselineFontSize. Vous pouvez aligner la ligne de base dominante sur l’une des lignes de bases du texte, à savoir la ligne ascendante, la ligne descendante, ou la ligne de base idéographique supérieure, centrale ou inférieure. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 420 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 A. Ascendante B. Ligne de base C. Descendante D. Hauteur-x Dans l’objet ElementFormat, trois propriétés déterminent la ligne de base et les caractéristiques d’alignement. La propriété alignmentBaseline définit la ligne de base principale d’un objet TextElement ou GraphicElement. Cette ligne de base est la ligne « d’accrochage ».de l’élément, et c’est à cette position que la ligne de base dominante du texte s’aligne. La propriété dominantBaseline indique la ligne de base de l’élément à utiliser, qui détermine la position verticale de l’élément sur la ligne. La valeur par défaut est TextBaseline.ROMAN, mais vous pouvez également stipuler que la ligne de base IDEOGRAPHIC_TOP ou IDEOGRAPHIC_BOTTOM doit être dominante. La propriété baselineShift déplace la ligne de base selon un nombre de pixels défini sur l’axe y. Dans un texte normal (aucune rotation), une valeur positive déplace la ligne de base vers le bas et une valeur négative la déplace vers le haut. Casse typographique Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La propriété TypographicCase de l’objet ElementFormat spécifie la casse du texte : majuscule, minuscule ou petites capitales. var ef_Upper:ElementFormat = new ElementFormat(); ef_Upper.typographicCase = TypographicCase.UPPERCASE; var ef_SmallCaps:ElementFormat = new ElementFormat(); ef_SmallCaps.typographicCase = TypographicCase.SMALL_CAPS; Rotation du texte Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez appliquer une rotation au bloc de texte ou aux glyphes d’un segment de texte par incréments de 90°. La classe TextRotation définit les constantes suivantes pour définir la rotation du bloc de texte et des glyphes : Constante Valeur Description AUTO “auto” Spécifie une rotation vers la gauche de 90 degrés. Généralement utilisée avec un texte asiatique vertical pour faire pivoter uniquement les glyphes auxquelles il est nécessaire d’appliquer une rotation. ROTATE_0 “rotate_0” Spécifie aucune rotation. ROTATE_180 “rotate_180” Spécifie une rotation de 180 degrés. ROTATE_270 “rotate_270” Spécifie une rotation de 270 degrés. ROTATE_90 “rotate_90” Spécifie une rotation vers la droite de 90 degrés. D A B C GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 421 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 Pour appliquer une rotation aux lignes d’un texte, définissez tout d’abord la propriété TextBlock.lineRotation avant d’appeler la méthode TextBlock.createTextLine() pour créer la ligne de texte. Pour appliquer une rotation aux glyphes dans un bloc de texte ou un segment, définissez la propriété ElementFormat.textRotation sur le nombre de degrés de rotation des glyphes souhaité. Une glyphe est la forme qui constitue un caractère, ou une partie d’un caractère qui consiste en plusieurs glyphes. La lettre « a » et le point sur un « i », par exemple, sont des glyphes. La rotation des glyphes est importante dans certaines langues asiatiques, notamment si vous souhaitez appliquer une rotation verticale aux lignes, mais ne pas appliquer de rotation aux caractères dans les lignes. Pour plus d’informations sur la rotation du texte asiatique, voir « Justification du texte asiatique » à la page 426. Voici un exemple de rotation du texte et des glyphes qu’il contient dans un texte asiatique : Cet exemple utilise également une police japonaise : package { import flash.display.Sprite; import flash.text.*; public class RotationExample extends Sprite { private var tb:TextBlock = new TextBlock(); private var te:TextElement; private var ef:ElementFormat; private var fd:FontDescription = new FontDescription(); private var str:String; private var tl:TextLine; public function RotationExample() { fd.fontName = "MS Mincho"; ef = new ElementFormat(fd); ef.textRotation = TextRotation.AUTO; str = "This is rotated Japanese text"; te = new TextElement(str, ef); tb.lineRotation = TextRotation.ROTATE_90; tb.content = te; tl = tb.createTextLine(null,600); addChild(tl); } } } Verrouillage et clonage d’un objet ElementFormat Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Lorsqu’un objet ElementFormat est affecté à un type de ContentElement, sa propriété locked est automatiquement définie sur true. Toute tentative de modification d’un objet ElementFormat verrouillé renvoie une erreur IllegalOperationError. La meilleure pratique consiste à définir complètement ce type d’objet avant de l’affecter à l’occurrence de TextElement. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 422 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 Si vous souhaitez modifier une occurrence de ElementFormat existante, vous devez tout d’abord vérifier sa propriété locked. Si elle est définie sur true, utilisez la méthode clone() pour créer une copie déverrouillée de l’objet. Vous pouvez modifier les propriétés de cet objet déverrouillé, puis l’affecter à l’occurrence de TextElement. Toute nouvelle ligne créée à partir de cet objet adopte la nouvelle mise en forme. Les lignes précédentes créées à partir de cet objet et utilisant l’ancienne mise en forme ne sont pas modifiées. package { import flash.display.Sprite; import flash.text.*; public class ElementFormatCloneExample extends Sprite { private var tb:TextBlock = new TextBlock(); private var te:TextElement; private var ef1:ElementFormat; private var ef2:ElementFormat; private var fd:FontDescription = new FontDescription(); public function ElementFormatCloneExample() { fd.fontName = "Garamond"; ef1 = new ElementFormat(fd); ef1.fontSize = 24; var str:String = "This is flash text"; te = new TextElement(str, ef); tb.content = te; var tx1:TextLine = tb.createTextLine(null,600); addChild(tx1); ef2 = (ef1.locked) ? ef1.clone() : ef1; ef2.fontSize = 32; tb.content.elementFormat = ef2; var tx2:TextLine = tb.createTextLine(null,600); addChild(tx2); } } } Utilisation des polices Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures L’objet FontDescription est utilisé avec l’occurrence de ElementFormat pour identifier une police et définir certaines de ses caractéristiques. Ces caractéristiques incluent le nom de la police, le poids, la position, le rendu et la méthode de recherche de la police (police de périphérique/police intégrée). Remarque : FTE ne prend pas en charge les polices Type 1 ou les polices bitmap, telles que Type 3, ATC, CID ou CID basées sur SFNT. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 423 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 Définition des caractéristiques des polices (objet FontDescription) Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La propriété fontName de l’objet FontDescription peut être un nom unique ou une liste de noms séparés par des virgules. Par exemple, dans une liste telle que « Arial, Helvetica, _sans », Text Engine recherche tout d’abord « Arial », puis « Helvetica » et finalement « _sans » s’il ne parvient pas à trouver les deux premières polices. La définition des noms de police comprend trois noms de police génériques : « _sans », « _serif » et « _typewriter ». Ces noms correspondent à des polices de périphérique spécifiques, selon le système de lecture. Il est judicieux de spécifier ce type de noms par défaut dans toutes les descriptions de police qui utilisent des polices de périphérique. Si la propriété fontName n’est pas spécifiée, « _serif » est utilisé comme nom par défaut. La propriété fontPosture peut être définie sur la valeur par défaut (FontPosture.NORMAL) ou en italique (FontPosture.ITALIC). La propriété fontWeight peut être définie sur la valeur par défaut (FontWeight.NORMAL) ou en caractères gras (FontWeight.BOLD). var fd1:FontDescription = new FontDescription(); fd1.fontName = "Arial, Helvetica, _sans"; fd1.fontPosture = FontPosture.NORMAL; fd1.fontWeight = FontWeight.BOLD; Polices intégrées ou polices de périphérique ? Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La propriété fontLookup de l’objet FontDescription indique si Text Engine recherche une police de périphérique ou une police intégrée pour rendre le texte. Si une police de périphérique (FontLookup.DEVICE) est spécifiée, le moteur d’exécution recherche la police sur le système de lecture. Si vous définissez une police intégrée (FontLookup.EMBEDDED_CFF), le moteur d’exécution recherche une police de ce type portant le nom indiqué dans le fichier SWF. Seules les polices CFF (Compact Font Format) intégrées utilisent ce paramètre. Si la police spécifiée est introuvable, une police de périphérique est utilisée. Les polices de périphérique donnent lieu à des fichiers SWF moins volumineux. Les polices intégrées garantissent une plus grande homogénéité d’une plate-forme à l’autre. var fd1:FontDescription = new FontDescription(); fd1.fontLookup = FontLookup.EMBEDDED_CFF; fd1.fontName = "Garamond, _serif"; Mode de rendu et repères Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Le rendu CFF (Compact Font Format) est disponible à partir de Flash Player 10 et Adobe AIR 1.5. Ce type de rendu de police permet une meilleure lisibilité du texte et un affichage optimisé des caractères de petite taille. Ce paramètre s’applique uniquement aux polices intégrées. La valeur par défaut de FontDescription correspond à ce paramètre (RenderingMode.CFF) pour la propriété renderingMode. Vous pouvez définir cette propriété sur RenderingMode.NORMAL afin qu’elle corresponde au type de rendu utilisé par Flash Player 7 ou versions antérieures. Lorsque le rendu CFF est sélectionné, une deuxième propriété, cffHinting, permet de contrôler la manière dont les corps horizontaux d’une police sont adaptés à la grille de sous-pixels. La valeur par défaut, CFFHinting.HORIZONTAL_STEM, utilise les repères CFF. Si vous définissez cette propriété sur CFFHinting.NONE , les repères sont supprimés. Ce paramètre convient pour les animations ou les grandes tailles de police. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 424 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 var fd1:FontDescription = new FontDescription(); fd1.renderingMode = RenderingMode.CFF; fd1.cffHinting = CFFHinting.HORIZONTAL_STEM; Verrouillage et clonage d’un objet FontDescription Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Lorsque vous affectez une occurrence de ElementFormat à un objet FontDescription, la propriété locked de ce dernier est automatiquement définie sur true. Toute tentative de modification d’un objet FontDescription verrouillé renvoie une erreur IllegalOperationError. La meilleure pratique consiste à définir complètement ce type d’objet avant de l’affecter à l’occurrence de ElementFormat. Si vous souhaitez modifier un objet FontDescription existant, vous devez tout d’abord vérifier sa propriété locked. Si elle est définie sur true, utilisez la méthode clone() pour créer une copie déverrouillée de l’objet. Vous pouvez modifier les propriétés de cet objet déverrouillé, puis l’affecter à ElementFormat. Toute nouvelle ligne créée à partir de ce TextElement adopte la nouvelle mise en forme. Les lignes précédentes créées à partir de ce même objet restent inchangées. package { import flash.display.Sprite; import flash.text.*; public class FontDescriptionCloneExample extends Sprite { private var tb:TextBlock = new TextBlock(); private var te:TextElement; private var ef1:ElementFormat; private var ef2:ElementFormat; private var fd1:FontDescription = new FontDescription(); private var fd2:FontDescription; public function FontDescriptionCloneExample() { fd1.fontName = "Garamond"; ef1 = new ElementFormat(fd); var str:String = "This is flash text"; te = new TextElement(str, ef); tb.content = te; var tx1:TextLine = tb.createTextLine(null,600); addChild(tx1); fd2 = (fd1.locked) ? fd1.clone() : fd1; fd2.fontName = "Arial"; ef2 = (ef1.locked) ? ef1.clone() : ef1; ef2.fontDescription = fd2; tb.content.elementFormat = ef2; var tx2:TextLine = tb.createTextLine(null,600); addChild(tx2); } } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 425 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 Contrôle du texte Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures FTE vous propose un ensemble de commandes de mise en forme du texte afin de gérer la justification et l’espacement des caractères (crénage et interlettrage). Il existe également des propriétés permettant de détecter les lignes brisées et de définir des taquets de tabulation dans les lignes. Justification du texte Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures En ajustant l’espacement entre les mots, et parfois entre les lettres, toutes les lignes d’un paragraphe possèdent une longueur identique. Bien que l’espacement entre les mots et les lettres varie, le texte est aligné des deux côtés. Les colonnes de texte dans les journaux et les magazines sont le plus souvent justifiées. La propriété lineJustfication de la classe SpaceJustifier vous permet de contrôler la justification des lignes dans un bloc de texte. La classe LineJustification définit des constantes en vue de spécifier une option de justification : ALL_BUT_LAST justifie tout le texte, à l’exception de la dernière ligne ; ALL_INCLUDING_LAST justifie tout le texte, y compris la dernière ligne ; l’option par défaut, UNJUSTIFIED, ne justifie pas le texte. Pour justifier le texte, définissez la propriété lineJustification sur une occurrence de la classe SpaceJustifier, puis affectez celle-ci à la propriété textJustifier d’une occurrence de TextBlock. L’exemple suivant crée un paragraphe dans lequel la totalité du texte est justifiée, à l’exception de la dernière ligne. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 426 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package { import flash.text.engine.*; import flash.display.Sprite; public class JustifyExample extends Sprite { public function JustifyExample() { var str:String = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut " + "enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + "aliquip ex ea commodo consequat."; var format:ElementFormat = new ElementFormat(); var textElement:TextElement=new TextElement(str,format); var spaceJustifier:SpaceJustifier=new SpaceJustifier("en",LineJustification.ALL_BUT_LAST); var textBlock:TextBlock = new TextBlock(); textBlock.content=textElement; textBlock.textJustifier=spaceJustifier; createLines(textBlock); } private function createLines(textBlock:TextBlock):void { var yPos=20; var textLine:TextLine=textBlock.createTextLine(null,150); while (textLine) { addChild(textLine); textLine.x=15; yPos+=textLine.textHeight+2; textLine.y=yPos; textLine=textBlock.createTextLine(textLine,150); } } } } Pour varier l’espacement entre les lettres et entre les mots, définissez la propriété SpaceJustifier.letterspacing sur true. L’activation de l’espacement entre les lettres peut réduire le nombre d’espaces disgracieux entre les mots, qui se produisent parfois lors d’une simple justification. Justification du texte asiatique Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Pour justifier un texte asiatique, il faut tenir compte d’autres considérations. Le texte peut être écrit de haut en haut et certains caractères appelés kinsoku ne peuvent pas apparaître au début ou à la fin d’une ligne. La classe JustificationStyle définit les constantes suivantes, qui spécifient les options de gestion de ces caractères. PRIORITIZE_LEAST_ADJUSTMENT base la justification sur l’expansion ou sur la compression de la ligne, en fonction de celle qui produit les meilleurs résultats. PUSH_IN_KINSOKU base la justification sur la compression des caractères kinsoku à la fin de la ligne, ou sur l’expansion de la ligne s’il n’existe aucun caractère kinsoku ou si cet espace est insuffisant. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 427 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 PUSH_OUT_ONLY base la justification sur l’expansion de la ligne. Pour créer un bloc de texte asiatique vertical, définissez la propriété TextBlock.lineRotation sur TextRotation.ROTATE_90, puis définissez la propriété ElementFormat.textRotation sur TextRotation.AUTO (paramètre par défaut). Si vous définissez la propriété textRotation sur AUTO, les glyphes dans le texte restent verticales au lieu de pivoter sur le côté lors de la rotation de la ligne. Le paramètre AUTO effectue une rotation vers la gauche de 90° pour les glyphes complètes uniquement, comme le spécifient les propriétés Unicode de la glyphe. L’exemple suivant affiche un bloc de texte japonais vertical et le justifie à l’aide de l’option PUSH_IN_KINSOKU. package { import flash.text.engine.*; import flash.display.Stage; import flash.display.Sprite; import flash.system.Capabilities; public class EastAsianJustifyExample extends Sprite { public function EastAsianJustifyExample() { var Japanese_txt:String = String.fromCharCode( 0x5185, 0x95A3, 0x5E9C, 0x304C, 0x300C, 0x653F, 0x5E9C, 0x30A4, 0x30F3, 0x30BF, 0x30FC, 0x30CD, 0x30C3, 0x30C8, 0x30C6, 0x30EC, 0x30D3, 0x300D, 0x306E, 0x52D5, 0x753B, 0x914D, 0x4FE1, 0x5411, 0x3051, 0x306B, 0x30A2, 0x30C9, 0x30D3, 0x30B7, 0x30B9, 0x30C6, 0x30E0, 0x30BA, 0x793E, 0x306E) var textBlock:TextBlock = new TextBlock(); var font:FontDescription = new FontDescription(); var format:ElementFormat = new ElementFormat(); format.fontSize = 12; format.color = 0xCC0000; format.textRotation = TextRotation.AUTO; textBlock.baselineZero = TextBaseline.IDEOGRAPHIC_CENTER; var eastAsianJustifier:EastAsianJustifier = new EastAsianJustifier("ja", LineJustification.ALL_BUT_LAST); eastAsianJustifier.justificationStyle = JustificationStyle.PUSH_IN_KINSOKU; textBlock.textJustifier = eastAsianJustifier; textBlock.lineRotation = TextRotation.ROTATE_90; var linePosition:Number = this.stage.stageWidth - 75; if (Capabilities.os.search("Mac OS") > -1) // set fontName: Kozuka Mincho Pro R GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 428 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 font.fontName = String.fromCharCode(0x5C0F, 0x585A, 0x660E, 0x671D) + " Pro R"; else font.fontName = "Kozuka Mincho Pro R"; textBlock.content = new TextElement(Japanese_txt, format); var previousLine:TextLine = null; while (true) { var textLine:TextLine = textBlock.createTextLine(previousLine, 200); if (textLine == null) break; textLine.y = 20; textLine.x = linePosition; linePosition -= 25; addChild(textLine); previousLine = textLine; } } } } Crénage et interlettrage Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Le crénage et l’interlettrage influent sur la distance entre les paires de caractères adjacentes dans un bloc de texte. Le crénage contrôle la manière dont les paires de caractères s’assemblent, notamment les paires « WA » ou « Va ». Il est défini dans l’objet ElementFormat. Par défaut, cet effet est activé (Kerning.ON) ; il peut être réglé sur OFF ou AUTO, auquel cas le crénage n’est appliqué qu’entre les caractères autres que Kanji, Hiragana ou Katakana. L’interlettrage ajoute ou soustrait un nombre de pixels défini entre les caractères dans un bloc de texte ; cet effet est également défini dans l’objet ElementFormat. L’interlettrage fonctionne avec les polices intégrées et les polices de périphérique. FTE prend en charge deux propriétés d’interlettrage : trackingLeft, qui ajoute ou soustrait des pixels à gauche d’un caractère, et trackingRight, qui ajoute ou soustrait des pixels à droite d’un caractère. Si vous utilisez le crénage, la valeur d’interlettrage est ajoutée aux valeurs de crénage ou soustraite des valeurs de crénage de chaque paire de caractères. A. Kerning.OFF B. TrackingRight=5, Kerning.OFF C. TrackingRight=-5, Kerning.OFF D. Kerning.ON E. TrackingRight=-5, Kerning.ON F. TrackingRight=-5, Kerning.ON VAY VAY VAY VAY VAY VAY A B C D E F GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 429 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 var ef1:ElementFormat = new ElementFormat(); ef1.kerning = Kerning.OFF; var ef2:ElementFormat = new ElementFormat(); ef2.kerning = Kerning.ON; ef2.trackingLeft = 0.8; ef2.trackingRight = 0.8; var ef3:ElementFormat = new ElementFormat(); ef3.trackingRight = -0.2; Texte avec retour à la ligne automatique Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La propriété breakOpportunity de l’objet ElementFormat indique les caractères pouvant être utilisés pour le renvoi lorsque le texte est renvoyé sur plusieurs lignes. La valeur par défaut, BreakOpportunity.AUTO, utilise les propriétés Unicode standard, telles que le saut entre les mots et sur les traits d’union. Le paramètre BreakOpportunity.ALL permet de considérer un caractère comme une opportunité de saut de ligne, ce qui est très utile lors de la création d’effets, tels que le texte le long d’un tracé. var ef:ElementFormat = new ElementFormat(); ef.breakOpportunity = BreakOpportunity.ALL; Taquets de tabulation Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Pour définir des taquets de tabulation dans un bloc de texte, définissez les taquets de tabulation en créant des occurrences de la classe TabStop. Les paramètres du constructeur TabStop() indiquent la méthode d’alignement du texte avec le taquet de tabulation. Ces paramètres indiquent la position du taquet de tabulation, et pour l’alignement décimal, la valeur d’alignement, exprimée sous forme de chaîne. En général, cette valeur est un point décimal, mais elle pourrait également être une virgule ou le symbole du dollar, du yen ou de l’euro, par exemple. La ligne de code suivante crée un taquet de tabulation appelé tab1. var tab1:TabStop = new TabStop(TabAlignment.DECIMAL, 50, "."); Après avoir créé les taquets de tabulation d’un bloc de texte, affectez-les à la propriété tabStops d’une occurrence de TextBlock. Etant donné que la propriété tabStops nécessite un vecteur, créez tout d’abord un vecteur, puis ajoutez la tabulation pour l’arrêter. Le vecteur vous permet d’affecter un ensemble de taquets de tabulation au bloc de texte. L’exemple suivant crée une occurrence de Vector et lui ajoute un ensemble d’objets TabStop. Affectez ensuite les taquets de tabulation à la propriété tabStops d’une occurrence de TextBlock. var tabStops:Vector. = new Vector.(); tabStops.push(tab1, tab2, tab3, tab4); textBlock.tabStops = tabStops Pour plus d’informations sur les vecteurs, voir « Utilisation de tableaux » à la page 25. L’exemple suivant illustre l’effet de chacune des options d’alignement de l’objet TabStop. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 430 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package { import flash.text.engine.*; import flash.display.Sprite; public class TabStopExample extends Sprite { public function TabStopExample() { var format:ElementFormat = new ElementFormat(); format.fontDescription = new FontDescription("Arial"); format.fontSize = 16; var tabStops:Vector. = new Vector.(); tabStops.push( new TabStop(TabAlignment.START, 20), new TabStop(TabAlignment.CENTER, 140), new TabStop(TabAlignment.DECIMAL, 260, "."), new TabStop(TabAlignment.END, 380)); var textBlock:TextBlock = new TextBlock(); textBlock.content = new TextElement( "\tt1\tt2\tt3\tt4\n" + "\tThis line aligns on 1st tab\n" + "\t\t\t\tThis is the end\n" + "\tThe following fragment centers on the 2nd tab:\t\t\n" + "\t\tit's on me\t\t\n" + "\tThe following amounts align on the decimal point:\n" + "\t\t\t45.00\t\n" + "\t\t\t75,320.00\t\n" + "\t\t\t6,950.00\t\n" + "\t\t\t7.01\t\n", format); textBlock.tabStops = tabStops; var yPosition:Number = 60; var previousTextLine:TextLine = null; var textLine:TextLine; var i:int; for (i = 0; i < 10; i++) { textLine = textBlock.createTextLine(previousTextLine, 1000, 0); textLine.x = 20; textLine.y = yPosition; addChild(textLine); yPosition += 25; previousTextLine = textLine; } } } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 431 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 Exemple d’utilisation de Flash Text Engine : mise en forme d’un article de journal Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Cet exemple de code illustre l’utilisation de FTE (Flash Text Engine) pour mettre en forme une page de journal simple. Cette page comprend un gros titre, un sous-titre et une section sur plusieurs colonnes. Créez d’abord un fichier FLA et rattachez le code suivant au cadre n° 2 de la couche par défaut : import com.example.programmingas3.newslayout.StoryLayout ; // frame sc ript - create a 3-columned arti cle layout var story:StoryLayout = new StoryLayout(720, 500, 3, 10); story.x = 20; story.y = 80; addChild(story); stop(); Dans cet exemple, StoryLayout.as est le script contrôleur. Il définit le contenu, lit les informations de style issues d’une feuille de style externe et les affecte aux objets ElementFormat. Il crée ensuite le gros titre, le sous-titre et les éléments de texte sur plusieurs colonnes. package com.example.programmingas3.newslayout { import flash.display.Sprite; import flash.text.StyleSheet; import flash.text.engine.*; import flash.events.Event; import flash.net.URLRequest; import flash.net.URLLoader; import flash.display.Sprite; import flash.display.Graphics; public class StoryLayout extends Sprite { public var headlineTxt:HeadlineTextField; public var subtitleTxt:HeadlineTextField; public var storyTxt:MultiColumnText; public var sheet:StyleSheet; public var h1_ElFormat:ElementFormat; public var h2_ElFormat:ElementFormat; public var p_ElFormat:ElementFormat; private var loader:URLLoader; public var paddingLeft:Number; public var paddingRight:Number; public var paddingTop:Number; public var paddingBottom:Number; public var preferredWidth:Number; public var preferredHeight:Number; public var numColumns:int; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 432 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 public var bgColor:Number = 0xFFFFFF; public var headline:String = "News Layout Example"; public var subtitle:String = "This example formats text like a newspaper page using the Flash Text Engine API. "; public var rawTestData:String = "From the part Mr. Burke took in the American Revolution, it was natural that I should consider him a friend to mankind; and as our acquaintance commenced on that ground, it would have been more agreeable to me to have had cause to continue in that opinion than to change it. " + "At the time Mr. Burke made his violent speech last winter in the English Parliament against the French Revolution and the National Assembly, I was in Paris, and had written to him but a short time before to inform him how prosperously matters were going on. Soon after this I saw his advertisement of the Pamphlet he intended to publish: As the attack was to be made in a language but little studied, and less understood in France, and as everything suffers by translation, I promised some of the friends of the Revolution in that country that whenever Mr. Burke's Pamphlet came forth, I would answer it. This appeared to me the more necessary to be done, when I saw the flagrant misrepresentations which Mr. Burke's Pamphlet contains; and that while it is an outrageous abuse on the French Revolution, and the principles of Liberty, it is an imposition on the rest of the world. " + "I am the more astonished and disappointed at this conduct in Mr. Burke, as (from the circumstances I am going to mention) I had formed other expectations. " + "I had seen enough of the miseries of war, to wish it might never more have existence in the world, and that some other mode might be found out to settle the differences that should occasionally arise in the neighbourhood of nations. This certainly might be done if Courts were disposed to set honesty about it, or if countries were enlightened enough not to be made the dupes of Courts. The people of America had been bred up in the same prejudices against France, which at that time characterised the people of England; but experience and an acquaintance with the French Nation have most effectually shown to the Americans the falsehood of those prejudices; and I do not believe that a more cordial and confidential intercourse exists between any two countries than between America and France. "; public function StoryLayout(w:int = 400, h:int = 200, cols:int = 3, padding:int = 10):void { this.preferredWidth = w; this.preferredHeight = h; this.numColumns = cols; this.paddingLeft = padding; this.paddingRight = padding; this.paddingTop = padding; this.paddingBottom = padding; var req:URLRequest = new URLRequest("story.css"); loader = new URLLoader(); loader.addEventListener(Event.COMPLETE, onCSSFileLoaded); loader.load(req); } public function onCSSFileLoaded(event:Event):void { this.sheet = new StyleSheet(); this.sheet.parseCSS(loader.data); // convert headline styles to ElementFormat objects GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 433 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 h1_ElFormat = getElFormat("h1", this.sheet); h1_ElFormat.typographicCase = TypographicCase.UPPERCASE; h2_ElFormat = getElFormat("h2", this.sheet); p_ElFormat = getElFormat("p", this.sheet); displayText(); } public function drawBackground():void { var h:Number = this.storyTxt.y + this.storyTxt.height + this.paddingTop + this.paddingBottom; var g:Graphics = this.graphics; g.beginFill(this.bgColor); g.drawRect(0, 0, this.width + this.paddingRight + this.paddingLeft, h); g.endFill(); } /** * Reads a set of style properties for a named style and then creates * a TextFormat object that uses the same properties. */ public function getElFormat(styleName:String, ss:StyleSheet):ElementFormat { var style:Object = ss.getStyle(styleName); if (style != null) { var colorStr:String = style.color; if (colorStr != null && colorStr.indexOf("#") == 0) { style.color = colorStr.substr(1); } var fd:FontDescription = new FontDescription( style.fontFamily, style.fontWeight, FontPosture.NORMAL, FontLookup.DEVICE, RenderingMode.NORMAL, CFFHinting.NONE); var format:ElementFormat = new ElementFormat(fd, style.fontSize, style.color, 1, TextRotation.AUTO, TextBaseline.ROMAN, TextBaseline.USE_DOMINANT_BASELINE, 0.0, Kerning.ON, 0.0, 0.0, "en", BreakOpportunity.AUTO, DigitCase.DEFAULT, DigitWidth.DEFAULT, LigatureLevel.NONE, TypographicCase.DEFAULT); if (style.hasOwnProperty("letterSpacing")) GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 434 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 { format.trackingRight = style.letterSpacing; } } return format; } public function displayText():void { headlineTxt = new HeadlineTextField(h1_ElFormat,headline,this.preferredWidth); headlineTxt.x = this.paddingLeft; headlineTxt.y = 40 + this.paddingTop; headlineTxt.fitText(1); this.addChild(headlineTxt); subtitleTxt = new HeadlineTextField(h2_ElFormat,subtitle,this.preferredWidth); subtitleTxt.x = this.paddingLeft; subtitleTxt.y = headlineTxt.y + headlineTxt.height; subtitleTxt.fitText(2); this.addChild(subtitleTxt); storyTxt = new MultiColumnText(rawTestData, this.numColumns, 20, this.preferredWidth, this.preferredHeight, p_ElFormat); storyTxt.x = this.paddingLeft; storyTxt.y = subtitleTxt.y + subtitleTxt.height + 10; this.addChild(storyTxt); drawBackground(); } } } FormattedTextBlock.as est utilisé en tant que classe de base pour la création des blocs de texte. Il comprend également des fonctions permettant de modifier la taille de police et la casse. package com.example.programmingas3.newslayout { import flash.text.engine.*; import flash.display.Sprite; public class FormattedTextBlock extends Sprite { public var tb:TextBlock; private var te:TextElement; private var ef1:ElementFormat; private var textWidth:int; public var totalTextLines:int; public var blockText:String; public var leading:Number = 1.25; public var preferredWidth:Number = 720; public var preferredHeight:Number = 100; public function FormattedTextBlock(ef:ElementFormat,txt:String, colW:int = 0) { this.textWidth = (colW==0) ? preferredWidth : colW; blockText = txt; ef1 = ef; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 435 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 tb = new TextBlock(); tb.textJustifier = new SpaceJustifier("en",LineJustification.UNJUSTIFIED,false); te = new TextElement(blockText,this.ef1); tb.content = te; this.breakLines(); } private function breakLines() { var textLine:TextLine = null; var y:Number = 0; var lineNum:int = 0; while (textLine = tb.createTextLine(textLine,this.textWidth,0,true)) { textLine.x = 0; textLine.y = y; y += this.leading*textLine.height; this.addChild(textLine); } for (var i:int = 0; i < this.numChildren; i++) { TextLine(this.getChildAt(i)).validity = TextLineValidity.STATIC; } this.totalTextLines = this.numChildren; } private function rebreakLines() { this.clearLines(); this.breakLines(); } private function clearLines() { while(this.numChildren) { this.removeChildAt(0); } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 436 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 public function changeSize(size:uint=12):void { if (size > 5) { var ef2:ElementFormat = ef1.clone(); ef2.fontSize = size; te.elementFormat = ef2; this.rebreakLines(); } } public function changeCase(newCase:String = "default"):void { var ef2:ElementFormat = ef1.clone(); ef2.typographicCase = newCase; te.elementFormat = ef2; } } } HeadlineTextBlock.as étend la classe FormattedTextBlock et est utilisé pour créer les gros titres. Il contient une fonction destinée à faire tenir le texte dans un espace déterminé sur la page. package com.example.programmingas3.newslayout { import flash.text.engine.*; public class HeadlineTextField extends FormattedTextBlock { public static var MIN_POINT_SIZE:uint = 6; public static var MAX_POINT_SIZE:uint = 128; public function HeadlineTextField(te:ElementFormat,txt:String,colW:int = 0) { super(te,txt); } public function fitText(maxLines:uint = 1, targetWidth:Number = -1):uint { if (targetWidth == -1) { targetWidth = this.width; } var pixelsPerChar:Number = targetWidth / this.blockText.length; var pointSize:Number = Math.min(MAX_POINT_SIZE, Math.round(pixelsPerChar * 1.8 * maxLines)); if (pointSize < 6) { // the point size is too small return pointSize; } this.changeSize(pointSize); if (this.totalTextLines > maxLines) GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 437 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 { return shrinkText(--pointSize, maxLines); } else { return growText(pointSize, maxLines); } } public function growText(pointSize:Number, maxLines:uint = 1):Number { if (pointSize >= MAX_POINT_SIZE) { return pointSize; } this.changeSize(pointSize + 1); if (this.totalTextLines > maxLines) { // set it back to the last size this.changeSize(pointSize); return pointSize; } else { return growText(pointSize + 1, maxLines); } } public function shrinkText(pointSize:Number, maxLines:uint=1):Number { if (pointSize <= MIN_POINT_SIZE) { return pointSize; } this.changeSize(pointSize); if (this.totalTextLines > maxLines) { return shrinkText(pointSize - 1, maxLines); } else { return pointSize; } } } } MultiColumnText.as gère la mise en forme du texte dans un format multicolonne. Il illustre la souplesse d’un objet TextBlock, utilisé comme usine pour créer, mettre en forme et positionner les lignes de texte. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 438 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 package com.example.programmingas3.newslayout { import flash.display.Sprite; import flash.text.engine.*; public class MultiColumnText extends Sprite { private var tb:TextBlock; private var te:TextElement; private var numColumns:uint = 2; private var gutter:uint = 10; private var leading:Number = 1.25; private var preferredWidth:Number = 400; private var preferredHeight:Number = 100; private var colWidth:int = 200; public function MultiColumnText(txt:String = "",cols:uint = 2, gutter:uint = 10, w:Number = 400, h:Number = 100, ef:ElementFormat = null):void { this.numColumns = Math.max(1, cols); this.gutter = Math.max(1, gutter); this.preferredWidth = w; this.preferredHeight = h; this.setColumnWidth(); var field:FormattedTextBlock = new FormattedTextBlock(ef,txt,this.colWidth); var totLines:int = field.totalTextLines; field = null; var linesPerCol:int = Math.ceil(totLines/cols); tb = new TextBlock(); te = new TextElement(txt,ef); tb.content = te; var textLine:TextLine = null; var x:Number = 0; var y:Number = 0; var i:int = 0; var j:int = 0; while (textLine = tb.createTextLine(textLine,this.colWidth,0,true)) { textLine.x = Math.floor(i/(linesPerCol+1))*(this.colWidth+this.gutter); textLine.y = y; y += this.leading*textLine.height; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 439 Utilisation de Flash Text Engine Dernière mise à jour le 27/4/2013 j++; if(j>linesPerCol) { y = 0; j = 0; } i++; this.addChild(textLine); } } private function setColumnWidth():void { this.colWidth = Math.floor( (this.preferredWidth - ((this.numColumns - 1) * this.gutter)) / this.numColumns); } } } 440 Dernière mise à jour le 27/4/2013 Chapitre 23 : Utilisation de Text Layout Framework Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Présentation de Text Layout Framework Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Text Layout Framework (TLF) est une bibliothèque ActionScript évolutive. TLF est basé sur le moteur texte d’Adobe® Flash® Player 10 et d’Adobe® AIR® 1.5. Il propose des fonctions typographiques et de mise en forme du texte avancées qui assurent une typographie innovatrice sur le Web. TLF peut être utilisé avec Adobe® Flex® ou Adobe® Flash® Professional. Les développeurs peuvent utiliser ou étendre des composants existants ou faire appel à la structure pour créer leurs propres composants texte. TLF intègre les fonctionnalités suivantes : • Texte bidirectionnel, texte vertical et plus de 30 scripts tels que l’arabe, le chinois, le coréen, l’hébreu, le japonais, le laotien, le thaï, le vietnamien, etc. • Sélection, modification et distribution du texte sur plusieurs colonnes et conteneurs liés • Texte vertical, Tate-Chu-Yoko (texte horizontal placé entre du texte vertical) et justificateur pour la typographie asiatique • Contrôles typographiques riches, tels que le crénage, les ligatures, la casse typographique, la casse des chiffres, la largeur des chiffres et les tirets conditionnels • Couper, copier, coller, annulation et mouvements de souris et clavier standard de modification • API riches de développement destinées à manipuler le contenu, la mise en forme et le balisage de texte, ainsi qu’à créer des composants texte personnalisés • Excellente prise en charge des listes, notamment les marques et formats de numérotation personnalisés • Règles de positionnement et images intégrées Text Layout Framework est une bibliothèque ActionScript 3.0 basée sur la version de Flash Text Engine (FTE) introduite dans Flash Player 10. Vous pouvez accéder à FTE via le package flash.text.engine, qui fait partie intégrante de l’API (Application Programming Interface) de Flash Player 10. Toutefois, l’API de Flash Player fournit un accès de bas niveau à FTE, ce qui signifie que certaines tâches nécessitent parfois un volume de code relativement important. TLF encapsule le code de bas niveau dans des API simplifiées. Il propose également une architecture conceptuelle qui organise les blocs de construction de base définis par FTE pour former un système convivial. Contrairement à FTE, TLF n’est pas intégré à Flash Player. Il correspond à une bibliothèque de composants indépendants écrits entièrement en ActionScript 3.0. En raison de l’extensibilité de la structure, il peut être adapté à des environnements déterminés. Flash Professional et le kit de développement (SDK) de Flex contiennent tous deux des composants basés sur la structure TLF. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 441 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Voir aussi Application de marquage TLF "Flow" Prise en charge des scripts complexes Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures TLF prend en charge les scripts complexes, qui gèrent des fonctionnalités telles que la capacité d’afficher et de modifier les scripts rédigés de droite à gauche. TLF permet également d’afficher et de modifier un mélange de scripts écrits de gauche à droite et de droite à gauche, comme l’arabe et l’hébreu. TLF prend en charge non seulement la mise en forme du texte vertical chinois, coréen et japonais, mais également tate-chu-yoko (éléments TCY). Les éléments TCY sont des blocs de texte horizontaux intégrés à des segments verticaux de texte. Les scripts suivants sont pris en charge : • Latin (anglais, espagnol, français, vietnamien, etc.) • Arménien, cyrillique, éthiopien, géorgien et grec • Arabe et hébreu • Idéogrammes Han, Kana (chinois, coréen et japonais) et Hangul Johab (coréen) • Thaï, khmer et laotien • Bengali, dévanâgarî, gujarâtî, gourmoukhî, kannara, malayalam, oriya, tamoul, télougou et tibétain • Bouhid, chérokie, deseret, écriture syllabique canadienne, hanounoo, shavian, tagalog, tagbanoua, tifinaghe, vai et yi Utilisation de Text Layout Framework (TLF) dans Flash Professional et Flex Vous pouvez créer des composants personnalisés dans Flash directement à partir de classes TLF. Flash Professional CS5 intègre en outre une nouvelle classe, fl.text.TLFTextField, qui encapsule la fonctionnalité TLF. La classe TLFTextField permet de créer des champs de texte en ActionScript qui utilisent les fonctions d’affichage de texte avancées de TLF. Créez un objet TLFTextField à l’instar d’un champ de texte par le biais de la classe TextField. Utilisez ensuite la propriété textFlow pour appliquer le formatage avancé à partir des classes de TLF. Vous pouvez également créer l’occurrence de TLFTextField sur la scène à l’aide de l’outil texte de Flash Professional. Vous pouvez alors utiliser ActionScript pour contrôler le formatage et la mise en forme du champ de texte à l’aide de classes TLF. Pour plus d’informations, voir TLFTextField dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Dans Flex, utilisez les classes TLF. Pour plus d’informations, voir « Utilisation de Text Layout Framework » à la page 441. Utilisation de Text Layout Framework Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Si vous travaillez dans Flex ou créez des composants texte personnalisés, faites appel aux classes TLF. TLF est une bibliothèque ActionScript 3.0 entièrement intégrée à la bibliothèque textLayout.swc. La bibliothèque TLF contient environ 100 classes et interfaces ActionScript 3.0 réparties dans dix packages. Ces packages sont des sous-packages du package flashx.textLayout. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 442 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Classes Text Layout Framework Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Les classes TLF sont regroupées en trois catégories : • Classes de formatage et structures de données • Classes de rendu • Classes d’interaction utilisateur Classes de formatage et structures de données Les packages suivants contiennent les classes de formatage et structures de données de TLF : • flashx.textLayout.elements • flashx.textLayout.formats • flashx.textLayout.conversion La structure de données principale de TLF correspond à la hiérarchie d’enchaînements, définie dans le package d’éléments. Au sein de cette structure, vous pouvez attribuer des styles et attributs à des segments de texte en utilisant le package de formats. Le package de conversion permet de contrôler l’importation et l’exportation du texte dans la structure de données. Classes de rendu Les packages suivants contiennent les classes de rendu de TLF : • flashx.textLayout.factory • flashx.textLayout.container • flashx.textLayout.compose Les classes de ces packages facilitent le rendu du texte affiché par Flash Player. Le package d’usine constitue un moyen simple d’afficher du texte statique. Le package de conteneur inclut les classes et les interfaces qui définissent les conteneurs d’affichage du texte dynamique. Le package de composition définit les techniques de positionnement et d’affichage de texte dynamique dans les conteneurs. Classes d’interaction utilisateur Les packages suivants contiennent les classes d’interaction utilisateur de TLF : • flashx.textLayout.edit • flashx.textLayout.operations • flashx.textLayout.events Les packages de modification et d’opérations définissent les classes dont vous disposez pour autoriser la modification du texte stocké dans les structures de données. Le package des événements contient les classes de gestion des événements. Procédure générale de création de texte à l’aide de Text Layout Framework La procédure suivante décrit le processus général de création de texte à l’aide de Text Layout Format : 1 Importez du texte formaté dans les structures de données TLF. Pour plus d’informations, voir « Structuration du texte à l’aide de TLF » à la page 446 et « Formatage du texte à l’aide de TLF » à la page 450. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 443 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 2 Créez un ou plusieurs conteneurs d’objets d’affichage liés destinés au texte. Pour plus d’informations, voir « Gestion des conteneurs de texte à l’aide de TLF » à la page 452. 3 Associez le texte figurant dans les structures de données aux conteneurs et définissez les options de modification et de défilement. Pour plus d’informations, voir « Activation de la sélection, de la modification et de l’annulation de texte à l’aide de TLF » à la page 453. 4 Créez un gestionnaire d’événement permettant de redistribuer le texte en réponse à des événements de redimensionnement (ou autre). Pour plus d’informations, voir « Gestion des événements à l’aide de TLF » à la page 453. Exemple Text Layout Framework : article de journal Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures L’exemple suivant illustre la mise en forme d’une page de journal simple à l’aide de TLF. Cette page comprend un gros titre, un sous-titre et une section sur plusieurs colonnes : package { import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Rectangle; import flashx.textLayout.compose.StandardFlowComposer; import flashx.textLayout.container.ContainerController; import flashx.textLayout.container.ScrollPolicy; import flashx.textLayout.conversion.TextConverter; import flashx.textLayout.elements.TextFlow; import flashx.textLayout.formats.TextLayoutFormat; public class TLFNewsLayout extends Sprite { private var hTextFlow:TextFlow; private var headContainer:Sprite; private var headlineController:ContainerController; private var hContainerFormat:TextLayoutFormat; private var bTextFlow:TextFlow; private var bodyTextContainer:Sprite; private var bodyController:ContainerController; private var bodyTextContainerFormat:TextLayoutFormat; private const headlineMarkup:String = "TLF News Layout ExampleThis example formats text like a newspaper page with a headline, a subtitle, and multiple columns"; private const bodyMarkup:String = "There are many such lime-kilns in that tract of country, for the purpose of burning the white marble which composes a large part of the GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 444 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 substance of the hills. Some of them, built years ago, and long deserted, with weeds growing in the vacant round of the interior, which is open to the sky, and grass and wild-flowers rooting themselves into the chinks of the stones, look already like relics of antiquity, and may yet be overspread with the lichens of centuries to come. Others, where the lime-burner still feeds his daily and nightlong fire, afford points of interest to the wanderer among the hills, who seats himself on a log of wood or a fragment of marble, to hold a chat with the solitary man. It is a lonesome, and, when the character is inclined to thought, may be an intensely thoughtful occupation; as it proved in the case of Ethan Brand, who had mused to such strange purpose, in days gone by, while the fire in this very kiln was burning.The man who now watched the fire was of a different order, and troubled himself with no thoughts save the very few that were requisite to his business. At frequent intervals, he flung back the clashing weight of the iron door, and, turning his face from the insufferable glare, thrust in huge logs of oak, or stirred the immense brands with a long pole. Within the furnace were seen the curling and riotous flames, and the burning marble, almost molten with the intensity of heat; while without, the reflection of the fire quivered on the dark intricacy of the surrounding forest, and showed in the foreground a bright and ruddy little picture of the hut, the spring beside its door, the athletic and coal-begrimed figure of the lime-burner, and the half-frightened child, shrinking into the protection of his father's shadow. And when again the iron door was closed, then reappeared the tender light of the halffull moon, which vainly strove to trace out the indistinct shapes of the neighboring mountains; and, in the upper sky, there was a flitting congregation of clouds, still faintly tinged with the rosy sunset, though thus far down into the valley the sunshine had vanished long and long ago."; public function TLFNewsLayout() { //wait for stage to exist addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); } private function onAddedToStage(evtObj:Event):void { removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage); stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; // Headline text flow and flow composer hTextFlow = TextConverter.importToFlow(headlineMarkup, TextConverter.TEXT_LAYOUT_FORMAT); // initialize the headline container and controller objects headContainer = new Sprite(); headlineController = new ContainerController(headContainer); headlineController.verticalScrollPolicy = ScrollPolicy.OFF; hContainerFormat = new TextLayoutFormat(); hContainerFormat.paddingTop = 4; hContainerFormat.paddingRight = 4; hContainerFormat.paddingBottom = 4; hContainerFormat.paddingLeft = 4; headlineController.format = hContainerFormat; hTextFlow.flowComposer.addController(headlineController); addChild(headContainer); stage.addEventListener(flash.events.Event.RESIZE, resizeHandler); // Body text TextFlow and flow composer bTextFlow = TextConverter.importToFlow(bodyMarkup, GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 445 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 TextConverter.TEXT_LAYOUT_FORMAT); // The body text container is below, and has three columns bodyTextContainer = new Sprite(); bodyController = new ContainerController(bodyTextContainer); bodyTextContainerFormat = new TextLayoutFormat(); bodyTextContainerFormat.columnCount = 3; bodyTextContainerFormat.columnGap = 30; bodyController.format = bodyTextContainerFormat; bTextFlow.flowComposer.addController(bodyController); addChild(bodyTextContainer); resizeHandler(null); } private function resizeHandler(event:Event):void { const verticalGap:Number = 25; const stagePadding:Number = 16; var stageWidth:Number = stage.stageWidth - stagePadding; var stageHeight:Number = stage.stageHeight - stagePadding; var headlineWidth:Number = stageWidth; var headlineContainerHeight:Number = stageHeight; // Initial compose to get height of headline after resize headlineController.setCompositionSize(headlineWidth, headlineContainerHeight); hTextFlow.flowComposer.compose(); var rect:Rectangle = headlineController.getContentBounds(); headlineContainerHeight = rect.height; // Resize and place headline text container // Call setCompositionSize() again with updated headline height headlineController.setCompositionSize(headlineWidth, headlineContainerHeight ); headlineController.container.x = stagePadding / 2; headlineController.container.y = stagePadding / 2; hTextFlow.flowComposer.updateAllControllers(); // Resize and place body text container var bodyContainerHeight:Number = (stageHeight - verticalGap - headlineContainerHeight); bodyController.format = bodyTextContainerFormat; bodyController.setCompositionSize(stageWidth, bodyContainerHeight ); bodyController.container.x = (stagePadding/2); bodyController.container.y = (stagePadding/2) + headlineContainerHeight + verticalGap; bTextFlow.flowComposer.updateAllControllers(); } } } La classe TLFNewsLayout utilise deux conteneurs de texte. Le premier affiche un titre et un sous-titre, tandis que le second contient trois colonnes de texte. Pour raison de simplicité, le texte est codé en dur dans l’exemple au format TLF Markup. La variable headlineMarkup contient le titre et le sous-titre, tandis que la variable bodyMarkup contient le corps du texte. Pour plus d’informations sur TLF Markup, voir « Structuration du texte à l’aide de TLF » à la page 446. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 446 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Au terme d’une initialisation, la fonction onAddedToStage() importe le titre du titre dans un objet TextFlow, qui correspond à la principale structure de données de TLF : hTextFlow = TextConverter.importToFlow(headlineMarkup, TextConverter.TEXT_LAYOUT_FORMAT); Le code suivant permet ensuite de créer un objet Sprite destiné au conteneur, puis de créer un contrôleur et de l’associer au conteneur : headContainer = new Sprite(); headlineController = new ContainerController(headContainer); Le contrôleur est initialisé de sorte à définir le formatage, le défilement et autres options. Il contient la géométrie qui définit les limites du conteneur dans lequel est distribué le texte. Un objet TextLayoutFormat contient les options de formatage suivantes : hContainerFormat = new TextLayoutFormat(); Le contrôleur est affecté au compositeur d’enchaînements et la fonction ajoute le conteneur à la liste d’affichage. La composition et l’affichage à proprement parler des conteneurs relèvent de la méthode resizeHandler(). Une procédure identique permet d’initialiser l’objet TextFlow associé au corps du texte. La méthode resizeHandler() mesure l’espace disponible pour le rendu des conteneurs et affecte à ces derniers la taille appropriée. Un appel initial de la méthode compose() permet de calculer la hauteur appropriée du conteneur de gros titre. La méthode resizeHandler() peut alors placer et afficher le conteneur de gros titre par le biais de la méthode updateAllControllers(). Enfin, la méthode resizeHandler() se base sur la taille du conteneur de gros titre pour déterminer le positionnement du conteneur de corps de texte. Structuration du texte à l’aide de TLF TLF représente le texte sous forme d’arborescence. Chaque noeud de l’arborescence est une occurrence d’une classe définie dans le package d’éléments. Par exemple, le noeud racine de l’arborescence est toujours une occurrence de la classe TextFlow. La class TextFlow représente un article de texte entier. Un article est un ensemble d’éléments texte ou autre assimilés à une seule unité, appelée enchaînement. Un article unique requiert parfois plusieurs colonnes ou conteneurs de texte pour s’afficher. Exception faite du noeud racine, les éléments restants sont peu ou prou basés sur des éléments XHTML. Le schéma suivant illustre l’arborescence de la structure : Arborescence TextFlow GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 447 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Format TLF Markup Une maîtrise de la structure de TLF s’avère également utile lorsque vous utilisez le format TLF Markup. Le format TLF Markup est une représentation XML du texte stocké dans TLF. Bien que la structure prenne également en charge d’autres formats XML, le format TLF Markup est unique, car il est basé spécifiquement sur la structure de l’arborescence TextFlow. Si vous exportez du code XML à partir d’une arborescence TextFlow à l’aide de ce format de balisage, le code XML est exporté en préservant sa structure arborescente. TLF Markup assure la représentation du texte la plus fidèle dans une arborescence TextFlow. Le langage de balisage associe des balises à chaque élément de base de l’arborescence TextFlow et fournit également des attributs pour toutes les propriétés de formatage intégrées à la classe TextLayoutFormat. Le tableau suivant dresse la liste les balises dont vous disposez dans TLF Markup. Elément Description Enfants Classe textflow Elément racine du balisage div, p TextFlow div Division au sein d’un flux TextFlow. Peut contenir un groupe de paragraphes. div, list, p DivElement p Paragraphe. a, tcy, span, img, tab, br, g ParagraphElement a Lien tcy, span, img, tab, br, g LinkElement tcy Segment de texte horizontal (utilisé dans un élément TextFlow vertical) a, span, img, tab, br, g TCYElement span Segment de texte au sein d’un paragraphe SpanElement img Image dans un paragraphe InlineGraphicElement tab Caractère de tabulation TabElement br Caractère de saut. Permet d’arrêter une ligne au sein d’un paragraphe. Le texte passe à la ligne suivante, mais sans changer de paragraphe. BreakElement linkNormalFormat Définit les attributs de formatage utilisés pour les liens en état normal. TextLayoutFormat TextLayoutFormat linkActiveFormat Définit les attributs de formatage utilisés pour les liens en état actif, c’est-à-dire lorsque l’utilisateur appuie sur un lien avec le bouton de la souris. TextLayoutFormat TextLayoutFormat linkHoverFormat Définit les attributs de formatage utilisés pour les liens en état suspendu, c’est-à-dire lorsque l’utilisateur survole un lien avec la souris. TextLayoutFormat TextLayoutFormat li Composant d’un élément de liste. Doit résider à l’intérieur d’un élément de liste. div, li, list, p ListItemElement list Liste. Les listes peuvent être imbriquées ou placées les unes à côté des autres. Différents modèles de libellé ou de numérotation peuvent être appliqués aux éléments de liste. div, li, list, p ListElement g Elément de groupe. Permet de regrouper les éléments dans un paragraphe. Permet d’imbriquer des éléments au-dessous du niveau paragraphe. a, tcy, span, img, tab, br, g SubParagraphGroupE lement GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 448 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Voir aussi TLF 2.0 Lists Markup (disponible en anglais uniquement) TLF 2.0 SubParagraphGroupElements and typeName (disponible en anglais uniquement) Utilisation des listes numérotées et des listes à puce Les classes ListElement et ListItemElement permettent d’ajouter des listes à puce aux contrôles de texte. Il est possible d’imbriquer les listes à puce et de les personnaliser en vue d’utiliser plusieurs puces (ou marqueurs), ainsi que la numérotation automatique et la numérotation de style contour. Pour créer des listes dans un enchaînement, utilisez la balise . Vous utilisez ensuite les balises
  • au sein de la balise pour chaque élément de la liste. La classe ListMarkerFormat permet de personnaliser l’aspect des puces. L’exemple suivant crée des listes simples : Item 1 Item 2 Item 3 Comme l’illustre l’exemple ci-dessous, vous pouvez imbriquer des listes au sein d’autres listes : Item 1 Item 1a Item 1b Item 1c Item 2 Item 3 Pour personnaliser le type de marques de la liste, utilisez la propriété listStyleType de la classe ListElement. Cette propriété peut posséder n’importe quelle valeur définie par la classe ListStyleType (check, circle, decimal et box, par exemple). L’exemple suivant permet de créer des listes dotées de divers types de marques et d’un incrément de compteur personnalisé : upperAlpha item another lowerAlpha item another upperRoman item another lowerRoman item another Vous utilisez la classe ListMarkerFormat pour définir le compteur. Parallèlement à la définition de l’incrément d’un compteur, vous pouvez personnaliser ce dernier en le réinitialisant à l’aide de la propriété counterReset. Vous pouvez personnaliser plus encore l’aspect des marques de liste à l’aide des propriétés beforeContent et afterContent de la classe ListMarkerFormat. Ces propriétés s’appliquent au contenu affiché avant et après le contenu de la marque. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 449 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 L’exemple suivant ajoute la chaîne « XX » avant la marque et la chaîne « YY » après ce dernier : Item 1 Item 2 Item 3 La propriété content définit quant à elle d’autres personnalisations du format de la marque. L’exemple suivant illustre une marque de type chiffre romain en majuscules : Item 1
  • Item 2 Item 3 Comme illustré par l’exemple précédent, la propriété content peut également insérer un suffixe, c’est-à-dire une chaîne insérée après la marque, mais avant la propriété afterContent. Pour insérer cette chaîne lorsque vous fournissez un contenu XML à l’enchaînement, entourez-la d’entités HTML "e; plutôt que de guillemets (""). Voir aussi TLF 2.0 Lists Markup (disponible en anglais uniquement) Utilisation de marges dans TLF Chaque objet FlowElement prend en charge des propriétés de marge destinées à contrôler la position de la zone de contenu de chaque élément, ainsi que l’espace qui sépare les zones de contenu. La largeur totale d’un élément correspond à la somme de la largeur de son contenu et des propriétés paddingLeft et paddingRight. La hauteur totale d’un élément correspond à la somme de la hauteur de son contenu et des propriétés paddingTop et paddingBottom. La marge correspond à l’espace qui sépare la bordure du contenu. Les propriétés de marge sont paddingBottom, paddingTop, paddingLeft et paddingRight. Il est possible d’appliquer un remplissage à l’objet TextFlow, ainsi qu’aux éléments enfants suivants : • div • img • li • list GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 450 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 • p Il est impossible d’appliquer les propriétés de marge aux éléments span. L’exemple suivant définit les propriétés de marge de l’objet TextFlow : Les valeurs valides des propriétés de remplissage sont un numéro (en pixels), « auto » et « inherit ». La valeur par défaut est « auto », qui signifie que la marge est automatiquement calculée et définie sur 0 pour tous les éléments, à l’exception de ListElement. Pour les objets ListElement, « auto » est défini sur 0, à l’exception du côté début de la liste, qui utilise la valeur de la propriété listAutoPadding. La valeur par défaut de listAutoPadding est de 40, qui donne aux listes un retrait par défaut. Les propriétés de marge n’héritent par défaut d’aucune valeur. Les valeurs « auto » et « inherit » sont des constantes définies par la classe FormatValue. Les propriétés de marge peuvent être des valeurs négatives. Voir aussi Padding changes in TLF 2.0 (disponible en anglais uniquement) Formatage du texte à l’aide de TLF Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Le package flashx.textLayout.formats contient des interfaces et classes qui permettent d’affecter des formats à tout objet FlowElement de l’arborescence d’enchaînements. Il existe deux manières d’appliquer le formatage. Vous pouvez affecter individuellement un format donné ou affecter simultanément un groupe de formats par le biais d’un objet de formatage spécial. L’interface ITextLayoutFormat rassemble tous les formats susceptibles d’être appliqués à un objet FlowElement. Certains formats s’appliquent à un paragraphe de texte ou conteneur entier mais pas, en toute logique, à des caractères individuels. Ainsi, les formats tels que la justification et les taquets de tabulation s’appliquent à des paragraphes entiers, mais pas à des caractères individuels. Affectation de formats à une classe FlowElement à l’aide de propriétés Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez affecter des formats à tout objet FlowElement par le biais de propriétés. La classe FlowElement implémente l’interface ITextLayoutFormat, c’est pourquoi toute sous-classe de la classe FlowElement doit également implémenter cette interface. Ainsi, le code suivant illustre l’affectation de formats individuels à une occurrence de ParagraphElement : var p:ParagraphElement = new ParagraphElement(); p.fontSize = 18; p.fontFamily = "Arial"; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 451 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Affectation de formats à une classe FlowElement à l’aide de la classe TextLayoutFormat Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Vous pouvez appliquer des formats à un objet FlowElement à l’aide de la classe TextLayoutFormat. Cette classe permet de créer un objet de formatage spécial qui contient toutes les valeurs de formatage requises. Vous pouvez ensuite affecter cet objet à la propriété format de n’importe quel objet FlowElement. Les classes TextLayoutFormat et FlowElement implémentent toutes deux l’interface ITextLayoutFormat. Cette caractéristique garantit que les deux classes contiennent les mêmes propriétés de format. Pour plus d’informations, voir TextLayoutFormat dans le manuel Guide de référence ActionScript 3.0 pour la plateforme Adobe Flash. Héritage des formats Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Les formats sont hérités par le biais de l’arborescence d’enchaînements. Si vous affectez une occurrence de TextLayoutFormat à une occurrence de FlowElement possédant des enfants, la structure déclenche un processus appelé cascade. Dans le cadre d’une cascade, la structure examine de manière récursive chaque noeud de la hiérarchie qui hérite de valeurs de l’objet FlowElement. Elle détermine ensuite s’il est nécessaire d’affecter les valeurs héritées à chaque propriété de formatage. La cascade est définie par les règles suivantes : 1 Les valeurs des propriétés sont héritées uniquement d’un ancêtre proche (appelé également le parent). 2 Les valeurs des propriétés sont héritées uniquement si la propriété ne possède aucune valeur (en d’autres termes, la valeur est non définie).. 3 Certains attributs non définis n’héritent d’une valeur que si la valeur de l’attribut est définie sur « inherit » ou sur la constante flashx.textLayout.formats.FormatValue.INHERIT. Par exemple, si vous définissez la valeur fontSize au niveau du flux TextFlow, ce paramètre s’applique à tous les éléments du flux TextFlow. En d’autres mots, les valeurs sont propagées en cascade vers le bas de l’arborescence d’enchaînements. Vous pouvez cependant remplacer la valeur d’un élément donné en lui affectant directement une nouvelle valeur. A titre de contre-exemple, si vous définissez la valeur backgroundColor au niveau TextFlow, les enfants du flux TextFlow n’en héritent pas. La propriété backgroundColor n’hérite en effet jamais de ses parents au cours d’une cascade. Vous pouvez éviter ce comportement en définissant la propriété backgroundColor de chaque enfant sur la valeur flashx.textLayout.formats.FormatValue.INHERIT.. Pour plus d’informations, voir TextLayoutFormat dans le manuel Guide de référence ActionScript 3.0 pour la plateforme Adobe Flash. Importation et exportation de texte à l’aide de TLF Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La classe TextConverter du package flashx.textLayout.conversion.* permet d’importer du texte dans TLF et d’en exporter hors de ce dernier. Utilisez cette classe si vous envisagez de charger du texte lors de l’exécution au lieu de le compiler dans le fichier SWF. Cette classe sert également à exporter du texte stocké dans une occurrence de TextFlow dans un objet String ou XML. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 452 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Les procédures d’importation et d’exportation sont simples. Il vous suffit d’appeler les méthodes export() ou importToFlow(), qui font toutes deux partie de la classe TextConverter. Ces deux méthodes sont statiques, ce qui signifie que vous les appelez sur la classe TextConverter plutôt que sur une occurrence de cette dernière. Les classes intégrées au package flashx.textLayout.conversion sont d’une souplesse considérable en ce qui concerne l’emplacement de stockage du texte. Ainsi, si vous stockez le texte dans une base de données, vous pouvez l’importer dans la structure pour l’afficher. Grâce aux classes du package flashx.textLayout.edit, vous pouvez alors modifier le texte et réexporter le texte modifié dans la base de données. Pour plus d’informations, voir flashx.textLayout.conversion dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Gestion des conteneurs de texte à l’aide de TLF Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Une fois le texte stocké dans les structures de données TLF, Flash Player peut l’afficher. Le texte stocké dans l’arborescence d’enchaînements doit être converti dans un format géré par Flash Player. TLF propose deux méthodes de création d’objets d’affichage à partir d’un enchaînement. La première approche, plus simple, est adaptée à l’affichage de texte statique. La seconde, plus complexe, permet de créer du texte dynamique qui peut être sélectionné et modifié. Dans les deux cas, le texte est finalement converti en occurrences de la classe TextLine, qui fait partie du package flash.text.engine de Flash Player 10. Création de texte statique L’approche simple exploite la classe TextFlowTextLineFactory, qui se trouve dans le package flashx.textLayout.factory. L’avantage de cette approche, hormis sa simplicité, est qu’elle limite l’encombrement mémoire par rapport à l’approche FlowComposer. Il est recommandé d’y faire appel pour le texte statique que l’utilisateur ne doit ni modifier, ni sélectionner, ni faire défiler. Pour plus d’informations, voir TextFlowTextLineFactory dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Création de texte dynamique et de conteneurs Un compositeur d’enchaînements permet de mieux contrôler l’affichage du texte que la classe TextFlowTextLineFactory. Grâce à un compositeur d’enchaînements, les utilisateurs peuvent, par exemple, sélectionner et modifier le texte. Pour plus d’informations, voir « Activation de la sélection, de la modification et de l’annulation de texte à l’aide de TLF » à la page 453. Un compositeur d’enchaînements est une occurrence de la classe StandardFlowComposer du package flashx.textLayout.compose. Il gère la conversion d’éléments TextFlow en occurrences de TextLine, ainsi que l’insertion de ces occurrences dans un ou plusieurs conteneurs. Un compositeur IFlowComposer possède un minimum de zéro objet ContainerController. IFlowComposer ContainerController TextFlow TextLine TextLine Stage Sprite GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 453 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 Chaque occurrence de TextFlow possède un objet correspondant qui implémente l’interface IFlowComposer. Cet objet IFlowComposer est accessible via la propriété TextFlow.flowComposer. Vous pouvez appeler les méthodes définies par l’interface IFlowComposer par le biais de cette propriété. Ces méthodes permettent d’associer le texte à un ou plusieurs conteneurs et de préparer le texte de sorte à l’afficher au sein d’un conteneur. Un conteneur est une occurrence de la classe Sprite, qui est une sous-classe de la classe DisplayObjectContainer. Ces deux classes font partie intégrante de l’API de liste d’affichage Flash Player. Un conteneur est une forme plus avancée du rectangle de sélection utilisé par la classe TextLineFactory. A l’instar du rectangle de sélection, un conteneur circonscrit la zone dans laquelle s’affichent les occurrences de TextLine. A l’encontre d’un rectangle de sélection, à chaque conteneur correspond un objet de « contrôleur ». Le contrôleur gère le défilement, la composition, la liaison, le formatage et la gestion des événements à l’intention d’un conteneur ou d’un ensemble de conteneurs. A chaque conteneur correspond un objet de contrôleur, qui est une occurrence de la classe ContainerController du package flashx.textLayout.container. Pour afficher du texte, créez un objet de contrôleur destiné à gérer le conteneur et associez-le au compositeur d’enchaînements. Une fois le conteneur associé, composez le texte pour pouvoir l’afficher. Les conteneurs gèrent donc deux états, composition et affichage. La composition correspond au processus de conversion du texte issu de l’arborescence d’enchaînements en occurrences de TextLine, et de calcul de la position de ces occurrences dans le conteneur. L’affichage correspond au processus de mise à jour de la liste Flash Player. Pour plus d’informations, voir IFlowComposer, StandardFlowComposer et ContainerController dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Activation de la sélection, de la modification et de l’annulation de texte à l’aide de TLF Flash Player 9.0 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La possibilité de sélectionner ou modifier du texte est contrôlée au niveau de l’enchaînement. Chaque occurrence de la classe TextFlow est associée à un gestionnaire d’interaction. Vous pouvez accéder au gestionnaire d’interaction d’un objet TextFlow par le biais de la propriété TextFlow.interactionManager de ce dernier. Pour activer la sélection de texte, affectez une occurrence de la classe SelectionManager à la propriété interactionManager. Pour activer la sélection et la modification du texte, affectez une occurrence de la classe EditManager à la place d’une occurrence de la classe SelectionManager. Pour annuler une opération; créez une occurrence de la classe UndoManager et spécifiezla en tant qu’argument lorsque vous appelez le constructeur associé à EditManager. La classe UndoManager gère un historique des activités de modification les plus récentes de l’utilisateur et autorise ce dernier à annuler ou rétablir des modifications spécifiques. Ces trois classes font partie du package de modification. Pour plus d’informations, voir SelectionManager, EditManager et UndoManager dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Gestion des événements à l’aide de TLF Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Les objets TextFlow distribuent des événements dans de nombreuses circonstances, à savoir : • lors d’un changement de texte ou de mise en forme ; GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 454 Utilisation de Text Layout Framework Dernière mise à jour le 27/4/2013 • avant le début d’une opération ou après la fin de cette dernière ; • lors d’un changement d’état d’un objet FlowElement ; • au terme d’une opération de composition. Pour plus d’informations, voir flashx.textLayout.events dans le manuel Guide de référence ActionScript 3.0 pour la plate-forme Adobe Flash. Voir aussi TLF FlowElement and LinkElement Events and EventMirrors (disponible en anglais uniquement) Positionnement des images dans le texte Pour positionner l’élément InlineGraphicElement dans le texte, vous disposez des propriétés suivantes : • Propriété float de la classe InlineGraphicElement • Propriété clearFloats de la classe FlowElement La propriété float contrôle le positionnement du graphique et du texte qui l’entoure. La propriété clearFloats contrôle le positionnement des éléments du paragraphe par rapport à l’élément flottant. Pour contrôler l’emplacement d’une image dans un élément de texte, vous disposez de la propriété float. L’exemple suivant insère une image dans un paragraphe et l’aligne à gauche de sorte que le texte l’habille sur la droite : Images in a flow are a good thing. For example, here is a float. It should show on the left: Don't you agree? Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here. Another sentence here. Les valeurs valides de la propriété float sont « left », « right », « start », « end » et « none ». La classe Float définit ces constantes. La valeur par défaut est « none ». La propriété clearFloats s’avère utile lorsque vous souhaitez ajuster la position de départ des paragraphes suivants qui habilleraient normalement l’image. Supposons, par exemple, que la largeur d’une image excède celle du premier paragraphe. Pour s’assurer que le deuxième paragraphe débute après l’image, définissez la propriété clearFloats. L’exemple suivant utilise une image dont la hauteur excède celle du texte dans le premier paragraphe. Pour que le deuxième paragraphe débute après l’image dans le bloc de texte, cet exemple définit la propriété clearFloats associée au deuxième paragraphe sur « end ». Here is another float, it should show up on the right: We'll add another paragraph that should clear past it.This should appear after the previous float on the right. Les valeurs valides de la propriété clearFloats sont « left », « right », « end », « start », « none » et « both ». La classe ClearFloats définit ces constantes. Vous pouvez également définir la propriété clearFloats sur « inherit » (constante définie par la classe FormatValue). La valeur par défaut est « none ». Voir aussi TLF Floats (disponible en anglais uniquement) 455 Dernière mise à jour le 27/4/2013 Chapitre 24 : Utilisation du son Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures ActionScript est conçu pour des applications immersives, interactives, et le son est un élément des applications immersives puissantes souvent ignoré. Vous pouvez ajouter des effets de son à un jeu vidéo, une réaction acoustique à l’interface utilisateur d’une application, ou même créer un programme qui analyse des fichiers mp3 chargés sur Internet, avec du son au coeur de l’application. Vous pouvez charger des fichiers audio externes et manipuler l’audio incorporé à un fichier SWF. Vous pouvez contrôler l’audio, créer des représentations visuelles des informations de son et capturer le son du microphone d’un utilisateur. Voir aussi Package flash.media flash.events.SampleDataEvent Principes de base de l’utilisation du son Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les ordinateurs peuvent capturer et coder l’audio numérique (représentation des informations de son de l’ordinateur), le stocker et le récupérer pour le diffuser sur des hauts-parleurs. Il est possible de lire le son à l’aide d’Adobe® Flash® Player ou Adobe® AIR™ et ActionScript. Lorsque les données audio sont converties au format numérique, elles possèdent différentes caractéristiques (volume du son, son stéréo ou mono). Lorsque vous lisez un son dans ActionScript, vous pouvez régler ces caractéristiques également (augmenter le volume du son ou faire comme s’il provenait d’une certaine direction, par exemple). Avant de contrôler un son dans ActionScript, les informations de son doivent être chargées dans Flash Player ou AIR. Vous disposez de cinq techniques de chargement des données audio dans Flash Player ou AIR afin de les utiliser avec ActionScript. • Vous pouvez charger un fichier audio externe tel qu’un fichier mp3 dans le fichier SWF. • Vous pouvez incorporer directement les informations audio dans le fichier SWF lors de sa création. • Vous pouvez capturer l’audio à partir d’un microphone connecté à l’ordinateur d’un utilisateur. • Vous pouvez diffuser l’audio en continu à partir d’un serveur. • Vous pouvez générer et lire l’audio en mode dynamique. Lorsque vous chargez des données audio depuis un fichier de son externe, vous pouvez commencer par lire le début du fichier audio pendant le chargement du reste des données audio. Même s’il existe différents formats de fichier audio utilisés pour coder l’audio numérique, ActionScript 3.0, Flash Player et AIR prennent en charge les fichiers audio stockés au format mp3. Ils ne peuvent pas charger ni lire directement des fichiers audio de formats différents (WAV ou AIFF, par exemple). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 456 Utilisation du son Dernière mise à jour le 27/4/2013 Lorsque vous utilisez du son dans ActionScript, vous utilisez probablement plusieurs classes issues du package flash.media. Utilisez la classe Sound pour accéder aux informations audio en chargeant un fichier audio ou en affectant une fonction à un événement pour échantillonner des données de son, puis en démarrant la lecture. Une fois que vous avez démarré la lecture d’un son, Flash Player et AIR vous permettent d’accéder à un objet SoundChannel. Etant donné qu’un fichier audio chargé est un son parmi d’autres que vous lisez sur l’ordinateur d’un utilisateur, chaque son individuel lu utilise son objet SoundChannel ; c’est la sortie combinée de tous les objets SoundChannel mixés qui est lue sur les haut-parleurs de l’ordinateur. Vous utilisez l’occurrence SoundChannel pour contrôler les propriétés du son et arrêter sa lecture. Enfin, si vous souhaitez contrôler l’audio combiné, la classe SoundMixer vous permet de contrôler la sortie mixée. Vous pouvez également utiliser d’autres classes pour effectuer des tâches plus spécifiques lorsque vous utilisez du son dans ActionScript. Pour plus d’informations sur toutes les classes liées au son, voir « Présentation de l’architecture audio » à la page 456. Concepts importants et terminologie La liste de référence suivante contient des termes importants que vous rencontrerez peut-être : Amplitude Distance d’un point sur la courbe audio à partir de la ligne zéro ou d’équilibre. Débit Quantité de données codées ou diffusées en continu pour chaque seconde d’un fichier audio. Pour les fichiers mp3, le débit est généralement exprimé en milliers de bits par seconde (kbits/s). Un débit supérieur est souvent synonyme d’une onde acoustique de meilleure qualité. Mise en mémoire tampon Réception et stockage de données audio avant leur lecture. MP3 MPEG-1 Audio Layer 3, ou MP3, est un format de compression audio connu. Balance horizontale Positionnement d’un signal audio entre les canaux gauche et droit dans un champ acoustique stéréo. Crête Point le plus élevé d’une courbe audio. Fréquence d’échantillonnage Définit le nombre d’échantillons par seconde extraits d’un signal audio analogique pour créer un signal numérique. La fréquence d’échantillonnage d’un CD audio standard est de 44,1 kHz ou 44 100 échantillons par seconde. Diffusion en continu Processus consistant à lire les premières sections d’un fichier audio ou vidéo pendant le chargement des dernières sections de ce fichier depuis un serveur. Volume Intensité d’un son. Courbe audio Forme d’un graphique des différentes amplitudes d’un signal audio au cours du temps. Présentation de l’architecture audio Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Vos applications peuvent charger des données audio à partir de cinq sources principales : • Fichiers audio externes chargés lors de l’exécution • Ressources audio incorporées dans le fichier SWF de l’application • Données audio issues d’un microphone connecté au système de l’utilisateur • Données audio diffusées en continu depuis une passerelle multimédia telle que Flash Media Server GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 457 Utilisation du son Dernière mise à jour le 27/4/2013 • Données audio générées dynamiquement par le biais du gestionnaire d’événement sampleData Vous pouvez charger entièrement les données audio avant leur lecture, ou bien les lire pendant leur chargement. ActionScript 3.0 prend en charge les fichiers audio stockés au format mp3. Ils ne peuvent pas charger ni lire directement des fichiers audio de formats différents, tels que WAV ou AIFF. Cependant, à partir de Flash Player 9.0.115.0, les fichiers audio AAC peuvent être chargés et lus à l’aide de la classe NetStream. Il s’agit de la même technique que celle utilisée pour le chargement et la lecture de contenu vidéo. Pour plus d’informations sur cette technique, voir « Utilisation de la vidéo » à la page 489. Vous pouvez utiliser Adobe Flash Professional pour importer des fichiers audio WAV ou AIFF puis les intégrer dans les fichiers SWF de votre application au format mp3. L’outil de programmation Flash vous permet également de compresser des fichiers audio intégrés pour réduire leur taille (mais ceci se fait au détriment de la qualité du son). Pour plus d’informations, voir « Importation de sons » dans Utilisation de Flash. L’architecture audio d’ActionScript 3.0 utilise les classes suivantes dans le package flash.media. Chaque son chargé et lu nécessite sa propre occurrence des classes Sound et SoundChannel. La sortie issue de plusieurs occurrences de SoundChannel est ensuite mixée par la classe SoundMixer globale pendant la lecture. Les classes Sound, SoundChannel, et SoundMixer ne sont pas utilisées pour les données audio provenant d’un microphone ou d’une transmission de passerelle multimédia en continu (Flash Media Server, par exemple). Classe Description flash.media.Sound La classe Sound gère le chargement du son, les propriétés de son de base et lance une lecture audio. flash.media.SoundChannel Lorsqu’une application lit un objet Sound, un objet SoundChannel est créé pour contrôler la lecture. L’objet SoundChannel contrôle le volume des canaux de lecture gauche et droit du son. Chaque son lu possède son propre objet SoundChannel. flash.media.SoundLoaderContext La classe SoundLoaderContext définit le nombre de secondes de mise en mémoire tampon à utiliser lors du chargement d’un son, et indique si Flash Player ou AIR recherche un fichier de régulation sur le serveur lors du chargement d’un fichier. Un objet SoundLoaderContext est utilisé comme paramètre pour la méthode Sound.load(). flash.media.SoundMixer La classe SoundMixer contrôle les propriétés de lecture et de sécurité de tous les sons dans une application. En effet, plusieurs canaux audio sont mixés au moyen d’un objet SoundMixer commun. Par conséquent, les valeurs de propriété dans l’objet SoundMixer affectent tous les objets SoundChannel en cours de lecture. flash.media.SoundTransform La classe SoundTransform contient des valeurs qui contrôlent le volume du son et la balance. Vous pouvez appliquer un objet SoundTransform à un objet SoundChannel individuel, à l’objet SoundMixer global, ou à un objet Microphone, entre autres. flash.media.ID3Info Un objet ID3Info contient des propriétés qui représentent les informations de métadonnées ID3 souvent stockées dans des fichiers audio mp3. flash.media.Microphone La classe Microphone représente un microphone ou un autre périphérique d’entrée de son connecté à l’ordinateur de l’utilisateur. L’entrée audio issue d’un microphone peut être acheminée vers des hautparleurs locaux ou envoyée à un serveur distant. L’objet Microphone contrôle le gain, la fréquence d’échantillonnage et d’autres caractéristiques de son propre flux de son. flash.media.AudioPlaybackMode La classe AudioPlaybackMode définit les constantes pour la propriété audioPlaybackMode de la classe SoundMixer. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 458 Utilisation du son Dernière mise à jour le 27/4/2013 Chargement de fichiers audio externes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Chaque occurrence de la classe Sound permet de charger et de déclencher la lecture d’une ressource audio spécifique. Une application ne peut pas réutiliser un objet Sound pour charger plusieurs sons. Si elle souhaite charger une nouvelle ressource audio, elle doit créer un objet Sound. Si vous chargez un fichier audio de petite taille (un son clic à associer à un bouton, par exemple), votre application peut créer un objet Sound qui charge automatiquement le fichier audio, comme indiqué ci-dessous : var req:URLRequest = new URLRequest("click.mp3"); var s:Sound = new Sound(req); Le constructeur Sound() accepte un objet URLRequest comme premier paramètre. Lorsqu’une valeur pour le paramètre URLRequest est fournie, le nouvel objet Sound commence à charger automatiquement la ressource audio spécifiée. Dans le meilleur des cas, votre application doit surveiller la progression du chargement du son et rechercher les erreurs pendant le chargement. Par exemple, si le son clic est volumineux, il risque de ne pas être totalement chargé lorsque l’utilisateur clique sur le bouton qui déclenche le son. Si vous tentez de lire un son non chargé, une erreur d’exécution risque de se produire. Il est préférable d’attendre la fin du chargement du son avant de permettre aux utilisateurs d’effectuer des actions risquant de lancer la lecture des sons. Un objet Sound envoie plusieurs événements différents pendant le chargement du son. Votre application peut écouter ces événements pour suivre la progression du chargement et vérifier que le son est complètement chargé avant la lecture. Le tableau suivant répertorie les événements pouvant être envoyés par un objet Sound. Le code suivant illustre la lecture d’un son après son chargement: import flash.events.Event; import flash.media.Sound; import flash.net.URLRequest; var s:Sound = new Sound(); s.addEventListener(Event.COMPLETE, onSoundLoaded); var req:URLRequest = new URLRequest("bigSound.mp3"); s.load(req); function onSoundLoaded(event:Event):void { var localSound:Sound = event.target as Sound; localSound.play(); } Evénement Description open (Event.OPEN) Envoyé juste avant le début du chargement du son. progress (ProgressEvent.PROGRESS) Envoyé régulièrement pendant le chargement du son lorsque des données sont reçues du fichier ou du flux. id3 (Event.ID3) Envoyé lorsque des données ID3 sont disponibles pour un son mp3. complete (Event.COMPLETE) Envoyé lorsque toutes les données de la ressource audio ont été chargées. ioError (IOErrorEvent.IO_ERROR) Envoyé lorsqu’un fichier audio est introuvable ou lorsque le chargement est interrompu avant la réception de toutes les données audio. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 459 Utilisation du son Dernière mise à jour le 27/4/2013 Tout d’abord, l’exemple de code crée un objet Sound sans lui donner de valeur initiale pour le paramètre URLRequest. Ensuite, il écoute l’événement Event.COMPLETE issu de l’objet Sound. La méthode onSoundLoaded() s’exécute alors lorsque toutes les données audio sont chargées. Puis, il appelle la méthode Sound.load() avec une nouvelle valeur URLRequest pour le fichier audio. La méthode onSoundLoaded() s’exécute lorsque le chargement du son est terminé. La propriété target de l’objet Event est une référence à l’objet Sound. L’appel à la méthode play() de l’objet Sound lance ensuite la lecture du son. Surveillance du chargement du son Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les fichiers audio peuvent être très volumineux et leur chargement très long. Flash Player et AIR permettent à votre application de lire des sons avant leur chargement complet. Vous pouvez indiquer à l’utilisateur la quantité de données audio ayant été chargées et la quantité de son déjà lue. La classe Sound envoie deux événements permettant d’afficher facilement la progression du chargement d’un son : ProgressEvent.PROGRESS et Event.COMPLETE. L’exemple suivant indique comment utiliser ces événements pour afficher les informations de progression concernant le son en cours de chargement : import flash.events.Event; import flash.events.ProgressEvent; import flash.media.Sound; import flash.net.URLRequest; var s:Sound = new Sound(); s.addEventListener(ProgressEvent.PROGRESS, onLoadProgress); s.addEventListener(Event.COMPLETE, onLoadComplete); s.addEventListener(IOErrorEvent.IO_ERROR, onIOError); var req:URLRequest = new URLRequest("bigSound.mp3"); s.load(req); function onLoadProgress(event:ProgressEvent):void { var loadedPct:uint = Math.round(100 * (event.bytesLoaded / event.bytesTotal)); trace("The sound is " + loadedPct + "% loaded."); } function onLoadComplete(event:Event):void { var localSound:Sound = event.target as Sound; localSound.play(); } function onIOError(event:IOErrorEvent) { trace("The sound could not be loaded: " + event.text); } Ce code crée d’abord un objet Sound puis lui ajoute des écouteurs pour les événements ProgressEvent.PROGRESS et Event.COMPLETE. Une fois que la méthode Sound.load() a été appelée et que les premières données sont reçues du fichier audio, un événement ProgressEvent.PROGRESS a lieu et déclenche la méthode onSoundLoadProgress(). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 460 Utilisation du son Dernière mise à jour le 27/4/2013 Le pourcentage des données audio chargées est équivalent à la valeur de la propriété bytesLoaded de l’objet ProgressEvent divisé par la valeur de la propriété bytesTotal. Les mêmes propriétés bytesLoaded et bytesTotal sont disponibles sur l’objet Sound également. L’exemple ci-dessus indique les messages relatifs à la progression du chargement du son, mais vous pouvez facilement utiliser les valeurs bytesLoaded et bytesTotal pour mettre à jour les composants de la barre de progression, tels que ceux intégrés à la structure d’Adobe Flex ou à l’outil de programmation d’Adobe Flash. Cet exemple indique également comment une application peut reconnaître et répondre à une erreur lors du chargement des fichiers audio. Par exemple, si un fichier audio avec le nom de fichier donné est introuvable, un événement Event.IO_ERROR est envoyé par l’objet Sound. Dans le code précédent, la méthode onIOError() s’exécute et affiche un message d’erreur court lorsqu’une erreur se produit. Utilisation des sons intégrés Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Utilisez des sons intégrés (au lieu de charger du son depuis un fichier externe) surtout dans le cas de fichiers audio de petite taille servant d’indicateurs dans l’interface utilisateur de votre application (des sons qui sont lus lorsque vous cliquez sur des boutons, par exemple). Lorsque vous incorporez un fichier audio dans votre application, la taille du fichier SWF résultant augmente proportionnellement à la taille du fichier audio. Ceci signifie que lorsque vous incorporez des fichiers volumineux dans votre application, la taille de votre fichier SWF risque de devenir trop importante. La méthode exacte à utiliser pour incorporer un fichier de police dans le fichier SWF de l’application varie selon l’environnement de développement. Utilisation d’un fichier audio incorporé dans Flash Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’outil de programmation Flash vous permet d’importer des sons dans un grand nombre de formats audio et de les stocker comme symboles dans la bibliothèque. Vous pouvez ensuite les affecter à des images dans le scénario ou aux images d’un état de bouton, les utiliser avec des comportements ou directement dans du code ActionScript. Cette section décrit comment utiliser des sons incorporés dans du code ActionScript avec l’outil de programmation Flash. Pour plus d’informations sur les autres façons d’utiliser des sons incorporés dans Flash, voir « Importation de sons » dans Utilisation de Flash. Pour intégrer un fichier son à l’aide de l’outil de programmation Flash : 1 Sélectionnez Fichier > Importer > Importer dans la bibliothèque, puis sélectionnez un fichier audio et importez-le. 2 Cliquez avec le bouton droit de la souris sur le nom du fichier importé dans le panneau Bibliothèque, et sélectionnez Propriétés. Activez la case à cocher Exporter pour ActionScript. 3 Dans le champ Classe, entrez un nom à utiliser lorsque vous faites référence à ce son incorporé dans ActionScript. Par défaut, il utilisera le nom du fichier audio dans ce champ. Si le nom du fichier contient un point (comme dans DrumSound.mp3), vous devez le remplacer par DrumSound ; ActionScript n’autorise pas le caractère point dans les noms de classe. Le champ Classe de base devrait encore afficher flash.media.Sound. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 461 Utilisation du son Dernière mise à jour le 27/4/2013 4 Cliquez sur OK. Il se peut qu’une boîte de dialogue indiquant qu’une définition pour cette classe est introuvable dans le chemin de classe apparaisse. Cliquez sur OK et continuez. Si vous avez saisi un nom qui ne correspond pas à celui d’une classe contenue dans le chemin de classe de votre application, une nouvelle classe qui hérite de la classe flash.media.Sound est générée automatiquement. 5 Pour utiliser le son incorporé, vous référencez le nom de classe pour ce son dans ActionScript. Par exemple, le code suivant commence par créer une occurrence de la classe DrumSound générée automatiquement : var drum:DrumSound = new DrumSound(); var channel:SoundChannel = drum.play(); DrumSound est une sous-classe de la classe flash.media.Sound. Par conséquent, elle hérite des méthodes et des propriétés de la classe Sound, notamment de la méthode play() comme indiqué ci-dessus. Utilisation d’un fichier audio intégré dans Flex Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Il existe plusieurs moyens d’intégrer des ressources son dans une application Flex. Vous pouvez par exemple : • utiliser la balise de métadonnées [Embed] dans un script ; • utiliser la directive @Embed dans MXML pour affecter une ressource intégrée en tant que propriété d’un composant, telle que Button ou SoundEffect ; • utiliser la directive @Embed dans un fichier CSS. Cette section décrit la première option : comment intégrer des sons dans le code ActionScript au sein d’une application Flex à l’aide de la balise de métadonnées [Embed]. Pour intégrer un élément dans le code ActionScript, utilisez la balise de métadonnées [Embed]. Placez le fichier audio dans le dossier source principal ou dans un autre dossier qui se trouve dans le chemin de création de votre projet. Lorsque le compilateur détecte une balise de métadonnées Embed, il crée la classe d’actifs intégrés à votre intention. Vous pouvez accéder à la classe par le biais d’une variable de données de type Class que vous déclarez immédiatement après la balise de métadonnées [Embed]. Le code suivant intègre un son appelé smallSound.mp3 et utilise une variable appelée soundClass pour stocker une référence à la classe de ressources intégrées associée à ce son. Le code crée ensuite une occurrence de la classe de ressources intégrées, l’attribue comme une occurrence de la classe Sound et appelle la méthode play() sur cette occurrence : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 462 Utilisation du son Dernière mise à jour le 27/4/2013 package { import flash.display.Sprite; import flash.media.Sound; import flash.media.SoundChannel; public class EmbeddedSoundExample extends Sprite { [Embed(source="smallSound.mp3")] public var soundClass:Class; public function EmbeddedSoundExample() { var smallSound:Sound = new soundClass() as Sound; smallSound.play(); } } } Pour utiliser le son incorporé en vue de définir une propriété d’un composant Flex, elle doit être attribuée comme une occurrence de la classe mx.core.SoundAsset plutôt que comme une occurrence de la classe Sound. Pour obtenir un exemple similaire qui utilise la classe SoundAsset, voir « Classes des éléments incorporés » dans le manuel Formation à ActionScript 3.0. Utilisation de fichiers audio de lecture en continu Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lorsqu’un fichier audio ou un fichier vidéo est lu alors que ses données sont encore en cours de chargement, il est lu en continu. Les fichiers audio externes chargés depuis un serveur distant sont souvent lus en continu de façon à ce que l’utilisateur ne doive pas attendre le chargement complet des données audio pour écouter le son. La propriété SoundMixer.bufferTime représente le nombre de millisecondes de données audio que Flash Player ou AIR doit rassembler avant la lecture du son. En d’autres termes, si la propriété bufferTime est définie sur 5000, Flash Player ou AIR charge au moins 5 000 millisecondes de données depuis le fichier audio avant le début de la lecture du son. La valeur SoundMixer.bufferTime par défaut est 1000. Votre application peut ignorer la valeur SoundMixer.bufferTime globale pour un son individuel en spécifiant explicitement une nouvelle valeur bufferTime lors du chargement du son. Pour ignorer la durée du tampon par défaut, créez d’abord une occurrence de la classe SoundLoaderContext, définissez sa propriété bufferTime, puis transmettez-la comme paramètre à la méthode Sound.load(), comme indiqué ci-dessous : import flash.media.Sound; import flash.media.SoundLoaderContext; import flash.net.URLRequest; var s:Sound = new Sound(); var req:URLRequest = new URLRequest("bigSound.mp3"); var context:SoundLoaderContext = new SoundLoaderContext(8000, true); s.load(req, context); s.play(); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 463 Utilisation du son Dernière mise à jour le 27/4/2013 Pendant la lecture, Flash Player ou AIR tente de conserver le tampon audio à la même taille ou à une taille supérieure. Si le téléchargement des données audio est plus rapide que la vitesse de la lecture, cette dernière continue sans interruption. Néanmoins, si la vitesse de chargement des données est ralentie en raison des limites du réseau, la tête de lecture peut atteindre la fin du tampon audio. Dans ce cas, la lecture est suspendue mais elle reprend automatiquement lorsque d’autres données audio sont chargées. Pour savoir si la lecture est suspendue car Flash Player ou AIR attend le chargement des données, utilisez la propriété Sound.isBuffering. Utilisation de données audio générées de façon dynamique Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Remarque : Flash Player 10 et Adobe AIR 1.5 donnent désormais la possibilité de générer des données audio de façon dynamique. Plutôt que de charger ou de diffuser en continu un son existant, vous pouvez générer des données audio de façon dynamique. Vous pouvez générer des données audio lorsque vous affectez un écouteur associé à l’événement sampleData d’un objet Sound (l’événement sampleData est défini dans la classe SampleDataEvent du package flash.events). Dans cet environnement, l’objet Sound ne charge pas de données audio à partir d’un fichier. Il agit en fait en tant que socket pour les données audio qui lui sont diffusées en continu par l’intermédiaire de la fonction que vous affectez à cet événement. Lorsque vous ajoutez un écouteur d’événement sampleData à un objet Sound, celui-ci demande périodiquement des données à ajouter au tampon audio. Ce tampon contient des données destinées à être lues par l’objet. Une fois appelé, la méthode play() de l’objet Sound distribue l’événement sampleData lorsqu’il demande de nouvelles données audio. Ceci n’est vrai que si l’objet Sound n’a pas chargé de données mp3 à partir d’un fichier. L’objet SampleDataEvent comprend une propriété data. Dans votre écouteur d’événement, vous écrivez des objets ByteArray dans cet objet data. Les tableaux d’octets que vous écrivez dans cet objet s’ajoutent aux données figurant dans le tampon que lit l’objet Sound. Le tableau d’octets que contient le tampon est un flux de valeurs en virgule flottante comprises en -1 et 1. Chaque valeur représente l’amplitude d’un canal unique (gauche ou droit) d’un échantillon audio. Le son est échantillonné à 44 100 échantillons par seconde. Chaque échantillon contient un canal gauche et un canal droit, entrelacés sous forme de données en virgule flottante dans le tableau d’octets. Dans votre fonction gestionnaire, vous utilisez la méthode ByteArray.writeFloat() pour écrire dans la propriété data de l’événement sampleData. Par exemple, le code suivant génère une onde sinusoïdale : var mySound:Sound = new Sound(); mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, sineWaveGenerator); mySound.play(); function sineWaveGenerator(event:SampleDataEvent):void { for (var i:int = 0; i < 8192; i++) { var n:Number = Math.sin((i + event.position) / Math.PI / 4); event.data.writeFloat(n); event.data.writeFloat(n); } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 464 Utilisation du son Dernière mise à jour le 27/4/2013 Lorsque vous appelez Sound.play(), l’application commence à appeler votre gestionnaire d’événement pour demander des données audio d’échantillonnage. Elle continue à envoyer des événements pendant la lecture du son jusqu’à ce que vous cessiez de fournir des données ou que vous appeliez la méthode SoundChannel.stop(). La période d’attente de l’événement varie selon les plates-formes et peut encore changer dans les futures versions de Flash Player et AIR. Plutôt que de vous appuyer sur une période d’attente spécifique, calculez-la. Pour calculer la période d’attente, utilisez la formule suivante : (SampleDataEvent.position / 44.1) - SoundChannelObject.position Fournissez entre 2 048 et 8 192 échantillons à la propriété data de l’objet SampleDataEvent (pour chaque appel du gestionnaire d’événement). Pour des performances optimales, fournissez autant d’échantillons que possible (8 192 au maximum). Moins vous fournissez d’échantillons, plus il est probable que des bruits parasites se feront entendre pendant la lecture. Ce comportement varie selon les plates-formes et peut se produire dans diverses situations, lors du redimensionnement du navigateur, par exemple. Un code qui fonctionne correctement sur une plate-forme lorsque vous fournissez uniquement 2 048 échantillons ne marchera pas aussi bien sur une autre plate-forme. S’il vous faut le plus court délai d’attente possible, envisagez de permettre à l’utilisateur de sélectionner la quantité de données. Si vous fournissez moins de 2 048 échantillons (par appel de l’écouteur d’événement sampleData), l’application s’arrête à l’issue de la lecture des échantillons restants. L’objet SoundChannel distribue alors un événement SoundComplete. Modification du son issu de données MP3 Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures La méthode SoundExtract vous permet d’extraire des données d’un objet Sound. Vous pouvez utiliser (et modifier) ces données pour accéder en écriture au flux continu dynamique d’un autre objet Sound à des fins de lecture. Ainsi, le code suivant utilise les octets d’un fichier MP3 chargé et les transmet par le biais d’une fonction de filtre, upOctave() : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 465 Utilisation du son Dernière mise à jour le 27/4/2013 var mySound:Sound = new Sound(); var sourceSnd:Sound = new Sound(); var urlReq:URLRequest = new URLRequest("test.mp3"); sourceSnd.load(urlReq); sourceSnd.addEventListener(Event.COMPLETE, loaded); function loaded(event:Event):void { mySound.addEventListener(SampleDataEvent.SAMPLE_DATA, processSound); mySound.play(); } function processSound(event:SampleDataEvent):void { var bytes:ByteArray = new ByteArray(); sourceSnd.extract(bytes, 8192); event.data.writeBytes(upOctave(bytes)); } function upOctave(bytes:ByteArray):ByteArray { var returnBytes:ByteArray = new ByteArray(); bytes.position = 0; while(bytes.bytesAvailable > 0) { returnBytes.writeFloat(bytes.readFloat()); returnBytes.writeFloat(bytes.readFloat()); if (bytes.bytesAvailable > 0) { bytes.position += 8; } } return returnBytes; } Limitations relatives aux sons générés Flash Player 10 et les versions ultérieures, Adobe AIR 1.5 et les versions ultérieures Lorsque vous utilisez un écouteur d’événement sampleData avec un objet Sound, les seules autres méthodes Sound activées sont Sound.extract() et Sound.play(). L’appel d’autres méthodes ou propriétés donne lieu à une exception. Tous les méthodes et propriétés de l’objet SoundChannel sont toujours activées. Lecture de sons Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Lire un son chargé peut être aussi simple qu’appeler la méthode Sound.play() pour un objet Sound, comme suit : var snd:Sound = new Sound(new URLRequest("smallSound.mp3")); snd.play(); Lorsque vous lisez des sons à l’aide d’ActionScript 3.0, vous pouvez effectuer les opérations suivantes : • Lire un son à partir d’une position de début spécifique • Interrompre un son et reprendre la lecture ultérieurement à partir de la même position GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 466 Utilisation du son Dernière mise à jour le 27/4/2013 • Savoir exactement lorsque la lecture d’un son est terminée • Suivre la progression de la lecture d’un son • Modifier le volume ou la balance pendant la lecture d’un son Pour effectuer ces opérations pendant la lecture, utilisez les classes SoundChannel, SoundMixer et SoundTransform. La classe SoundChannel contrôle la lecture d’un seul son. La propriété SoundChannel.position peut être considérée comme une tête de lecture qui indique le point actuel dans les données audio en cours de lecture. Lorsqu’une application appelle la méthode Sound.play(), une occurrence de la classe SoundChannel est créée pour contrôler la lecture. Votre application peut lire un son à partir d’une position de début spécifique en la transmettant, en termes de millisecondes, comme paramètre startTime de la méthode Sound.play(). Elle peut également spécifier un nombre fixe de répétitions du son en succession rapide en transmettant une valeur numérique dans le paramètre loops de la méthode Sound.play(). Lorsque la méthode Sound.play() est appelée avec un paramètre startTime et un paramètre loops, le son est lu de façon répétée à partir du même point de début chaque fois, comme indiqué dans le code suivant : var snd:Sound = new Sound(new URLRequest("repeatingSound.mp3")); snd.play(1000, 3); Dans cet exemple, le son est lu à partir d’un point une seconde après le début du son, trois fois de suite. Pause et reprise d’un son Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Si votre application lit des sons longs (chansons ou podcasts, par exemple), vous pouvez permettre aux utilisateurs d’interrompre et de reprendre leur lecture. Il est impossible d’interrompre littéralement un son pendant la lecture dans ActionScript ; vous pouvez uniquement l’arrêter. Néanmoins, un son peut être lu à partir de n’importe quel point. Vous pouvez enregistrer la position du son au moment de l’arrêt puis le relire ultérieurement à partir de cette position. Par exemple, supposons que votre code charge et lit un fichier audio de la façon suivante : var snd:Sound = new Sound(new URLRequest("bigSound.mp3")); var channel:SoundChannel = snd.play(); Lors de la lecture du son, la propriété SoundChannel.position indique le point dans le fichier audio qui est en cours de lecture. Votre application peut stocker la valeur de position avant d’arrêter la lecture du son, comme suit : var pausePosition:int = channel.position; channel.stop(); Pour reprendre la lecture du son, transmettez la valeur de position stockée précédemment pour relancer le son à partir du même point d’arrêt précédent. channel = snd.play(pausePosition); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 467 Utilisation du son Dernière mise à jour le 27/4/2013 Surveillance de la lecture Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Votre application a peut-être besoin de savoir lorsque la lecture d’un son s’arrête afin de lancer la lecture d’un autre son ou d’effacer des ressources utilisées pendant la lecture précédente. La classe SoundChannel envoie un événement Event.SOUND_COMPLETE à la fin de la lecture du son. Votre application peut écouter cet événement et effectuer l’action appropriée, comme indiqué ci-dessous : import flash.events.Event; import flash.media.Sound; import flash.net.URLRequest; var snd:Sound = new Sound(); var req:URLRequest = new URLRequest("smallSound.mp3"); snd.load(req); var channel:SoundChannel = snd.play(); channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); public function onPlaybackComplete(event:Event) { trace("The sound has finished playing."); } La classe SoundChannel n’envoie pas d’événements progress pendant la lecture. Pour fournir des informations relatives à la progression de la lecture, votre application peut définir son propre mécanisme de synchronisation et suivre la position de la tête de lecture du son. Pour calculer le pourcentage d’un son lu, vous pouvez diviser la valeur de la propriété SoundChannel.position par la longueur des données audio en cours de lecture : var playbackPercent:uint = 100 * (channel.position / snd.length); Néanmoins, ce code signale uniquement des pourcentages de lecture précis si les données audio ont été totalement chargées avant le début de la lecture. La propriété Sound.length indique la taille des données audio actuellement chargées, et non pas la taille éventuelle du fichier audio entier. Pour suivre la progression de la lecture d’un son diffusé en continu qui est toujours en cours de chargement, votre application doit estimer la taille éventuelle du fichier audio entier et utiliser cette valeur dans ses calculs. Vous pouvez estimer la longueur éventuelle des données audio à l’aide des propriétés bytesLoaded et bytesTotal de l’objet Sound, comme suit : var estimatedLength:int = Math.ceil(snd.length / (snd.bytesLoaded / snd.bytesTotal)); var playbackPercent:uint = 100 * (channel.position / estimatedLength); Le code suivant charge un fichier audio plus volumineux et utilise l’événement Event.ENTER_FRAME comme mécanisme de synchronisation pour afficher la progression de la lecture. Il fournit régulièrement des informations sur le pourcentage de lecture, qui est calculé de la façon suivante : la valeur de position actuelle divisée par la longueur totale des données audio : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 468 Utilisation du son Dernière mise à jour le 27/4/2013 import flash.events.Event; import flash.media.Sound; import flash.net.URLRequest; var snd:Sound = new Sound(); var req:URLRequest = new URLRequest("http://av.adobe.com/podcast/csbu_dev_podcast_epi_2.mp3"); snd.load(req); var channel:SoundChannel; channel = snd.play(); addEventListener(Event.ENTER_FRAME, onEnterFrame); channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); function onEnterFrame(event:Event):void { var estimatedLength:int = Math.ceil(snd.length / (snd.bytesLoaded / snd.bytesTotal)); var playbackPercent:uint = Math.round(100 * (channel.position / estimatedLength)); trace("Sound playback is " + playbackPercent + "% complete."); } function onPlaybackComplete(event:Event) { trace("The sound has finished playing."); removeEventListener(Event.ENTER_FRAME, onEnterFrame); } Une fois que le chargement des données audio commence, ce code appelle la méthode snd.play() et stocke l’objet SoundChannel résultant dans la variable channel. Il ajoute ensuite un écouteur d’événement à l’application principale pour l’événement Event.ENTER_FRAME et un autre écouteur d’événement à l’objet SoundChannel pour l’événement Event.SOUND_COMPLETE qui a lieu à la fin de la lecture. Chaque fois que l’application atteint une nouvelle image dans son animation, la méthode onEnterFrame() est appelée. La méthode onEnterFrame() estime la longueur totale du fichier audio en fonction de la quantité de données déjà chargées puis calcule et affiche le pourcentage de lecture actuel. Une fois que tout le son a été lu, la méthode onPlaybackComplete() s’exécute, supprimant l’écouteur d’événement pour l’événement Event.ENTER_FRAME de façon à ce qu’il ne tente pas d’afficher les mises à jour de progression après la lecture. L’événement Event.ENTER_FRAME peut être envoyé plusieurs fois par seconde. Dans certains cas, vous pouvez ne pas afficher la progression de la lecture aussi fréquemment. Votre application peut alors définir son propre mécanisme de synchronisation à l’aide de la classe flash.util.Timer ; voir « Utilisation des dates et des heures » à la page 1. Arrêt de sons diffusés en continu Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Il y a quelque chose d’étrange dans le processus de lecture des sons diffusés en continu, c’est-à-dire ceux qui sont lus pendant leur chargement. Lorsque votre application appelle la méthode SoundChannel.stop() sur une occurrence de SoundChannel qui lit un son diffusé en continu, la lecture du son s’arrête pendant une image puis elle relance au début du son sur l’image suivante. Ceci a lieu car le chargement du son est toujours en cours. Pour arrêter à la fois le chargement et la lecture d’un son diffusé en continu, appelez la méthode Sound.close(). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 469 Utilisation du son Dernière mise à jour le 27/4/2013 Sécurité lors du chargement et de la lecture des sons Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’accès aux données audio par votre application peut être limité selon la fonction de sécurité de Flash Player ou AIR. Chaque son est soumis aux restrictions de deux sandbox de sécurité différents, le sandbox pour le contexte lui-même (le sandbox de contexte), et le sandbox pour l’application ou l’objet qui charge et lit le son (le sandbox propriétaire). Pour le contenu de l’application AIR dans le sandbox de sécurité de l’application, tous les sons, y compris ceux chargés à partir d’autres domaines, sont accessibles au contenu dans le sandbox de sécurité de l’application. Toutefois, le contenu dans d’autres sandbox de sécurité observe les même règles que le contenu qui s’exécute dans Flash Player. Pour plus d’informations sur le modèle de sécurité de Flash Player en général et la définition des sandbox, voir « Sécurité » à la page 1085. Le sandbox de contexte contrôle si des données audio détaillées peuvent être extraites du son à l’aide de la propriété id3 ou de la méthode SoundMixer.computeSpectrum(). Il ne limite pas le chargement ou la lecture du fichier audio lui-même. Le domaine d’origine du fichier audio définit les limites de sécurité du sandbox de contexte. Généralement, si un fichier audio se trouve dans le même domaine ou dossier que le fichier SWF de l’application ou de l’objet qui le charge, ce dernier dispose d’un accès total à ce fichier audio. Si le son provient d’un domaine différent par rapport à l’application, il peut être intégré dans le sandbox de contexte à l’aide d’un fichier de régulation. Votre application peut transmettre un objet SoundLoaderContext avec une propriété checkPolicyFile comme paramètre à la méthode Sound.load(). Lorsque vous définissez la propriété checkPolicyFile sur true, vous indiquez à Flash Player ou à AIR de rechercher un fichier de régulation sur le serveur à partir duquel le son est chargé. Si un fichier de régulation existe et qu’il autorise l’accès au domaine du fichier SWF de chargement, ce dernier peut charger le fichier audio, accéder à la propriété id3 de l’objet Sound et appeler la méthode SoundMixer.computeSpectrum() pour les sons chargés. Le sandbox propriétaire contrôle la lecture locale des sons. L’application ou l’objet qui lance la lecture d’un son définit le sandbox propriétaire. La méthode SoundMixer.stopAll() interrompt les sons dans tous les objets SoundChannel en cours de lecture, tant qu’ils répondent aux critères suivants : • Les sons ont été démarrés par des objets se trouvant dans le même sandbox propriétaire. • Les sons sont issus d’une source possédant un fichier de régulation qui autorise l’accès au domaine de l’application ou de l’objet qui appelle la méthode SoundMixer.stopAll(). Cependant, dans une application AIR, le contenu du sandbox de sécurité de l’application (contenu installé avec l’application AIR) n’est pas restreint par ces limites de sécurité. Pour savoir si la méthode SoundMixer.stopAll() interrompra tous les sons lus, votre application peut appeler la méthode SoundMixer.areSoundsInaccessible(). Si cette méthode renvoie une valeur true, certains des sons lus ne sont pas sous le contrôle du sandbox propriétaire actuel et ne seront pas arrêtés par la méthode SoundMixer.stopAll(). La méthode SoundMixer.stopAll() empêche également la tête de lecture de continuer pour tous les sons chargés à partir de fichiers externes. Néanmoins, les sons qui sont incorporés dans des fichiers FLA et associés à des images dans le scénario à l’aide de l’outil de programmation Flash risquent d’être relus si l’animation s’est déplacée sur une nouvelle image. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 470 Utilisation du son Dernière mise à jour le 27/4/2013 Contrôle du volume du son et de la balance Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un objet SoundChannel individuel contrôle les canaux stéréo gauche et droit pour un son. Si un son mp3 est un son mono, les canaux stéréo gauche et droit de l’objet SoundChannel contiennent des courbes audio identiques. Vous pouvez connaître l’amplitude de chaque canal stéréo du son lu à l’aide des propriétés leftPeak et rightPeak de l’objet SoundChannel. Ces propriétés indiquent l’amplitude de crête de la courbe audio du son. Elles ne représentent pas le volume de lecture réel. Le volume de lecture réel est une fonction de l’amplitude de l’onde acoustique et des valeurs de volume définies dans l’objet SoundChannel et la classe SoundMixer. Vous pouvez utiliser la propriété pan d’un objet SoundChannel pour indiquer un niveau de volume différent pour chacun des canaux gauche et droit pendant la lecture. La propriété pan peut avoir une valeur comprise entre -1 et 1, où -1 signifie que le canal gauche lit à volume maximal alors que le canal droit est muet, et 1 signifie que le canal droit lit à volume maximal alors que le canal gauche est muet. Les valeurs numériques comprises entre -1 et 1 définissent des valeurs proportionnelles pour les valeurs des canaux gauche et droit, et une valeur de 0 signifie que les deux canaux lisent à un niveau de volume moyen, équilibré. L’exemple de code suivant crée un objet SoundTransform avec une valeur de volume de 0,6 et une valeur de balance horizontale de -1 (volume de canal gauche maximal et aucun volume de canal droit). Il transmet l’objet SoundTransform comme paramètre à la méthode play(), qui l’applique au nouvel objet SoundTransform créé pour contrôler la lecture. var snd:Sound = new Sound(new URLRequest("bigSound.mp3")); var trans:SoundTransform = new SoundTransform(0.6, -1); var channel:SoundChannel = snd.play(0, 1, trans); Vous pouvez modifier le volume et la balance pendant la lecture d’un son en définissant les propriétés pan ou volume d’un objet SoundTransform puis en appliquant cet objet comme propriété soundTransform d’un objet SoundChannel. Vous pouvez également définir des valeurs de balance et de volume global pour tous les sons à la fois à l’aide de la propriété soundTransform de la classe SoundMixer, comme l’indique l’exemple suivant : SoundMixer.soundTransform = new SoundTransform(1, -1); Vous pouvez également utiliser un objet SoundTransform pour définir des valeurs de balance et de volume global pour un objet Microphone (voir « Capture de l’entrée de son » à la page 476), et pour des objets Sprite et SimpleButton. L’exemple suivant modifie la balance horizontale du son du canal gauche au canal droit et de nouveau lors de la lecture du son. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 471 Utilisation du son Dernière mise à jour le 27/4/2013 import flash.events.Event; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundMixer; import flash.net.URLRequest; var snd:Sound = new Sound(); var req:URLRequest = new URLRequest("bigSound.mp3"); snd.load(req); var panCounter:Number = 0; var trans:SoundTransform; trans = new SoundTransform(1, 0); var channel:SoundChannel = snd.play(0, 1, trans); channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); addEventListener(Event.ENTER_FRAME, onEnterFrame); function onEnterFrame(event:Event):void { trans.pan = Math.sin(panCounter); channel.soundTransform = trans; // or SoundMixer.soundTransform = trans; panCounter += 0.05; } function onPlaybackComplete(event:Event):void { removeEventListener(Event.ENTER_FRAME, onEnterFrame); } Ce code commence par charger un fichier audio puis crée un objet SoundTransform avec un volume défini sur 1 (volume maximal) et une balance définie sur 0 (balance équilibrée entre gauche et droite). Il appelle ensuite la méthode snd.play() en transmettant l’objet SoundTransform comme paramètre. Lors de la lecture du son, la méthode onEnterFrame() s’exécute de façon répétée. La méthode onEnterFrame() utilise la fonction Math.sin() pour générer une valeur comprise entre -1 et 1 (plage qui correspond aux valeurs acceptables de la propriété SoundTransform.pan). La propriété pan de l’objet SoundTransform est définie sur la nouvelle valeur, puis la propriété soundTransform du canal est définie pour utiliser l’objet SoundTransform modifié. Pour exécuter cet exemple, remplacez le nom de fichier bigSound.mp3 par le nom d’un fichier mp3 local. Exécutez ensuite l’exemple. Le volume du canal gauche devrait augmenter quand celui du canal droit diminue, et vice-versa. Dans cet exemple, le même effet peut être obtenu en définissant la propriété soundTransform de la classe SoundMixer. Néanmoins, la balance de tous les sons en cours de lecture est affectée (pas seulement le son lu par cet objet SoundChannel). Utilisation des métadonnées audio Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Les fichiers audio qui utilisent le format mp3 peuvent contenir des données supplémentaires relatives au son sous la forme de balises ID3. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 472 Utilisation du son Dernière mise à jour le 27/4/2013 Tous les fichiers mp3 ne contiennent pas de métadonnées ID3. Lorsqu’un objet Sound charge un fichier audio mp3, il envoie un événement Event.ID3 si le fichier audio contient des métadonnées ID3. Pour éviter des erreurs d’exécution, votre application doit attendre de recevoir l’événement Event.ID3 avant d’accéder à la propriété Sound.id3 pour un son chargé. Le code suivant indique comment savoir si les métadonnées ID3 pour un fichier audio ont été chargées : import flash.events.Event; import flash.media.ID3Info; import flash.media.Sound; var s:Sound = new Sound(); s.addEventListener(Event.ID3, onID3InfoReceived); s.load("mySound.mp3"); function onID3InfoReceived(event:Event) { var id3:ID3Info = event.target.id3; trace("Received ID3 Info:"); for (var propName:String in id3) { trace(propName + " = " + id3[propName]); } } Ce code commence par créer un objet Sound et par lui demander d’écouter l’événement Event.ID3. Lorsque les métadonnées ID3 du fichier audio sont chargées, la méthode onID3InfoReceived() est appelée. La cible de l’objet Event qui est transmise à la méthode onID3InfoReceived() est l’objet Sound d’origine. Par conséquent, la méthode obtient ensuite la propriété id3 de l’objet Sound puis effectue une itération sur toutes ses propriétés appelées pour suivre leurs valeurs. Accès aux données audio brutes Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode SoundMixer.computeSpectrum() permet à une application de lire les données audio brutes pour la courbe audio en cours de lecture. Si plusieurs objets SoundChannel sont en cours de lecture, la méthode SoundMixer.computeSpectrum() indique les données audio combinées de chaque objet SoundChannel mixé. Les données audio sont renvoyées sous la forme d’un objet ByteArray contenant 512 octets de données (chacun d’eux contenant une valeur en virgule flottante comprise entre -1 et 1). Ces valeurs représentent l’amplitude des points dans la courbe audio en cours de lecture. Les valeurs sont fournies en deux groupes de 256 : le premier groupe pour le canal stéréo gauche et le second pour le canal stéréo droit. La méthode SoundMixer.computeSpectrum() renvoie des données de spectre de fréquences plutôt que des données de courbe audio si le paramètre FFTMode est défini sur true. Le spectre de fréquences indique l’amplitude par fréquence du son, de la plus basse à la plus élevée. Une FFT (Fast Fourier Transform - transformation de Fourier rapide) est utilisée pour convertir les données de courbe audio en données de spectre de fréquences. Les valeurs de spectre de fréquences résultantes sont comprises entre 0 et 1,414 environ (la racine carrée de 2). GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 473 Utilisation du son Dernière mise à jour le 27/4/2013 Le diagramme suivant compare les données renvoyées de la méthode computeSpectrum() lorsque le paramètre FFTMode est défini sur true et lorsqu’il est défini sur false. Le son dont les données ont été utilisées pour ce diagramme contient un son de basse de grande intensité dans le canal gauche et un son de tambour dans le canal droit. Valeurs renvoyées par la méthode SoundMixer.computeSpectrum() A. fftMode=true B. fftMode=false La méthode computeSpectrum() peut également renvoyer des données qui ont été rééchantillonnées à un débit inférieur. Généralement, ceci entraîne des données de fréquence ou des données de courbe audio plus lisses, au profit des détails. Le paramètre stretchFactor contrôle la fréquence à laquelle les données de la méthode computeSpectrum() sont échantillonnées. Lorsque le paramètre stretchFactor est défini sur 0 (valeur par défaut), les données audio sont échantillonnées à une fréquence de 44,1 KHz. La fréquence est diminuée de moitié à chaque valeur successive du paramètre stretchFactor. Par conséquent, une valeur de 1 indique une fréquence de 22,05 KHz, une valeur de 2 une fréquence de 11,025 KHz, et ainsi de suite. La méthode computeSpectrum() continue à renvoyer 256 octets par canal stéréo lorsqu’une valeur stretchFactor supérieure est utilisée. La méthode SoundMixer.computeSpectrum() comporte des limites : • Etant donné que les données audio issues d’un microphone ou de flux RTMP ne passent pas par l’objet SoundMixer global, la méthode SoundMixer.computeSpectrum() ne renvoie pas de données de ces sources. • Si un ou plusieurs sons lus proviennent de sources externes au sandbox de contexte actuel, les restrictions de sécurité provoquent le renvoi d’une erreur par la méthode SoundMixer.computeSpectrum(). Pour plus d’informations sur les limites de sécurité de la méthode SoundMixer.computeSpectrum(), voir « Sécurité lors du chargement et de la lecture des sons » à la page 469 et « Accès aux médias chargés comme s’il s’agissait de données » à la page 1111. Cependant, dans une application AIR, le contenu du sandbox de sécurité de l’application (contenu installé avec l’application AIR) n’est pas restreint par ces limites de sécurité. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 474 Utilisation du son Dernière mise à jour le 27/4/2013 Création d’un visualiseur audio simple Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’exemple suivant utilise la méthode SoundMixer.computeSpectrum() pour afficher un diagramme de la courbe audio animée avec chaque image : import flash.display.Graphics; import flash.events.Event; import flash.media.Sound; import flash.media.SoundChannel; import flash.media.SoundMixer; import flash.net.URLRequest; const PLOT_HEIGHT:int = 200; const CHANNEL_LENGTH:int = 256; var snd:Sound = new Sound(); var req:URLRequest = new URLRequest("bigSound.mp3"); snd.load(req); var channel:SoundChannel; channel = snd.play(); addEventListener(Event.ENTER_FRAME, onEnterFrame); snd.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete); var bytes:ByteArray = new ByteArray(); function onEnterFrame(event:Event):void { SoundMixer.computeSpectrum(bytes, false, 0); var g:Graphics = this.graphics; g.clear(); g.lineStyle(0, 0x6600CC); g.beginFill(0x6600CC); g.moveTo(0, PLOT_HEIGHT); var n:Number = 0; // left channel for (var i:int = 0; i < CHANNEL_LENGTH; i++) { n = (bytes.readFloat() * PLOT_HEIGHT); g.lineTo(i * 2, PLOT_HEIGHT - n); } g.lineTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 475 Utilisation du son Dernière mise à jour le 27/4/2013 g.endFill(); // right channel g.lineStyle(0, 0xCC0066); g.beginFill(0xCC0066, 0.5); g.moveTo(CHANNEL_LENGTH * 2, PLOT_HEIGHT); for (i = CHANNEL_LENGTH; i > 0; i--) { n = (bytes.readFloat() * PLOT_HEIGHT); g.lineTo(i * 2, PLOT_HEIGHT - n); } g.lineTo(0, PLOT_HEIGHT); g.endFill(); } function onPlaybackComplete(event:Event) { removeEventListener(Event.ENTER_FRAME, onEnterFrame); } Cet exemple commence par charger et lire un fichier audio puis écoute l’événement Event.ENTER_FRAME qui déclenchera la méthode onEnterFrame() lors de la lecture du son. La méthode onEnterFrame() commence par appeler la méthode SoundMixer.computeSpectrum(), qui stocke les données d’onde acoustique dans l’objet ByteArray bytes. La courbe audio est tracée à l’aide de l’API de dessin vectoriel. Une boucle for passe dans les 256 premières valeurs de données, représentant le canal stéréo gauche, et trace une ligne entre chaque point au moyen de la méthode Graphics.lineTo(). Une second boucle for passe dans les 256 valeurs suivantes, en les traçant cette fois dans l’ordre inverse, de droite à gauche. Les tracés de courbe audio résultants peuvent produire un effet miroir-image intéressant, comme illustré sur l’image suivante. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 476 Utilisation du son Dernière mise à jour le 27/4/2013 Capture de l’entrée de son Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Microphone permet à votre application de se connecter à un microphone ou à un autre périphérique d’entrée de son sur le système de l’utilisateur et de diffuser l’audio sur les haut-parleurs de ce système ou d’envoyer les données audio à un serveur distant (Flash Media Server, par exemple). Vous pouvez accéder aux données audio brutes à partir du microphone, puis les enregistrer ou les traiter. Vous pouvez également envoyer directement l’audio aux hautparleurs du système ou envoyer des données audio compressées à un serveur distant. Pour envoyer des données à un serveur distant, vous pouvez utiliser le codec Speex ou Nellymoser (le codec Speex est pris en charge depuis Flash Player version 10 et Adobe AIR version 1.5). Voir aussi Michael Chaize : AIR, Android, and the Microphone (disponible en anglais uniquement) Christophe Coenraets : Voice Notes for Android (disponible en anglais uniquement) Accès à un microphone Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La classe Microphone ne possède pas de méthode constructeur. A la place, vous utilisez la méthode statique Microphone.getMicrophone() pour obtenir une nouvelle occurrence de Microphone, comme indiqué ci-dessous : var mic:Microphone = Microphone.getMicrophone(); Lorsque vous appelez la méthode Microphone.getMicrophone() sans paramètre, le premier périphérique d’entrée de son détecté sur le système de l’utilisateur est renvoyé. Un système peut avoir plusieurs périphériques d’entrée de son qui lui sont associés. Votre application peut utiliser la propriété Microphone.names pour obtenir un tableau des noms de tous les périphériques d’entrée de son disponibles. Elle peut ensuite appeler la méthode Microphone.getMicrophone() avec un paramètre index qui correspond à la valeur d’index du nom d’un périphérique dans le tableau. Il se peut qu’un système n’ait aucun microphone ni périphérique d’entrée de son qui lui soit associé. Vous pouvez utiliser la propriété Microphone.names ou la méthode Microphone.getMicrophone() pour vérifier si l’utilisateur a installé un périphérique d’entrée de son. Si ce n’est pas le cas, la longueur du tableau names est zéro, et la méthode getMicrophone() renvoie une valeur null. Lorsque votre application appelle la méthode Microphone.getMicrophone(), Flash Player affiche la boîte de dialogue des paramètres de Flash Player, qui invite l’utilisateur à autoriser ou à refuser l’accès Flash Player à la caméra et au microphone sur le système. Une fois que l’utilisateur a fait son choix dans cette boîte de dialogue, un StatusEvent est envoyé. La propriété code de cette occurrence de StatusEvent indique si l’accès au microphone a été autorisé ou refusé, comme indiqué dans cet exemple : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 477 Utilisation du son Dernière mise à jour le 27/4/2013 import flash.media.Microphone; var mic:Microphone = Microphone.getMicrophone(); mic.addEventListener(StatusEvent.STATUS, this.onMicStatus); function onMicStatus(event:StatusEvent):void { if (event.code == "Microphone.Unmuted") { trace("Microphone access was allowed."); } else if (event.code == "Microphone.Muted") { trace("Microphone access was denied."); } } La propriété StatusEvent.code contiendra Microphone.Unmuted si l’accès a été autorisé, ou Microphone.Muted s’il a été refusé. la propriété Microphone.muted est définie sur true ou sur false lorsque l’utilisateur autorise ou refuse l’accès au microphone, respectivement. Néanmoins, la propriété muted n’est pas définie sur l’occurrence de Microphone tant que StatusEvent n’a pas été distribué. Par conséquent, l’application doit également attendre la distribution de l’événement StatusEvent.STATUS avant de vérifier la propriété Microphone.muted. Pour que Flash Player affiche la boîte de dialogue de paramétrage, la taille de la fenêtre de l’application doit être suffisamment élevée (215 sur 138 pixels au moins). Dans le cas contraire, l’accès est automatiquement refusé. Un contenu qui s’exécute dans le sandbox de l’application AIR ne nécessite pas l’autorisation de l’utilisateur pour accéder au microphone. Par conséquent, les événements d’état associés à l’activation et à la désactivation du microphone ne sont jamais distribués. Etant donné qu’un contenu qui s’exécute dans AIR en dehors du sandbox de l’application ne nécessite pas l’autorisation de l’utilisateur, il est possible de distribuer ces événements d’état. Acheminement de l’audio du microphone vers des haut-parleurs locaux Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’entrée audio issue d’un microphone peut être acheminée vers les haut-parleurs du système local en appelant la méthode Microphone.setLoopback() avec une valeur de paramètre true. Lorsque le son provenant d’un microphone local est acheminé vers des haut-parleurs locaux, vous risquez de créez une boucle de réaction acoustique pouvant entraîner des grincements d’une grande intensité et endommager ainsi votre matériel. Vous pouvez appeler la méthode Microphone.setUseEchoSuppression() avec une valeur de paramètre true pour réduire (sans éliminer complètement) le risque de réaction acoustique. Adobe vous conseille de toujours appeler Microphone.setUseEchoSuppression(true) avant d’appeler Microphone.setLoopback(true), à moins que vous soyez sûr que l’utilisateur lit le son à l’aide d’un casque ou d’un dispositif autre que les haut-parleurs. Le code suivant indique comment acheminer l’audio d’un microphone local vers les haut-parleurs du système local : var mic:Microphone = Microphone.getMicrophone(); mic.setUseEchoSuppression(true); mic.setLoopBack(true); GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 478 Utilisation du son Dernière mise à jour le 27/4/2013 Modification de l’audio du microphone Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Votre application peut modifier les données audio provenant d’un microphone de deux façons différentes. Premièrement, elle peut modifier le gain du son entré, qui multiplie les valeurs d’entrée par une quantité spécifiée pour créer un son plus ou moins intense. La propriété Microphone.gain accepte des valeurs numériques comprises entre 0 et 100 inclus. Une valeur de 50 a un rôle de multiplicateur de un et spécifie un volume normal. Une valeur de zéro agit comme un multiplicateur de zéro et interrompt l’audio d’entrée. Les valeurs supérieures à 50 indiquent un volume supérieur à la normale. Votre application peut également modifier la fréquence d’échantillonnage de l’audio d’entrée. Des fréquences d’échantillonnage supérieures augmentent la qualité du son, mais créent également des flux de données plus denses qui utilisent davantage de ressources pour la transmission et le stockage. La propriété Microphone.rate représente la fréquence d’échantillonnage audio mesurée en kilohertz (kHz). La fréquence d’échantillonnage par défaut est de 8 kHz. Vous pouvez définir la propriété Microphone.rate sur une valeur supérieure à 8 kHz si votre microphone prend en charge la fréquence supérieure. Par exemple, si vous définissez la propriété Microphone.rate sur la valeur 11, la fréquence d’échantillonnage est réglée sur 11 kHz ; si vous la définissez sur 22, la fréquence d’échantillonnage est réglée sur 22 kHz, et ainsi de suite. Les fréquences d’échantillonnage disponibles varient en fonction du codec sélectionné. Lorsque vous utilisez le codec Nellymoser, vous pouvez spécifier les fréquences d’échantillonnage 5, 8, 11, 16, 22 et 44 kHz. Lorsque vous utilisez le codec Speex (disponible à partir de Flash Player 10 et Adobe AIR 1.5), vous ne pouvez utiliser que 16 kHz. Détection de l’activité du microphone Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Pour économiser les ressources de traitement et de bande passante, Flash Player tente de détecter lorsque aucun son n’est transmis par un microphone. Lorsque le niveau d’activité du microphone se situe sous le seuil de niveau de silence pendant longtemps, Flash Player arrête la transmission de l’entrée audio et envoie un simple événement ActivityEvent à la place. Si vous utilisez le codec Speex (disponible dans Flash Player 10 et versions ultérieures, ainsi que dans Adobe AIR 1.5 et versions ultérieures), définissez le niveau de silence sur 0 afin de vous assurer que l’application transmet les données audio en continu. La fonction de détection d’activité vocale de Speex réduit automatiquement la bande passante. Remarque : un objet Microphone ne distribue des événements Activity que si l’application contrôle actuellement le microphone. Par conséquent, si vous n’appelez pas setLoopBack( true ), que vous n’associez pas d’écouteur aux événements de données d’exemple ou que vous ne connectez pas le microphone à un objet NetStream, aucun événement d’activité n’est distribué. Trois propriétés de la classe Microphone surveillent et contrôlent la détection d’activité : • La propriété activityLevel en lecture seule indique la quantité de son détectée par le microphone, sur une échelle de 0 à 100. • La propriété silenceLevel spécifie la quantité de son nécessaire pour activer le microphone et envoie un événement ActivityEvent.ACTIVITY. La propriété silenceLevel utilise également une échelle de 0 à 100, et la valeur par défaut est 10. • La propriété silenceTimeout décrit le nombre de millisecondes pendant lequel le niveau d’activité doit rester sous le niveau de silence, jusqu’à ce qu’un événement ActivityEvent.ACTIVITY soit envoyé pour indiquer que le microphone est maintenant désactivé. La valeur silenceTimeout par défaut est 2000. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 479 Utilisation du son Dernière mise à jour le 27/4/2013 Les propriétés Microphone.silenceLevel et Microphone.silenceTimeout sont en lecture seule, mais vous pouvez modifier leurs valeurs à l’aide de la méthode Microphone.setSilenceLevel(). Dans certains cas, l’activation du microphone alors qu’une nouvelle activité est détectée peut entraîner un court délai. Vous pouvez laisser le microphone actif en permanence pour supprimer ces délais d’activation. Votre application peut appeler la méthode Microphone.setSilenceLevel() avec le paramètre silenceLevel défini sur zéro pour indiquer à Flash Player de laisser le microphone actif et de continuer à rassembler des données audio, même lorsque aucun son n’est détecté. Inversement, lorsque vous définissez le paramètre silenceLevel sur 100, le microphone n’est pas activé. L’exemple suivant affiche les informations relatives au microphone et aux événements activity et status envoyés par un objet Microphone : import flash.events.ActivityEvent; import flash.events.StatusEvent; import flash.media.Microphone; var deviceArray:Array = Microphone.names; trace("Available sound input devices:"); for (var i:int = 0; i < deviceArray.length; i++) { trace(" " + deviceArray[i]); } var mic:Microphone = Microphone.getMicrophone(); mic.gain = 60; mic.rate = 11; mic.setUseEchoSuppression(true); mic.setLoopBack(true); mic.setSilenceLevel(5, 1000); mic.addEventListener(ActivityEvent.ACTIVITY, this.onMicActivity); mic.addEventListener(StatusEvent.STATUS, this.onMicStatus); var micDetails:String = "Sound input device name: " + mic.name + '\n'; micDetails += "Gain: " + mic.gain + '\n'; micDetails += "Rate: " + mic.rate + " kHz" + '\n'; micDetails += "Muted: " + mic.muted + '\n'; micDetails += "Silence level: " + mic.silenceLevel + '\n'; micDetails += "Silence timeout: " + mic.silenceTimeout + '\n'; micDetails += "Echo suppression: " + mic.useEchoSuppression + '\n'; trace(micDetails); function onMicActivity(event:ActivityEvent):void { trace("activating=" + event.activating + ", activityLevel=" + mic.activityLevel); } function onMicStatus(event:StatusEvent):void { trace("status: level=" + event.level + ", code=" + event.code); } Lorsque vous exécutez l’exemple ci-dessus, parlez ou faites du bruit dans votre microphone système et observez les instructions trace qui apparaissent dans une console ou une fenêtre de débogage. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 480 Utilisation du son Dernière mise à jour le 27/4/2013 Envoi d’audio vers et depuis une passerelle multimédia Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures D’autres fonctionnalités audio sont disponibles lorsque vous utilisez ActionScript avec une passerelle multimédia de diffusion en continu telle que Flash Media Server. Votre application peut notamment associer un objet Microphone à un objet NetStream et transmettre directement des données du microphone de l’utilisateur au serveur. Les données audio peuvent également être diffusées en continu du serveur vers une application et lues dans le cadre d’un MovieClip ou au moyen d’un objet Video. Le codec Speex est pris en charge depuis Flash Player version 10 et Adobe AIR version 1.5. Pour définir le codec utilisé pour les données audio compressées envoyées au serveur multimédia, définissez la propriété codec de l’objet Microphone. Cette propriété gère deux valeurs, qui sont énumérées dans la classe SoundCodec. La définition de la propriété codec sur SoundCodec.SPEEX sélectionne le codec Speex pour la compression audio. La définition de la propriété codec sur SoundCodec.NELLYMOSER (valeur par défaut) sélectionne le codec Nellymoser pour la compression audio. Pour plus d’informations, voir la documentation de Flash Media Server disponible en ligne à l’adresse suivante : www.adobe.com/go/learn_fms_docs_fr. Capture des données audio issues d’un microphone Flash Player 10.1 et les versions ultérieures, Adobe AIR 2 et les versions ultérieures Dans Flash Player 10.1 et AIR 2 ou ultérieur, vous pouvez capturer les données issues d’un microphone sous forme de tableau d’octets composé de valeurs à virgule flottante. Chaque valeur représente un échantillon de données audio monophoniques. Pour obtenir les données issues d’un microphone, définissez un écouteur associé à l’événement sampleData de l’objet Microphone. L’objet Microphone distribue les événements sampleData à fréquence régulière au fur et à mesure que le tampon du microphone se remplit d’échantillons audio. La propriété data de l’objet SampleDataEvent correspond à un tableau d’octets d’échantillons audio. Les échantillons sont représentés par des valeurs à virgule flottante, chacune d’elles correspondant à un échantillon audio monophonique. Le code suivant capture les données audio issues d’un microphone dans un objet ByteArray appelé soundBytes : var mic:Microphone = Microphone.getMicrophone(); mic.setSilenceLevel(0, DELAY_LENGTH); mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); function micSampleDataHandler(event:SampleDataEvent):void { while(event.data.bytesAvailable) { var sample:Number = event.data.readFloat(); soundBytes.writeFloat(sample); } } Vous pouvez réutiliser les octets d’échantillon sous forme d’audio à lire d’un objet Sound. Pour ce faire, définissez la propriété rate de l’objet Microphone sur 44, à savoir la fréquence d’échantillonnage utilisée par les objets Sound. (Vous pouvez également convertir des échantillons issus de microphone capturés à une fréquence inférieure sur le taux 44 kHz requis par l’objet Sound.) N’oubliez pas non plus que l’objet Microphone capture des échantillons monophoniques, alors que l’objet Sound utilise un son stéréo. Ecrivez donc deux fois dans l’objet Sound chaque octet capturé par l’objet Microphone. L’exemple suivant capture 4 secondes de données issues d’un microphone et les lit par le biais d’un objet Sound : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 481 Utilisation du son Dernière mise à jour le 27/4/2013 const DELAY_LENGTH:int = 4000; var mic:Microphone = Microphone.getMicrophone(); mic.setSilenceLevel(0, DELAY_LENGTH); mic.gain = 100; mic.rate = 44; mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); var timer:Timer = new Timer(DELAY_LENGTH); timer.addEventListener(TimerEvent.TIMER, timerHandler); timer.start(); function micSampleDataHandler(event:SampleDataEvent):void { while(event.data.bytesAvailable) { var sample:Number = event.data.readFloat(); soundBytes.writeFloat(sample); } } var sound:Sound = new Sound(); var channel:SoundChannel; function timerHandler(event:TimerEvent):void { mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler); timer.stop(); soundBytes.position = 0; sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler); channel.addEventListener( Event.SOUND_COMPLETE, playbackComplete ); channel = sound.play(); } function playbackSampleHandler(event:SampleDataEvent):void { for (var i:int = 0; i < 8192 && soundBytes.bytesAvailable > 0; i++) { trace(sample); var sample:Number = soundBytes.readFloat(); event.data.writeFloat(sample); event.data.writeFloat(sample); } } function playbackComplete( event:Event ):void { trace( "Playback finished."); } Pour plus d’informations sur la lecture de données d’échantillons audio, voir « Utilisation de données audio générées de façon dynamique » à la page 463. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 482 Utilisation du son Dernière mise à jour le 27/4/2013 Exemple d’objet Sound : Podcast Player Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Un podcast est un fichier audio distribué sur Internet, sur demande ou sur abonnement. Les podcasts sont généralement publiés dans un annuaire. Etant donné que les épisodes de podcast peuvent durer d’une minute à plusieurs heures, ils sont généralement diffusés en continu pendant la lecture. Les épisodes de podcast, également appelés éléments, sont généralement fournis au format de fichier mp3. Les podcasts vidéo sont également courants, mais cet exemple d’application lit uniquement des podcasts audio utilisant des fichiers mp3. Cet exemple n’est pas une application agrégatrice de podcasts comprenant toutes les fonctionnalités. Par exemple, elle ne gère pas les abonnements à des podcasts spécifiques et ne mémorise pas les podcasts qu’un utilisateur a écoutés lors de l’exécution suivante de l’application. Il peut servir de point de départ pour un agrégateur de podcasts comprenant toutes les fonctionnalités. L’exemple Podcast Player illustre les techniques de programmation ActionScript suivantes : • Lecture d’un fil de syndication et analyse de son contenu XML • Création d’une classe SoundFacade pour simplifier le chargement et la lecture des fichiers audio • Affichage de la progression de la lecture du son • Interruption et reprise de la lecture du son Pour obtenir les fichiers d’application de cet exemple, voir www.adobe.com/go/learn_programmingAS3samples_flash_fr. Les fichiers d’application Podcast Player se trouvent dans le dossier Samples/PodcastPlayer. L’application se compose des fichiers suivants : Fichier Description PodcastPlayer.mxml ou PodcastPlayer.fla Interface utilisateur de l’application pour Flex (MXML) ou Flash (FLA). comp/example/progra mmingas3/podcastplay er/PodcastPlayer.as Classe Document contenant la logique de l’interface utilisateur pour le lecteur de podcast (Flash uniquement). SoundPlayer.mxml Un composant MXML qui affiche les commandes de lecture et les barres de progression, et contrôle la lecture du son, pour Flex uniquement. main.css Styles associés à l’interface utilisateur de l’application (Flex uniquement) image/ Icônes permettant le formatage des boutons (Flex uniquement). comp/example/progra mmingas3/podcastplay er/SoundPlayer.as Classe pour le symbole du clip SoundPlayer contenant la logique de l’interface utilisateur du lecteur de sons (Flash uniquement). comp/example/progra mmingas3/podcastplay er/PlayButtonRenderer. as Composant de rendu de cellule personnalisé permettant d’afficher un bouton de lecture dans une cellule de la grille de données (Flash uniquement). com/example/program mingas3/podcastplayer /RSSBase.as Une classe de base qui fournit les méthodes et les propriétés courantes pour la classe RSSChannel et la classe RSSItem. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 483 Utilisation du son Dernière mise à jour le 27/4/2013 Lecture de données RSS pour une chaîne de podcast Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’application Podcast Player commence par lire les informations concernant des chaînes de podcasts et leurs épisodes : 1. L’application commence par lire un fichier de configuration XML qui contient une liste des chaînes de podcast et affiche la liste des chaînes pour l’utilisateur. 2. Lorsque l’utilisateur sélectionne l’une des chaînes de podcast, il lit le flux RSS pour la chaîne et affiche une liste des épisodes de chaîne. Cet exemple utilise la classe d’utilitaire URLLoader pour récupérer des données de texte depuis un emplacement distant ou un fichier local. L’application Podcast Player crée d’abord un objet URLLoader pour obtenir une liste des fils de syndication au format XML du fichier playerconfig.xml. Ensuite, lorsque l’utilisateur sélectionne un fil de syndication spécifique dans la liste, un nouvel objet URLLoader est créé pour lire les données RSS de l’URL de ce fil. Simplification de la lecture et du chargement du son à l’aide de la classe SoundFacade Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures L’architecture audio ActionScript 3.0 est puissante mais complexe. Les applications nécessitant des fonctions de lecture et de chargement de son de base uniquement peuvent utiliser une classe masquant une partie de la complexité en fournissant un ensemble d’appels et d’événements plus simple. Dans l’univers des modèles de conception de logiciel, une telle classe est appelée façade. La classe SoundFacade présente une seule interface permettant d’effectuer les tâches suivantes : • Chargement de fichiers audio à l’aide d’un objet Sound, d’un objet SoundLoaderContext et d’une classe SoundMixer • Lecture de fichiers audio à l’aide des objets Sound et SoundChannel • Envoi d’événements de progression de la lecture com/example/program mingas3/podcastplayer /RSSChannel.as Une classe ActionScript qui contient des données relatives à un canal RSS. com/example/program mingas3/podcastplayer /RSSItem.as Une classe ActionScript qui contient des données relatives à un élément RSS. com/example/program mingas3/podcastplayer /SoundFacade.as La classe ActionScript principale pour l’application. Elle encapsule les méthodes et les événements des classes Sound et SoundChannel et ajoute une prise en charge pour l’interruption et la reprise de la lecture. com/example/program mingas3/podcastplayer /URLService.as Une classe ActionScript qui récupère des données d’une URL distante. playerconfig.xml Un fichier XML contenant une liste des fils de syndication qui représentent des chaînes de podcast. comp/example/progra mmingas3/utils/DateUt il.as Classe permettant le formatage rapide de la date (Flash uniquement). Fichier Description GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 484 Utilisation du son Dernière mise à jour le 27/4/2013 • Interruption et reprise de la lecture du son à l’aide des objets Sound et SoundChannel La classe SoundFacade essaie d’offrir le meilleur de la fonctionnalité des classes de son ActionScript avec moins de complexité. Le code suivant indique la déclaration de classe, les propriétés de classe et la méthode constructeur SoundFacade() : public class SoundFacade extends EventDispatcher { public var s:Sound; public var sc:SoundChannel; public var url:String; public var bufferTime:int = 1000; public var isLoaded:Boolean = false; public var isReadyToPlay:Boolean = false; public var isPlaying:Boolean = false; public var isStreaming:Boolean = true; public var autoLoad:Boolean = true; public var autoPlay:Boolean = true; public var pausePosition:int = 0; public static const PLAY_PROGRESS:String = "playProgress"; public var progressInterval:int = 1000; public var playTimer:Timer; public function SoundFacade(soundUrl:String, autoLoad:Boolean = true, autoPlay:Boolean = true, streaming:Boolean = true, bufferTime:int = -1):void { this.url = soundUrl; // Sets Boolean values that determine the behavior of this object this.autoLoad = autoLoad; this.autoPlay = autoPlay; this.isStreaming = streaming; // Defaults to the global bufferTime value if (bufferTime < 0) { bufferTime = SoundMixer.bufferTime; } // Keeps buffer time reasonable, between 0 and 30 seconds this.bufferTime = Math.min(Math.max(0, bufferTime), 30000); if (autoLoad) { load(); } } GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 485 Utilisation du son Dernière mise à jour le 27/4/2013 La classe SoundFacade étend la classe EventDispatcher pour qu’elle puisse envoyer ses propres événements. Le code de classe déclare d’abord les propriétés pour un objet Sound et un objet SoundChannel. La classe stocke également la valeur de l’URL du fichier audio et une propriété bufferTime à utiliser lors de la lecture du son en continu. De plus, elle accepte des valeurs de paramètre booléennes qui affectent le comportement de lecture et de chargement : • Le paramètre autoLoad indique à l’objet que le chargement du son doit commencer dès la création de cet objet. • Le paramètre autoPlay indique que la lecture du son doit commencer dès qu’une quantité suffisante de données audio a été chargée. S’il s’agit d’un son diffusé en continu, la lecture commence dès qu’une quantité suffisante de données (comme spécifié par la propriété bufferTime) est chargée. • Le paramètre streaming indique que ce fichier audio peut commencer la lecture avant la fin du chargement. Le paramètre bufferTime prend la valeur -1 par défaut. Si la méthode constructeur détecte une valeur négative dans le paramètre bufferTime, elle définit la propriété bufferTime sur la valeur de SoundMixer.bufferTime. Ceci permet à l’application de prendre la valeur SoundMixer.bufferTime globale, par défaut, comme souhaité. Si le paramètre autoLoad est défini sur true, la méthode constructeur appelle immédiatement la méthode load() suivante pour commencer le chargement du fichier audio: public function load():void { if (this.isPlaying) { this.stop(); this.s.close(); } this.isLoaded = false; this.s = new Sound(); this.s.addEventListener(ProgressEvent.PROGRESS, onLoadProgress); this.s.addEventListener(Event.OPEN, onLoadOpen); this.s.addEventListener(Event.COMPLETE, onLoadComplete); this.s.addEventListener(Event.ID3, onID3); this.s.addEventListener(IOErrorEvent.IO_ERROR, onIOError); this.s.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onIOError); var req:URLRequest = new URLRequest(this.url); var context:SoundLoaderContext = new SoundLoaderContext(this.bufferTime, true); this.s.load(req, context); } La méthode load() crée un objet Sound puis ajoute des écouteurs pour tous les événements de son importants. Elle indique ensuite à l’objet Sound de charger le fichier audio, à l’aide d’un objet LoaderContext pour transmettre la valeur bufferTime. Etant donné que la propriété url peut être modifiée, vous pouvez utiliser une occurrence de SoundFacade pour lire différents fichiers audio à la suite : il vous suffit de modifier la propriété url et d’appeler la méthode load() afin de charger le nouveau fichier audio. Les trois méthodes d’écouteur d’événement suivantes indiquent comment l’objet SoundFacade suit la progression du chargement et décide quand lancer la lecture du son : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 486 Utilisation du son Dernière mise à jour le 27/4/2013 public function onLoadOpen(event:Event):void { if (this.isStreaming) { this.isReadyToPlay = true; if (autoPlay) { this.play(); } } this.dispatchEvent(event.clone()); } public function onLoadProgress(event:ProgressEvent):void { this.dispatchEvent(event.clone()); } public function onLoadComplete(event:Event):void { this.isReadyToPlay = true; this.isLoaded = true; this.dispatchEvent(evt.clone()); if (autoPlay && !isPlaying) { play(); } } La méthode onLoadOpen() s’exécute lorsque le chargement du son commence. Si vous pouvez lire le son en mode continu, la méthode onLoadComplete() définit immédiatement l’indicateur isReadyToPlay sur true. L’indicateur isReadyToPlay détermine si l’application peut lancer la lecture du son, peut-être en réponse à une action utilisateur (clic sur un bouton de lecture, par exemple). La classe SoundChannel gère la mise en mémoire tampon des données audio. Par conséquent, il est inutile de vérifier si suffisamment de données ont été chargées avant d’appeler la méthode play(). La méthode onLoadProgress() s’exécute régulièrement pendant le chargement. Elle envoie simplement une copie de son objet ProgressEvent pour le code qui utilise cet objet SoundFacade. Une fois que les données audio ont été complètement chargées, la méthode onLoadComplete() s’exécute en appelant la méthode play() pour des sons non diffusés en continu, si nécessaire. La méthode play() est décrite ci-dessous. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 487 Utilisation du son Dernière mise à jour le 27/4/2013 public function play(pos:int = 0):void { if (!this.isPlaying) { if (this.isReadyToPlay) { this.sc = this.s.play(pos); this.sc.addEventListener(Event.SOUND_COMPLETE, onPlayComplete); this.isPlaying = true; this.playTimer = new Timer(this.progressInterval); this.playTimer.addEventListener(TimerEvent.TIMER, onPlayTimer); this.playTimer.start(); } } } La méthode play() appelle la méthode Sound.play() lorsque le son peut être lu. L’objet SoundChannel résultant est stocké dans la propriété sc. La méthode play() crée ensuite un objet Timer qui sera utilisé pour envoyer des événements de progression de la lecture à des intervalles réguliers. Affichage de la progression de la lecture Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La création d’un objet Timer pour surveiller la lecture est une opération complexe que vous devez coder une seule fois. Le fait d’encapsuler cette logique Timer dans une classe réutilisable telle que la classe SoundFacade permet aux applications d’écouter les mêmes types d’événements de progression lorsqu’un son est chargé et lorsqu’il est lu. L’objet Timer créé par la méthode SoundFacade.play() envoie une occurrence de TimerEvent toutes les secondes. La méthode onPlayTimer() s’exécute chaque fois qu’un nouveau TimerEvent arrive : public function onPlayTimer(event:TimerEvent):void { var estimatedLength:int = Math.ceil(this.s.length / (this.s.bytesLoaded / this.s.bytesTotal)); var progEvent:ProgressEvent = new ProgressEvent(PLAY_PROGRESS, false, false, this.sc.position, estimatedLength); this.dispatchEvent(progEvent); } La méthode onPlayTimer() implémente la technique d’estimation de la taille décrite dans la section « Surveillance de la lecture » à la page 467. Elle crée ensuite une occurrence de ProgressEvent avec un type d’événement de SoundFacade.PLAY_PROGRESS, avec la propriété bytesLoaded définie sur la position actuelle de l’objet SoundChannel et la propriété bytesTotal définie sur la longueur estimée des données audio. Interruption et reprise de la lecture Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La méthode SoundFacade.play() décrite précédemment accepte un paramètre pos correspondant à une position de début dans les données audio. Si la valeur pos est zéro, la lecture du son commence au début. La méthode SoundFacade.stop() accepte également un paramètre pos, comme indiqué ici : GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 488 Utilisation du son Dernière mise à jour le 27/4/2013 public function stop(pos:int = 0):void { if (this.isPlaying) { this.pausePosition = pos; this.sc.stop(); this.playTimer.stop(); this.isPlaying = false; } } Chaque fois que la méthode SoundFacade.stop() est appelée, elle définit la propriété pausePosition de façon à ce que l’application sache où positionner la tête de lecture si l’utilisateur souhaite reprendre la lecture du même son. Les méthodes SoundFacade.pause() et SoundFacade.resume() indiquées ci-dessous appellent les méthodes SoundFacade.stop() et SoundFacade.play() respectivement, transmettant chaque fois une valeur de paramètre pos. public function pause():void { stop(this.sc.position); } public function resume():void { play(this.pausePosition); } La méthode pause() transmet la valeur SoundChannel.position actuelle à la méthode play(), qui la stocke dans la propriété pausePosition. La méthode resume() recommence à lire le même son en utilisant la valeur pausePosition comme point de début. Extension de l’exemple Podcast Player Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Cet exemple présente un Podcast Player dépouillé qui présente l’utilisation de la classe SoundFacade réutilisable. Vous pouvez ajouter d’autres fonctions pour améliorer l’utilité de cette application, notamment : • stocker la liste des fils de syndication et des informations d’utilisation concernant chaque épisode dans une occurrence de SharedObject pouvant être utilisée la prochaine fois que l’utilisateur exécute l’application ; • permettre à l’utilisateur d’ajouter son fil de syndication à la liste des chaînes de podcast ; • mémoriser la position de la tête de lecture lorsque l’utilisateur arrête ou quitte un épisode de façon à ce qu’il puisse être redémarré à partir de ce point la prochaine fois que l’utilisateur exécute l’application ; • télécharger des fichiers mp3 d’épisodes pour les écouter hors ligne, lorsque l’utilisateur n’est pas connecté à Internet ; • ajouter des fonctions d’abonnement qui vérifient régulièrement la présence de nouveaux épisodes dans une chaîne de podcast et mettre à jour la liste des épisodes automatiquement ; • ajouter une fonctionnalité de recherche de podcasts à l’aide d’une API à partir d’un service d’hébergement de podcasts, tel que Odeo.com. 489 Dernière mise à jour le 27/4/2013 Chapitre 25 : Utilisation de la vidéo Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La vidéo avec Flash est l’une des technologies dominantes d’Internet. Toutefois, l’interface traditionnelle de la vidéo, dans un écran rectangulaire avec une barre de progression surmontant des boutons de contrôle, n’est que l’un des usages possibles de la vidéo. En ActionScript, il est possible de contrôler avec précision le chargement, la présentation et la lecture d’une vidéo. Principes de base de la vidéo Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures La possibilité de lire et manipuler des informations vidéo en ActionScript, au même titre que les autres éléments multimédias (images, texte, animations, etc.) est l’une des principales caractéristiques d’Adobe® Flash® Player et d’Adobe® AIR™. Lorsque vous créez un fichier vidéo Flash (FLV) dans Adobe Flash CS4 Professional, vous avez la possibilité de sélectionner un habillage, ou « enveloppe », comportant les commandes de lecture courantes. Toutefois, vous n’êtes pas limité aux options disponibles. ActionScript offre un contrôle précis du chargement, de l’affichage et de la lecture de la vidéo, et vous pouvez créer votre propre enveloppe ou utiliser une vidéo de façon beaucoup moins traditionnelle. La gestion de la vidéo en ActionScript nécessite de travailler avec une combinaison de plusieurs classes : • Classe Video : la zone de contenu vidéo traditionnelle affichée sur la scène est une occurrence de la classe Video. La classe Video est un objet d’affichage, qu’il est donc possible de manipuler à l’aide des mêmes techniques que les autres objets d’affichage (positionnement, application de transformations, de filtres et de modes de fusion, etc.). • Classe StageVideo : la classe Video fait traditionnellement appel au décodage et au rendu logiciels. Si un périphérique gère l’accélération matérielle par processeur graphique, l’utilisation de la classe StageVideo permet à l’application d’exploiter pleinement la présentation à accélération matérielle. L’API StageVideo intègre un ensemble d’événements qui indiquent au code quand passer d’un objet StageVideo à un objet Video et inversement. La vidéo sur la scène impose diverses restrictions mineures en matière de lecture de vidéo. Si l’application gère ces restrictions, mettez en oeuvre l’API StageVideo. Voir « Directives et restrictions » à la page 530. • Classe NetStream : lorsque vous chargez un fichier vidéo qui doit être contrôlé en ActionScript, une occurrence de NetStream représente la source du contenu vidéo (dans ce cas précis, un flux de données vidéo). L’utilisation d’une occurrence de NetStream nécessite d’utiliser également un objet NetConnection, qui assure la connexion avec le fichier vidéo, comme un tunnel qu’emprunteraient les données vidéo. • Classe Camera : si vous devez gérer des données provenant d’une caméra connectée à l’ordinateur de l’utilisateur, une occurrence de Camera représente la source du contenu vidéo (la caméra de l’utilisateur et les données vidéo qu’elle transmet). Nouveauté dans Flash Player 11.4 et AIR 3.4 : vous pouvez utiliser une caméra pour alimenter StageVideo. Pour charger un fichier vidéo externe, vous pouvez charger ce fichier à partir d’un serveur Web standard (téléchargement progressif) ou gérer de la vidéo en flux continu transmise par un serveur spécialisé tel que Flash® Media Server d’Adobe. GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 490 Utilisation de la vidéo Dernière mise à jour le 27/4/2013 Concepts importants et terminologie Point de repère Marqueur qu’il est possible de placer en un point spécifique d’un fichier vidéo, notamment pour l’utiliser comme signet pour repérer ce point à partir du début de la vidéo ou pour fournir des données supplémentaires associées à ce moment de la vidéo. Codage Processus de conversion de données vidéo d’un format dans un autre format vidéo. Par exemple, la conversion d’une vidéo source en haute résolution dans un format plus adapté à la diffusion sur Internet. Image Elément de base des informations vidéo. Chaque image s’apparente à un cliché photographique représentant un moment précis. La lecture en séquence à vitesse élevée de ces images fixes donne l’illusion du mouvement. Image-clé Image vidéo qui contient l’ensemble des informations de l’image. Les autres images qui suivent une imageclé ne contiennent que les informations décrivant leurs différences par rapport à l’image-clé, et non pas les informations d’image complètes. Métadonnées Informations sur un fichier vidéo intégrées à ce fichier et lues après son chargement. Téléchargement progressif Lorsqu’un fichier vidéo est transmis par un serveur Web standard, les données vidéo sont chargées en mode progressif, c’est-à-dire en séquences. L’avantage est qu’il est possible de commencer à diffuser la vidéo avant la fin du téléchargement complet. Toutefois, il est alors impossible de passer directement à une partie de la vidéo qui n’a pas encore été chargée. Diffusion en continu Pour éviter le téléchargement progressif, il est possible d’utiliser un serveur vidéo spécial pour diffuser de la vidéo sur Internet selon une technique connue sous le nom de diffusion en continu. Avec la diffusion en flux continu, l’ordinateur client ne charge jamais toute la vidéo à la fois. Pour accélérer les délais de chargement, l’ordinateur n’a besoin, à un moment donné, que d’une partie de l’ensemble des informations vidéo. Comme un serveur spécial contrôle la diffusion du contenu vidéo, une partie quelconque de celle-ci peut être transmise à tout moment, et il n’est donc pas nécessaire d’attendre qu’elle soit chargée pour y accéder. Présentation des formats vidéo Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures Outre le format vidéo Adobe FLV, Flash Player et Adobe AIR prennent en charge les contenus vidéo et audio codés au format H.264 et HE-AAC des formats de fichier standard MPEG-4. Ces formats diffusent des vidéos de qualité supérieure à des débits inférieurs. Les développeurs peuvent utiliser les outils standard, notamment Adobe Premiere Pro et Adobe After Effects, pour créer et présenter du contenu vidéo de grande qualité. Type Format Contenant Vidéo H.264 MPEG-4 : MP4, M4V, F4V, 3GPP Vidéo Sorenson Spark Fichier FLV Vidéo ON2 VP6 Fichier FLV Audio AAC+ / HE-AAC / AAC v1 / AAC v2 MPEG-4:MP4, M4V, F4V, 3GPP Audio Mp3 Mp3 Audio Nellymoser Fichier FLV Audio Speex Fichier FLV GUIDE DU DÉVELOPPEUR D’ACTIONSCRIPT 3.0 491 Utilisation de la vidéo Dernière mise à jour le 27/4/2013 Voir aussi Flash Media Server : codecs pris en charge Technologie HTTP Dynamic Streaming d’Adobe Codage vidéo destiné aux périphériques mobiles AIR sur Android peut décoder un large éventail de vidéos H.264. Toutefois, seul un jeu partiel réduit de vidéos H.264 bénéficie d’une lecture fluide sur un téléphone portable. De nombreux téléphones portables ne disposent en effet pas d’une puissance de traitement suffisante. Adobe Flash Player pour périphérique mobile peut décoder les vidéos H.264 par le biais d’une accélération matérielle intégrée. Ce décodage allie une qualité de lecture supérieure à une consommation réduite. Le standard H.264 prend en charge plusieurs techniques d’encodage. Seuls les périphériques de pointe assurent une lecture fluide avec des profils et niveaux complexes. La plupart des périphériques peut toutefois lire des vidéos codées en profil de base. Sur les périphériques mobiles, un jeu partiel de ces techniques exploite l’accélération matérielle. Le profil et les paramètres de niveau définissent ce jeu partiel de paramètres et techniques de codage utilisé par l’encodeur. Pour les développeurs, il se traduit par la conversion de la vidéo à la résolution sélectionnée, assurant ainsi une lecture fluide sur la plupart des périphériques. Bien que les résolutions qui exploitent l’accélération matérielle varient d’un périphérique à l’autre, la plupart de ces derniers prend en charge les résolutions standard suivantes. Remarque : Flash Player prend en charge tous les niveaux et profils du standard H.264. Le respect de ces recommandations assure l’accélération matérielle et une expérience utilisateur optimisée sur la plupart des périphériques. Ces recommandations ne sont pas obligatoires. Pour plus d’informations et pour obtenir la liste des paramètres d’encodage dans Adobe Media Encoder CS5, voir Recommendations for encoding H.264 video for Flash Player 10.1 on mobile devices (disponible en anglais uniquement). Remarque : sous iOS, seules les vidéos codées avec les codecs Sorenson Spark et On2 VP6 peuvent être lues à l’aide de la classe Video. Vous pouvez lire les données vidéos H.264 dans le lecteur vidéo du périphérique en accédant à l’URL de la vidéo à l’aide de la fonction flash.net.navigateToURL(). Vous pouvez également lire les données vidéo H.264 à l’aide de la balise