________ __ ________ _______ __ __
| | | | | | / | | | | |
| _____| | | | __ | | __| | |__| |
| |_____ | | | |__| | \_ |_ | |
| _____| | |_____ | __ | __\ \ | __ |
| | | | | | | | | | | | | |
|__| |________| |__| |__| |_______/ |__| |__|
Cours sur le flash, ActionScript v2
flash.txt 23/03/2018
maregeneration
Sommaire
CHAPITRE 1 - Action Script
1.1. Espace de travail
1.2. Création d'un document
1.3. Insertion du document dans une page html
1.4. Action Script Variables
1.5. Structures de controle
1.6. Traduction des notions de classes et objets
1.7. Types de données objets
1.8. Structure d'un programme
1.9. External Interface
1.10. Charger HTML ou PhP dans un fichier flash
1.11. Utilisation des composants
CHAPITRE 2 - Action Script 3
2.1. Attacher des objets sur la scene
CHAPITRE 3 - Flex 4 avec Flash Builer
3.1. Etats d’affichage et de transitions
3.2. Création de composants MXML personnalisés
3.3. Evenements sur les objets
3.4. Appel webservice
3.5. Utilisation des ArrayCollection
3.6. Array et Vector
3.7. Utilisation des dataGrid
3.8. Text Layout Framework (TLF)
3.9. ExternalInterface : Javascript et ActionScript en communication
3.10. Charger HTML ou PhP dans un fichier flash
3.11. Definition de style
3.12. Création d'un curseur personnalisé
CHAPITRE 4 - AIR
4.1. Connecter un webservice
4.2. Appeler une application
4.3. Update framework
4.4. Update framework pour un installeur Natif
4.5. Air avec Flex
CHAPITRE 5 - Animate CC
5.1. Fonctionnement de base
5.2. Etape par etape
Introduction
Flash est un outil de programmation qui vous permet de créer une animation
simple ou une application web complexe et interactive, telle qu’une boutique en
ligne. Vous pouvez enrichir vos applications Flash en y ajoutant des images, du
son et de la vidéo.
CHAPITRE 1 - Action Script
ActionScript est basé sur la même spécification que JavaScript l'ECMA-262, et de
l'environnement de programmation.
1.1. Espace de travail
L'espace de travail se compose de prusieurs zones
- la scene au centre: contenus graphique.
- le scénario en haut: represente la bande du film animé.
- les calques du scénario: superposition d'images du film.
- une boite à outil à gauche: pour dessiner et peindre.
- le panneau actions en bas: créer des actions pour un objet ou une image.
- l'inspecteur des propriétés en bas: attributs de la sélection actuelle.
- le panneau bibliothèque à droite: symboles créés et fichiers importés.
Pour afficher des vignettes dans le scénario, cliquer sur l'icone à droite de la
règle de temps (timeline).
Une image-clé est une image dans laquelle est définit la modification d’un effet
animé ou des actions permettant de modifier un document. Flash peut interpoler,
ou remplir les images situées entre les images-clés pour produire des animations
fluides. L'organisation des images-clés dans le scénario permet de modifier la
séquence des événements dans l’animation.
Il est possible de masquer des calques, les classer dans des dossiers. Il est
conseillé d’utiliser des calques ou dossiers distincts pour certains éléments:
- les fichiers audio,
- les actions,
- les étiquettes et les commentaires d’image.
Les calques de guide permettent d'aligner les autres calques, ils n'apparaissent
pas dans le fichier publier. Ils permettent aussi de contrôler le mouvement des
objets d’une animation interpolée de mouvement. Rem : un calque normal placé sur
un calque de guide convertit le calque de guide en calque de guide de mouvement.
Pour éviter cela, placez tous les calques de guide en dernier.
Les objets tracés dans Flash sont des dessins vectoriels. Ils sont plus rapides
à télécharger que des images bmp. Une forme se compose de deux parties: la ligne
extérieure (le trait), et le remplissage qui colorie l’intérieur de la forme.
1.2. Création d'un document
Les documents enregistrés dans l’environnement auteur portent l’extension FLA.
Les applications Flash publiées prennent l’extension SWF.
Mise en oeuvre du graphique
1 Choisir Fichier > Nouveau > Document Flash puis Fichier > Enregistrer.
2 Dessiner un rectangle dans le premier calque renomé en illustration
3 Changer la couleur pour metre la même sur le trait et sur le remplissage.
4 Importer une image dans la librairie
5 Mettre un texte
6 Mettre un bouton (Window > Components > UI, ou Ctrl-F7)
7 Modifier dans le panneau de propriété le label du composant
8 Modifier dans le panneau de bibliothèque le nom du composant
9 Modifier le comportement du bouton (Window > Behaviors, ou Shift-F3)
Web -> Go To Web Page
Mise en oeuvre du scénario
1 Selectionner l'image
2 Insertion > Effets de scénario > Transition.
3 Etendre le calque dans le scénario: Copy Frames/Paste Frames à la 30eme image
Options d'accéssibilité
1 Sur chaque occurence d'un composant cliquer sur l'icone "bonhomme bleu"
2 Remplir une description si le composant doit etre lu par un lecteur d’écran
3 Spécifier un ordre de tabulation (View > Show Tab Order
4 Remplacer les textes statiques en textes dynamiques pour accéder aux options
d'accéssibilité (combo dans les propriétés du texte).
pour changer un index avec ActionScript: _root.logo_mc.tabIndex = 1;
1.3. Insertion du document dans une page html
<embed src="votre_anim.swf" quality="high" pluginspage=
"http://www.macromedia.com/shockwave/download/index.cgi
?P1_Prod_Version=ShockwaveFlash"
type="application/x-shockwave-flash"
width="Largeur" height="Hauteur">
1.4. Variables
ActionScript(AS) est sensible au majuscules et aux minuscules.
- déclaration : var a : String = 'ca'; var i,j : Number;
- affectation : a = 'tete a toto'; i = 15+17*3; += -= etc…
- lecture : trace(a);
- operations : iv = 7 < (16/2); iv = 2*5;
- operandes : + - / * % ++ -- < > <= >= != == === && || ! & | ^ ~ << >> >>>
- commentaires : /* */ //
1.5. Structures de controle
// structure while // structure do while // structure if then else
while (var i>0) { i = 4; if(id == 0){ … }
i--; do { i--; else{ … //facultatif
} } while (var i > 0); }
// structure for // structure for in // structure case
for (var i=4; monObjet = {nom:'Joe', âge:25}; switch (nombre) {
i>0;i--) for (nomDeProp in monObjet) { case 1: trace ("1"); break
{ trace(nomDeProp + " : " + case 2: trace ("2"); break
… monObjet[nomDeProp]); default trace ("rien")
} } }
1.6. Traduction des notions de classes et objets
Une classe est une structure évoluée, qui permet de regrouper non seulement des
données, mais aussi des fonctions (méthodes). L'accé aux champs, et aux méthodes
se fait avec l'operateur ".". Un objet est une representation dynamique de la
classe. Tous les objets d'une même classe auront les mêmes possibilités. Sous
AS, à part Object toutes les classes héritent d’une autre classe. Une classe
peut uniquement être définie dans un fichier .AS externe.
L'héritage permet de définir une nouvelle classe à partir d'une classe de base.
On parle alors de sous classe, ou de classe dérivée. Cela permet de hiérarchiser
et de créer des modèles entre les classes.
______________ ________________________ _____________________
Statut dans la Accés aux membres de la Accés aux membres de
classe de base classe de base par un la classe de base par
modifieurs utilisateur de la classe une classe derivée
______________ ________________________ _____________________
private non non
- rien - non oui
public oui oui
Toutes les méthodes et propriétés, sont visibles et utilisables à l'intérieur de
la classe elle-même: à l' implémentation de la classe et de ses méthodes.
L'héritage entre les 2 classes est implémenté par la déclaration de la classe
class Fille extends Merre.
Si une super-classe prend des paramètres différents, il faut que le constructeur
de la sous-classe appele la super-classe avec les paramètres requis.
class Mere { class Fille extends Mere {
private var age:Number function grandit() {
public var beaute:Number super.grandit(); // classe Mère
function grandit() { beaute = beaute +1;
age = age+1; }
} }
function Mere(age:Number) {
this.age = age; // instanciation
} var martine:Mere = new Mere(35);
}
Le lancement des constructeurs se fait du sommet vers le bas de la pyramide
d'héritage.
Une méthode statique s'appelle à partir d'une classe, il est possible de
l'executer directement sans créer une instance d'objet de type de la classe.
ex: static var nbDefs:Number=0; // nombre de définitions
nbDefs++; // dans le constructeur de la classe
Une interface est une collection de déclarations de méthodes. Une classe peut
hériter d'une classe et implémenter une ou plusieurs interfaces (implements).
Une interface s'utilise comme une classe abstraite. Le but d'une interface est
de pouvoir rapprocher d'autres types d'objets quand il ne peuvent pas être
hiérarchiser. Cela améliore le polymosphisme (plusieurs aspects), par example:
interface Déplacable { class Box implements Déplacable {
function monter(); var x_pos, y_pos;
function descendre(); function monter() { … }
} function descendre() { … }
}
var newBox:Movable = new Box();
if(Movable(someObject) != null) { unObjet.moveUp(); }
Une interface peut être utilisé comme un type. Ce type étant alimenté par une
instance normale d'une classe. par ex: public void ajouter(Dessinable d) { }
Une interface peut hériter d'une super-interface.
1.7. Types de données objets
Définifion de constantes (facilite la maintenance)
String
Number
Boolean
Object
MovieClip
1.8. Structure d'un programme
Cette partie explique la déclaration et la création des fonctions, ainsi que la
portée des variables.
// typage strict de paramètre et de valeur renvoyée
function square(x:Number):Number {
var squared = x*x;
return squared;
}
1.9. External Interface
Ci dessous un exemple complet d'intégration flash sur une page html, avec prise
en charge du javascript.
ExtInterface.fla
var JavaScriptFct:Function=null;
var JavaScriptPrm:String="";
var methodName:String = "envoiActionScript";
var instance:Object = null;
var method:Function = envoiActionScript;
// Contrôle de compatibilité de la version Flash Player
if (ExternalInterface.available) {
ExternalInterface.addCallback(methodName, instance, envoiActionScript);
trace("ExternalInterface available ! "); }
else {
trace("Erreur ExternalInterface\nMerci de mettre à jour Flash Player.");
}
// Fonction interface avec javascript (JS->FLASH)
function envoiActionScript(resultat:String,sortie:String,arResult:Array)
{
if (sortie != "ERREUR Javascript")
{
_root.arResult = arResult;
}
trace("resultat="+resultat+"&sortie="+sortie);
if (_root.JavaScriptPrm != undefined)
_root.JavaScriptFct(_root.JavaScriptPrm);
}
// Fonction interface avec javascript (FLASH->JS)
function JavaScript(sFunction:String, sPrm1:String, arTmp:Array, fct:Function)
{
_root.JavaScriptFct = fct;
_root.JavaScriptPrm = sFunction+" "+sPrm1;
_root.FCT_TraceLog("trace", "envoiActionScript", sFunction+"("+sPrm1+","+arTmp+","+fct+")");
ExternalInterface.call(sFunction,sPrm1,arTmp);
}
JavaScript("LignesDevisInit", "", _root.dataSet_LignesDevis.items, undefined);
js/INI_init.js
// Espaces de donnees
var dataSet_LignesDevis;
js/global.js
// Retourne L'objet Flash
function thisMovie(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName]
}
else {
if (document.embeds && document.embeds[movieName])
return document.embeds[movieName];
else
return document[movieName]
}
}
// trace Javascript
function trace(str) {console.log(str);}
// Classe globale accessible partout _root
// PS: Une classe Javascript se fait avec une fonction
function global() {
// Inclusion des scripts JQuery
$.getScript('js/INI_init.js', function(){});
// Fonctions Publiques accessible en aval
this.fct = function(sPrm) {}
// Constructeur
this.constructor = function() {
trace('Initialisation ...');
this.dataSet_LignesDevis = new Array;
}
this.constructor();
}
var _root = new global();
function LignesDevisInit(sPrm,arTmp)
{
_root.dataSet_LignesDevis = new Array;
for(var i=0; i < arTmp.length; ++i) {
trace(arTmp[i]["Libelle"]);
_root.dataSet_LignesDevis[i] = arTmp[i];
}
thisMovie("mouvieId").envoiActionScript(resultat,tampon,arTmp);
}
</script>
index.html
<script language="javascript">
var pageHost = ((document.location.protocol == "https:") ? "https" : "http");
function getParms(){
if(window.location.search.length > 1)
{
var parms = window.location.search.substring(1).split("&");
var parmList = new Array();
for(var i = 0; i < parms.length; i++){
parmList[i] = new Object;
parmList[i].name = parms[i].substring(0,parms[i].indexOf("="));
parmList[i].value = parms[i].substring(parms[i].indexOf("=")+1);
}
return parmList;
}
else return null;
}
// declaration des paramétrages de l'url
var base = "default";
var uid = "";
var controleElementaire = "N";
// chargement des paramétrages de l'url
var parms = getParms();
if(parms != null)
for(var i = 0; i < parms.length; i++) {
if (parms[i].name == "base")
base = parms[i].value;
if (parms[i].name == "controleElementaire")
controleElementaire = parms[i].value;
}
</script>
<script language="javascript">AC_FL_RunContent = 0;</script>
<script src="AC_RunActiveContent.js" language="javascript"></script>
<SCRIPT LANGUAGE="Javascript" SRC="js/jquery-3.2.1.min.js"> </SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="js/global.js"> </SCRIPT>
<script language="javascript">
if (AC_FL_RunContent == 0) {
alert("Cette page nécessite le fichier AC_RunActiveContent.js.");
} else {
AC_FL_RunContent(
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',
'width', '100%',
'height', '100%',
'src', 'JADE 140',
'quality', 'high',
'pluginspage', 'http://www.macromedia.com/go/getflashplayer',
'align', 'middle',
'play', 'true',
'loop', 'true',
'scale', 'showall',
'wmode', 'window',
'devicefont', 'false',
'id', 'mouvieId',
'bgcolor', '#cccccc',
'name', 'ExtInterface Exemple',
'menu', 'true',
'allowFullScreen', 'false',
'allowScriptAccess','sameDomain',
'movie', 'ExtInterface',
'salign', '',
'flashVars', 'loadBase='+base+'&controleElementaire='+controleElementaire
); //end AC code
}
</script>
1.10. Charger HTML ou PhP dans un fichier flash
Créez votre page HTML avec une structure XML et non pas celle d'un HTML...
Une balise ne sera pas lue par flash comme si c'était du gras,
il va falloir la définir dans le CSS. Vous n'aurez pas d'id de texte à marquer,
mais directement un nom de balise. vous n'aurez pas non-plus de balise. Vous
gérez tous les retours à la ligne avec des
et vous notez soigneusement,
sauf pour lien et images, les noms des balises que vous utilisez.
<body>
<titre1>Lorem ipsum dolor sit amet
</titre1><br>
<titre2>consectetur adipiscing elit
</titre2>.
<br />
<corpsTexte><img src='image1.jpg' width="147" height="260" align='right'/><br />
In feugiat condimentum lacus. Aliquam erat volutpat. Duis sit amet neque.
<br /> <br />
<gras>Nam dolor. Curabitur ligula eros
</gras>, convallis eget, pharetra non,
<br />
<italique>Photo de midnightcomm
</italique> In hac habitasse platea dictumst.
<br /> <br />
<A HREF="http://www.kommunauty.fr">Voir kommunauty
</A>. Suspendisse tincidunt
<br /> <br />
</corpstexte>
</body>
Là, vous définissez le CSS en fonction du nom des balises.
A {
font-family: Arial,Helvetica,sans-serif;
color:#AAAAAA;
font-size: 11px;
display: inline;
text-decoration:underline;
}
titre1 {
font-family: Arial,Helvetica,sans-serif;
font-size: 16px;
font-weight: bold;
display: block;
}
titre2 {
font-family: Arial,Helvetica,sans-serif;
font-size: 13px;
font-style: italic;
display: block;
}
corpsTexte {
font-family: Arial,Helvetica,sans-serif;
font-size: 11px;
display: block;
}
gras { font-weight: bold; }
italique { font-style: italic; }
Ouvrez Flash, créez un nouveau document, dans lequel vous placez n'importe
quelle mise en page, symboles d'agrémentation comme si c'était un flash normal,
avec en plus un champ de texte que nous allons ici prénommer d'occurrence
"champ", multiligne, auquel vous faites glisser une scrollbar:
Maintenant créez un nouveau calque pour les actions. Je préfères séparer le code
du contenu, ce n'est pas obligé mais c'est plus propre, qui a utiliser include
dans la première image #include "Scripts/exemple.as".
On commence par créer la variable qui nous servira à accueillir le code CSS :
// Création de la variable de type style css
var style1:TextField.StyleSheet = new TextField.StyleSheet();
// chargement du css dedans
style1.load("style.css");
//application au champ
champ.styleSheet = style1;
Maintenant on défini les paramètres de M. Champ de texte :
//définition des paramètres du champ de texte.
champ.multiline= true;
champ.wordWrap = true;
champ.html = true;
Et pour fini on charge la page et on l'implante :
// On va maintenant charger notre page en tant que XML dans une variable
var page:XML = new XML();
//On ignore les blancs
page.ignoreWhite = true;
// On charge le fichier
page.load("page.html");
page.onLoad = function () {
// et on attribue son contenu au texte "champ"
champ.htmlText = page;
}
http://www.kommunauty.fr/article-206-charger-html-ou-php-dans-un-fichier-flash
1.11. Utilisation des composants
Les composants sont des clips qui contiennent des paramètres permettant d’en
modifier l’aspect et le comportement. Un composant peut offrir n’importe quelle
fonctionnalité imaginée par son créateur. Il peut s’agir d’un simple bouton
radio, ou d’un contenant, comme un panneau défilant.
De base Flash contient des composants, visualisables dans Windows/Components. Il
est possible de télécharger des composants à partir de Macromedia Exchange. Pour
installer des composants :
- Placez le fichier SWC, FLA contenant le composant dans "/First Run/Components"
- Ouvrez Flash.
Tous les composants contiennent des paramètres prédéfinis que vous pouvez
configurer pendant la programmation dans Flash. Chaque composant a également un
jeu unique de méthodes, de propriétés et d’événements ActionScript, également
appelé API (interface de programmation), qui permet de définir les paramètres et
d’autres options à l’exécution.
Les composants inclus dans Flash sont divisés en 4 catégories:
- l’interface utilisateur (UI): interactions homme machine
- le support: lire un support (ex:MediaPlayback)
- les données: manipuler des sources de données (WebServiceConnector, XMLConn…)
- les gestionnaires: compos invisibles qui permettent de gérer une fonction (ex:
FocusManager, DepthManager, PopUpManager et StyleManager)
Les composants v2 sont inclus dans le panneau Composants en tant que symboles
Clip compilé (SWC). Un SWC est un clip composant dont le code a été compilé. Ils
ne peuvent pas être modifiés, mais comme pour les autres composants, il est
possible de changer leurs paramètres.
Chaque composant v2 est une classe, et chaque classe est un paquet ActionScript.
Par ex, un bouton radio est une occurrence de la classe RadioButton dont le nom
de paquet est mx.controls. Tous les composants créés avec la v2 sont des sous-
classes des classes UIObject/UIComponent et héritent de tous leurs événements,
propriétés et méthodes. Beaucoup de composants sont des sous-classes d'autres.
Tous les composants utilisent le même modèle d’événement, les mêmes styles CSS
et le même mécanisme intégré d’application d’enveloppes.
CHAPITRE 2 - Action Script 3
2.1 Attacher des objets sur la scene
Voici comment ajouter un clip situé dans votre bibliothèque avec Actionscript 3.
Créez un clip puis ajoutez-le dans la bibliothèque de l'animation.
Dans la bibliothèque, clic droit sur votre clip puis Liaison > Classe
Cocher Exporter pour ActionScript
Cocher Exporter dans la première image
Nommer la classe différement que le nom du movie Clip par défaut (my_mcClass).
var my_temp:my_mcClass = new my_mcClass();
my_temp.x = -128;
my_temp.y = stage.stageHeight /2;
addChild(my_temp);
pour acceder à root, il faut passer par (root as MovieClip)
Ajouter un lien dynamiquement:
var label1:TextField = new TextField();
label1.autoSize = TextFieldAutoSize.LEFT;
label1.selectable = false;
label1.text = String(i+1)+" - texte ";
label1.x=40;
label1.y=40+i*15;
label1.addEventListener ( "mouseOver", this.LienActif);
label1.addEventListener ( "mouseOut", this.LienInactif);
var formatLiens:TextFormat = new TextFormat();
formatLiens.url = items[i];
formatLiens.color = 0x000000;
formatLiens.underline = false;
formatLiens.font = "Verdana";
label1.setTextFormat(formatLiens);
this.addChild(label1);
function LienActif(evt_obj:Object)
{
var formatLiens:TextFormat = new TextFormat();
formatLiens.color = 0x000000;
formatLiens.underline = false;
formatLiens.font = "Verdana";
evt_obj.target.setSelection(0, 255);
evt_obj.target.alwaysShowSelection = true;
evt_obj.target.setTextFormat(formatLiens);
}
function LienInactif(evt_obj:Object)
{
var formatLiens:TextFormat = new TextFormat();
formatLiens.color = 0x000000;
formatLiens.underline = false;
formatLiens.font = "Verdana";
formatLiens.bold = false;
evt_obj.target.alwaysShowSelection = false;
evt_obj.target.setTextFormat(formatLiens);
}
CHAPITRE 3 - Flex 4 avec Flash Builer
3.1. Etats d’affichage et de transitions
Flash Builder permet de créer des applications dont l’apparence varie selon les
tâches exécutées par l’utilisateur. Par exemple, l’état de base de l’application
peut représenter la page d’accueil et inclure un logo, une barre latérale et un
message de bienvenue. Lorsque l’utilisateur clique sur un bouton de la barre
latérale, l’apparence (l’état) de l’application change de façon dynamique et la
zone de contenu principale est remplacée par un formulaire de bon de commande
sans modifier la position du logo et de la barre latérale. Flex vous permet
d’appliquer cette interaction aux états d’affichage et aux transitions. Une
transition permet d'améliorer le changement visuel d’un état à un autre par des
effets. Tout comme vous pouvez utiliser des états d’affichage pour ces mises en
forme, il est également possible d’utiliser le conteneur de navigateur ViewStack
avec d’autres conteneurs de navigateur.
Dans la vue Etats il est possible de créer et de définir l'etat de demarrage.
this.setCurrentState("etat2",true);
3.2. Création de composants MXML personnalisés
Vous pouvez créer des composants personnalisés pour ajouter certaines fonctions
à un composant existant ou pour créer un composant réutilisable, tel qu’une zone
de recherche ou l’affichage d’un élément dans une grille de données. Vous pouvez
également rédiger un nouveau composant, qui n’existe pas dans la structure Flex.
Les composants que vous créez sont affichés dans la vue Composants en mode
Création. Vous pouvez distribuer les composants à l’aide des fichiers SWC. Si le
composant est créé à partir de composants existants, l’utilisation de MXML en
facilitera la définition. Toutefois, s’il s’agit d’un nouveau type de composant,
définissez-le en tant que composant ActionScript.
1) Cliquez sur Fichier > Nouveau > Composant MXML.
2) Spécifiez le dossier parent pour le fichier du composant personnalisé.
3) Spécifiez le nom de fichier du composant (frmMXML2).
4) Dans le champ Basé sur, sélectionnez le composant d'ou dérive le composant.
Enregistrez le fichier dans un dossier situé dans le répertoire du projet actuel
ou dans le chemin source du projet actuel. Le composant s’affichera ainsi dans
la vue Composants. On peut alors glisser le composant sur la scene, et le nommé
en renseignant la propriété id. Pour insérer ce composant dynamiquement sur la
scène, utiliser la méthode addElement ou addElementAt:
var aura:frmMXML2=new frmMXML2();
aura.x = 357;
aura.y = 45;
aura.comboPrat.dataProvider = dataSet_Prat;
aura.comboPrat.labelFunction = filtrePraticien;
this.addElementAt(aura,this.numChildren - 1);
pour lancer l'élément en popUp (ex d'un MXML personnalisé)
var dBox:IFlexDisplayObject = PopUpManager.createPopUp(this,frmMXML2,true);
(dBox as frmMXML2).addEventListener(KeyboardEvent.KEY_DOWN,app_keyDownHandler);
PopUpManager.centerPopUp(dBox);
commande de fermeture depuis le popup : PopUpManager.removePopUp(this);
Attention le popup doit implémenter IFocusManagerContainer, sinon des erreurs
apparaitrons sur certain composants: TypeError: Error #1009:
Cannot access a property or method of a null object reference
Copiez collez le code suivant sur le mxml
<s:Group ... implements="mx.managers.IFocusManagerContainer" ... >
<fx:Script><![CDATA[
import mx.core.IFlexDisplayObject;
protected var _defaultButton:IFlexDisplayObject;
public function get defaultButton():IFlexDisplayObject {
return _defaultButton;
}
public function set defaultButton(value:IFlexDisplayObject):void {
_defaultButton = value;
}
]]></fx:Script>
ajout dynamique d'un composant:
var label1:TextField = new TextField();
label1.autoSize = TextFieldAutoSize.LEFT;
label1.selectable = false;
label1.text = String(i+1)+" - texte ";
label1.x=40;
label1.y=40+i*15;
label1.addEventListener ( "mouseOver", this.LienActif);
label1.addEventListener ( "mouseOut", this.LienInactif);
var formatLiens:TextFormat = new TextFormat();
formatLiens.url = items[i];
formatLiens.color = 0x000000;
formatLiens.underline = false;
formatLiens.font = "Verdana";
label1.setTextFormat(formatLiens);
var ui:UIComponent = new UIComponent();
ui.addChild(label1);
this.addElement(ui);
3.3. Evenements sur les objets
Flash Builder peut générer un évenement. Click droit sur le composant, et Créer
le gestionnaire ... Exemple sur le compasant TitleWindows:
<fx:Script>
import mx.events.CloseEvent;
private function maFonctionClose(e:CloseEvent):void{
e.currentTarget.visible = false;
// si lancé en popup: PopUpManager.removePopUp(this);
}
]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>
<s:TitleWindow x="0" y="0" width="524" height="383" title="TRACE LOG"
close="maFonctionClose(event)">
Interception des frapes sur le clavier
// classe gb
var frappeSurEchap:Function;
var frappeSurEnter:Function;
var frappeSurSuppr:Function;
var id_interval_Frappe:Number;
//fenetre principale
protected function app_keyDownHandler(event:KeyboardEvent):void
{
trace("Key Pressed: " + String.fromCharCode(event.charCode) +
" (character code: " + event.charCode + ") - keyCode="+String(event.keyCode));
if (event.ctrlKey && (event.keyCode==220))
{
var dBox:IFlexDisplayObject = PopUpManager.createPopUp(this,TraceLog, true);
PopUpManager.bringToFront(dBox);
PopUpManager.centerPopUp(dBox);
gb.TraceAfficherLogs((dBox as TraceLog).ta_log);
}
// Action sur la touche Echap
if ((event.keyCode == 27) && (gb.frappeSurEchap != null)) {
gb.frappeSurEchap(null);
}
// Action sur la touche Entrer
if ((event.keyCode == 13) && (gb.frappeSurEnter != null)) {
gb.frappeSurEnter(null);
}
// Action sur la touche Suppr
if ((event.keyCode == 46) && (gb.frappeSurSuppr != null)) {
gb.frappeSurSuppr(null);
}
}
// fenetre popup
clearInterval(gb.id_interval_Frappe);
id_interval_Frappe = setInterval(initRaccourcisClavier,100);
public function initRaccourcisClavier():void
{
gb.frappeSurSuppr = null;
// actions selon focus
var fm:FocusManager = new FocusManager(winEncaiss)
var objetFocus:Object=fm.getFocus();
if (objetFocus!=null)
{
gb.frappeSurEchap = null;
gb.frappeSurEnter = null;
// Error #1069: Property id not found on mx.core.UITextField*
// mettre un tabIndex aux composants ayant un id et devant etre scannés.
var tabIndex:Number = objetFocus.tabIndex;
if ((tabIndex != -1) && (tabIndex<23))
{
//var composant:String=String(objetFocus.id);
gb.frappeSurEchap = winEncaissements_close;
gb.frappeSurEnter = BtnRechercher_clickHandler;
}
}
}
3.4. Appel webservice
Flash Builder possède un moniteur de réseau qui permet de voir les echanges, le
temps passé, et la quantité de données échangées. Activer le moniteur de réseau
via l'icone sur la barre de titre du cadran Moniteur de réseau.
// Appel webservice
protected function monBouton(event:MouseEvent):void
{
ItemProvider=new ArrayCollection;
gridData.dataProvider = ItemProvider;
clientResultat.token = iwebdatabaseconnection.executeselect("10.210.1.21",
"SELECT * FROM MAGASIN", "31", "bdjade");
}
// Reponse du webservice
protected function reponseWSDL(event:ResultEvent):void
{
// création d'une requette url
var adresse:URLRequest = new URLRequest ("http://10.210.1.21/Tmpxml/"
+ event.result[event.result.length-1] + ".xml");
// chargement de l'url
var chargeur:URLLoader = new URLLoader ();
chargeur.dataFormat = URLLoaderDataFormat.TEXT;
chargeur.load(adresse);
// définition des évenements de l'objet chargeur
chargeur.addEventListener(Event.COMPLETE, finDuChargement);
chargeur.addEventListener(IOErrorEvent.IO_ERROR, indiquerErreur);
//mise à jour du dataGrid;
gridData.dataProvider = ItemProvider;
}
// définition de la fonction exécutée par l'évenement COMPLETE :
// ( déclenchée lorsque le chargement se termine )
private function finDuChargement ( event:Event ):void
{
var xDoc:XMLDocument = new XMLDocument();
xDoc.ignoreWhite = true;
var lignesXML:XML = XML(event.target.data);
xDoc.parseXML(lignesXML.toXMLString());
for(var index:Number=0;
index<XMLNode(XMLNode(xDoc.firstChild.childNodes[1])).childNodes.length;
index++)
{
var aNode:XMLNode = XMLNode(XMLNode(XMLNode(
xDoc.firstChild.childNodes[1])).childNodes[index]);
var obj:Object = new Object();
for (var attribute:String in aNode.attributes)
{
obj[attribute] = aNode.attributes[attribute];
}
ItemProvider.addItem(obj);
}
}
// fonction indiquant si une erreur de chargmement survient :
private function indiquerErreur( event:Event ):void {
trace(event);
Alert.show("Erreur de Chargement xml.");
return;
}
<s:CallResponder id="clientResultat"
result="reponseWSDL(event)"/>
La liste suivant présente les types généraux et comment ils sont convertis en
ActionScript:
* String (xsd:string) >> String
* Integer (xsd:int) >> Int
* Floating-point Number (xsd:float) >> Number
* Boolean (xsd:boolean) >> Boolean
* Date (xsd:date) >> Date
* Array (xsd:string[], etc) >> mx.collections.ArrayCollection
3.5. Utilisation des ArrayCollection
Création Manuelle d'une donnée ArrayCollection:
<mx:ArrayCollection id="arrColl"> arrColl.addItem(Object);
<mx:source> arrColl.getItemAt(0);
<mx:Array> arrColl.setItemAt(obj, idx);
<mx:Object label="EleveA" note="16" /> arrColl.filterFunction = monFiltre;
<mx:Object label="EleveB" note="11" /> arrColl.refresh();
</mx:Array> arrColl.filterFunction = null;
</mx:source>
</mx:ArrayCollection>
private function monFiltre(item:Object):Boolean {
if (item.hasOwnProperty("value"))
return parseFloat(item.value) == 0;
return false;
}
deuxieme methode:
var data:ArrayCollection = ArrayCollection(grid.dataProvider);
var filter:IFilter = new Filter();
filter = new LevelFilter(filter, levelValue);
filter = new CategoryFilter(filter, categoryValue);
filter = new DateFilter(filter, dateValue, "DD/MM/YY");
data.filterFunction = filter.apply;
data.refresh();
Création d'un curseur:
private var cursor:IViewCursor;
private function init():void {
var sortField:SortField = new SortField(null, true);
var sort:Sort = new Sort();
sort.fields = [sortField];
arrColl.sort = sort;
arrColl.refresh();
cursor = arrColl.createCursor();
}
Sur une ComboBox il faut définir un labelFunction pour que le programme sache
quelle colonne de l'Array Collection il doit afficher. Attention un élément du
comboBox est vide et ne correspond à rien d'existant (pas selectedIndex ni de
item) si le Combo est éditable. Ce peut peut provoquer des exeptions.
function filtreModes(item:Object):String {
if (item == null) return ""; // Vérification obligatoire
if (item.hasOwnProperty("MPALIBELLE"))
return item.MPALIBELLE;
return "";
}
ComboBox1.dataProvider = arrColl;
ComboBox1.labelFunction = filtreModes;
On utilise le type ArrayCollection pour stocker des ensembles de donnés. Ce type
a de nombreux avantages, au rang desquels on peut retenir la possibilité de
mettre dedans tous types d'objet, ainsi qu'un ensemble de méthodes pour filtrer,
trier, manipuler le contenu.
Mais quand on commence à manipuler de grandes quantité de données, on s'aperçoit
vite des limites de l'ArrayCollection. En effet, lors de l'ajout ou la
suppression d'éléments dans une ArrayCollection, une série d'events sont
dispatchés, ainsi que beaucoup de traitements internes. Cela cause de gros
ralentissements, voir dans le pire des cas, vous plantez votre navigateur.
A coté de cela, on a notre bon vieux Array. Certes, plus basique, il permet
quand même de faire pas mal de choses, (par exemple le reverse qui n'existe pas
pour l'ArrayCollection), parfois de manière aussi simple, et surtout beaucoup
plus rapidement. De plus, on retrouve ce type dans presque tous les langages,
donc pour du classMapping, c'est parfait.
Le type Vector est une nouveauté apportée par Flash Player 10, qui correspond au
type Vector en Java. C’est-à-dire qu’il vous permet de typer un Array. Le
résultat est flagrant, le parcours d’un Vector est 20 fois plus rapide que celui
d’un Array.
[Vector] 0.008ms for creating 100000 items and find the average
[Array] 0.032ms for creating 100000 items and find the average
[ArrayCollection] 4.303ms for creating 100000 items and find the average
3.6. Array et Vector
Vous pouvez stocker divers types de données dans un élément Array, y compris les
nombres, les chaînes, les objets et même d'autres tableaux. Vous pouvez créer un
tableau multidimensionnel en concevant un tableau indexé et en affectant à
chacun de ses éléments un tableau indexé différent.
var a:Array = new Array(); a=Array("a","b","c"); a=Array(3); a.length;
Méthodes disponibles :
concat(), every(callback:Function, thisObject:* = null)
filter(), forEach(), indexOf(), join(), lastIndexOf(), map(), pop(), push(),
reverse(), shift(), slice(), some(), sort(), sortOn(), splice(), ...
constantes: CASEINSENSITIVE, DESCENDING, NUMERIC, RETURNINDEXEDARRAY, UNIQUESORT
La classe Vector vous permet d’accéder à un vecteur et de le manipuler; un
vecteur est un tableau dont les éléments possèdent tous le même type de données.
Le type de données des éléments d’un vecteur est appelé le type de base. Le type
de base peut correspondre à n’importe quelle classe ou interface.
La manipulation d’un vecteur se fait en utilisant l’opérateur d’accès au tableau
([]) mais aussi en utilisant des méthodes identiques à la classe Array. Parmi
ces méthodes, on retrouve : push(), pop(), shift(), unshift(), splice().
var trimestre:Vector.<String>;
trimestre = new Vector.<String>();
trimestre = new Vector.<String>(4, true);
trimestre[0] = "Janvier-Mars";
var len:int=trimestre.push("Avril-Juin", "Juillet-Septembre");
Lors de l’ajout d’une seule valeur à la fois, l’opérateur d’accès au tableau []
se montre plus rapide que la méthode push().
Tri d'un tableau ## : reverse(), sort(), sorton()
var poets:Array = new Array();
poets.sort(Array.DESCENDING | Array.CASEINSENSITIVE);
poets.push({name:"Angelou", born:"1928"});
poets.sortOn("born", Array.NUMERIC); // only Arrays
3.7. Utilisation des dataGrid
Attention de bien distinguer les dataGrid mx des dataGrid spark, qui ne
possedent pas toutes les fonctionnalités de mise en forme des colonnes du
composant mx, puisque en fait le dataGrid spark n'est qu'un assemblage de listes
car les développeur Adobe n'on pas eut le temps de le réalisé.
http://blogs.adobe.com/aharui/2009/12/spark_list_spark_list_spark_da.html
Toutes les actions sur le dataGrid se fond via le dataprovider. Les colonnes
éditables du dataGrid se gèrent au niveau des évenements:
protected function dataGrid1_keyDownHandler(event:KeyboardEvent):void {
if (event.keyCode == 13) // Validation par entrer
Alert.show(dataPrv.getItemAt(dataGrid1.selectedIndex).SAISI);
}
protected function dataGrid1_itemFocusInHandler(event:DataGridEvent):void {
gb.frappeSurEchap = null;
gb.frappeSurEnter = null;
}
protected function dataGrid1_itemFocusOutHandler(event:DataGridEvent):void {
if (isNaN(dataPrv.getItemAt(event.rowIndex).SAISI)) {
dataPrv.getItemAt(event.rowIndex).SAISI = "";
}
}
3.8. Text Layout Framework (TLF)
Les composants text spark sont dotés de fonctionnalité de texte enrichis TLF
var markup:String = "<TextFlow xmlns='http://ns.adobe.com/textLayout/2008'> "
markup += "<p fontFamily='Arial'>This is TLF markup with paragraphs.</p> "
markup += "<p color='0x663399'>The root TextFlow tag is included.</p> "
markup += "</TextFlow>";
rt1.textFlow = TextFlowUtil.importFromString(markup);
<s:TextArea id="rt1" width="300" height="50"/>
Attention; si une valeur text est définit par la suite sur le TextArea, tous
les éléments textflow seront automatiquement convertis en texte.
private static const textInput:XML =
<TextFlow xmlns="http://ns.adobe.com/textLayout/2008">
<div> <p color="0x336699"><span>The Text. </span></p> </div>
</TextFlow>;
!!! Attention le texte ne doit pas contenir les caractere < et > !!!
private var _textFlow:TextFlow;
var importer:ITextImporter =
TextConverter.getImporter(TextConverter.TEXT_LAYOUT_FORMAT);
_textFlow = importer.importToFlow(textInput);
* TextConverter.TEXT_LAYOUT_FORMAT text layout markup format
* TextConverter.PLAIN_TEXT_FORMAT plain text string
* TextConverter.TEXT_FIELD_HTML_FORMAT HTML (subset of HTML supported)
Ajouter une image, sélectionner et éditer le texte, mise en forme:
[Embed(source="adobe_air_logo.jpg")]
[Bindable]
static public var imgClass:Class;
var p:ParagraphElement = new ParagraphElement();
var inlineGraphicElement:InlineGraphicElement = new InlineGraphicElement();
inlineGraphicElement.source = imgClass;
inlineGraphicElement.width=32;
inlineGraphicElement.height=32;
p.addChild(inlineGraphicElement);
textFlow.addChild(p);
textFlow.interactionManager = new EditManager(new UndoManager());
var tlf:TextLayoutFormat = new TextLayoutFormat();
tlf.fontSize =11;
tlf.direction = Direction.RTL;
tlf.columnCount = 3;
tlf.columnGap = 15;
textFlow.format = tlf;
pour mettre a jour le contenus après une modification de format:
textFlow.fontSize = 11;
flow.flowComposer = new StandardFlowComposer();
textFlow.flowComposer.updateAllControllers();
3.9. ExternalInterface : Javascript et ActionScript en communication
Il est parfaitement possible de faire communiquer Javascript avec ActionScript,
d'ailleurs, ces langages sont très proches au niveau de la syntaxe. Attention;
pour un projet Flash Builder (FB) le html généré est écrasé à chaque déploiement
le mieux étant de créer un nouvel html pour la version release. Par défaut sous
FB le flash est inséré avec comme id le nom du projet. Ci dessous code html
<script>
function envoiActionScript()
{
var texte = document.getElementById('texte').value;
document.getElementById('projet_FB').envoiActionScript(texte);
}
function envoiJavaScript(str)
{
document.getElementById('texte').value = str;
}
</script>
<object type="application/x-shockwave-flash" id="projet_FB" data="flash.swf"
width="550" height="400">
<param name="movie" value="flash.swf" />
<param name="allowScriptAccess" value="sameDomain" />
</object>
<p><textarea id="texte" cols="60" rows="10"></textarea></p>
<p><input type="button" value="Envoyer à Actionscript"
onclick="envoiActionScript();" /></p>
Dans le Flash, On écoute la fonction envoiActionScript de Javascript, qui
correspond à envoiActionScript d'actionscript. On ajoute un événement sur le
bouton pour permettre l'envoi à Javascript de notre champ de saisie dans
l'animation :
// classe principale (évenement Creation_Complete par ex)
if (ExternalInterface.available) {
ExternalInterface.addCallback("envoiActionScript", envoiActionScript);
}
// fonction publique dans la classe principale
var fct:Function=null;
public function envoiActionScript(s:String):void {
fct(s);
}
private function envoyer_click(event:MouseEvent):void {
if (ExternalInterface.available) {
function traitement(s:String):void {
}
fct = traitement;
ExternalInterface.call("envoiJavaScript", this._texte.text);
}
}
Cela permet d'appeler facilement des ActiveX OLE en local sur la machine, et de
récupérer le résultat à la volée.
<script>
function envoiActionScript(param)
{
var newObject = new ActiveXObject(servername.typename[, location])
newObject.traitement(param);
var res = newObject.ZoneSortie;
document.getElementById('projet_FB').envoiActionScript(res);
}
</script>
Il est également possible de lancer une popup avec ExternalInterface, très
pratique en terme de droits sur les action de la popup, fermeture automatique
par exemple.
ExternalInterface.call("window.open", url, "_blank",
"width=0,height=0,left=0,top=0, fullscreen=No");
Récupération des paramètres de l'url
package
{
import flash.net.URLVariables;
import flash.external.ExternalInterface;
public class URLParamManager
{
private var urlParameters:Object;
public function URLParamManager()
{
var result:URLVariables = new URLVariables();
if (ExternalInterface.available) {
var search:String =
ExternalInterface.call("location.search.substring", 1);
if (search && search.length > 0) {
result.decode(search);
urlParameters = result;
}
} else throw new Error("Accès Javascript non disponible");
}
public function getParamValue(paramName:String):String
{
if (!urlParameters) return "";
var strValue:String = urlParameters[paramName];
if (!strValue) strValue = "";
return strValue;
}
}
}
var prm:URLParamManager=new URLParamManager();
idUser = prm.getParamValue("i01");
3.10. Charger HTML ou PhP dans un fichier flash
var textLoader:URLLoader = new URLLoader();
var cssLoader:URLLoader = new URLLoader();
var textReq:URLRequest=new URLRequest('ma page .html, .php, ...');
var cssReq:URLRequest=new URLRequest("mon css .css");
textLoader.load(textReq);
cssLoader.load(cssReq);
textLoader.addEventListener(Event.COMPLETE, textLoadComplete);
cssLoader.addEventListener(Event.COMPLETE, cssLoadComplete);
// Texte chargé => on convertit les infos en 'string' et on affiche
function textLoadComplete(event:Event):void {
// Récupération du résultat & conversion en 'string'
var s_htmlText:String=textLoader.data.toString();
// Découpage de la chaîne de <body> à </body>
s_htmlText=s_htmlText.substring(s_htmlText.indexOf("<body>"),
s_htmlText.lastIndexOf("</body>"));
tx.condenseWhite=true;// ignore les blancs
// affichage du texte dans tx (tx est un texte dynamique)
tx.htmlText=s_htmlText;
}
//--------- CSS chargée => on applique la css à tx
function cssLoadComplete(event:Event):void {
var sheet:StyleSheet = new StyleSheet();// Création d'un objet css
sheet.parseCSS(cssLoader.data); // Parse le css
tx.styleSheet=sheet; // Application de la css à tx
}
3.11. Definition de style
Les styles se définissent juste au dessus de par inclusion :
par inclusion : ou directement :
<fx:Style source="assets/style.css" /> <fx:Style>
/* CSS file */ mx|DataGrid {
@namespace s "library://ns.adobe.com/flex/spark"; font-weight:bold;
@namespace mx "library://ns.adobe.com/flex/mx"; textAlign: center;
.dataGridMX {
}
alternatingItemColors: #FFFFFF, #E2E5E8;
</fx:Style>
rollOverColor: #ACCDE3;
selectionColor: #A1B2C7;
}
La définition de style pour se faire de manière globale sur un composant par
mx|composant
Sur un mx:DataGrid par exemple dans la vue Propriété, il est alors possible de
le sélectionner dans la section Style. Sur le mxml cela donne:
<mx:DataGrid id="DBGrid1" x="9" y="4" width="573" height="383"
styleName="dataGridMX" variableRowHeight="true">
Les styles disponibles sur un composant sont listés dans le panneau propriétés,
section style. L'aide en ligne AS3 les détailles également sur la page : http://
help.adobe.com/fr_FR/FlashPlatform/reference/actionscript/3/package-detail.html
Définition d'un style global pour tous les éléments:
global {
font-family: Arial;font-size: 10;chrome-color: #CCCCCC;
selection-color: #A1B2C7;roll-over-color: #ACCDE3;focus-color: #A1B2C7;
}
mx|DataGrid {
alternatingItemColors: #FFFFFF, #E2E5E8;header-style-name:titles;
}
.titles { color:#000000;font-weight:bold;textAlign: left; }
http://ressources.mediabox.fr/tutoriaux/flashplatform/programmation/generalites/
flex4-1-jour/composants-spark-presentation
http://www.adobe.com/fr/devnet/flex/testdrive/articles/5_customize_app.html
3.12. Création d'un curseur personnalisé
[Bindable]
[Embed(source="assets/images/hpane.png")]
private var hpanIcon:Class;
// survol du trait de séparation entre les deux grille
protected function hrule1_mouseOverHandler(event:MouseEvent):void
{ // change le curseur
cursorManager.setCursor(hpanIcon,2,0,-6);
}
// fin de survol du trait de séparation entre les deux grille
protected function hrule1_mouseOutHandler(event:MouseEvent):void
{ // enleve le curseur personnalisé
cursorManager.removeAllCursors();
}
// click sur le trait de séparation entre les deux grille
protected function hrule1_mouseDownHandler(event:MouseEvent):void
{ // attache la fonction sur l'évenement de déplacement de la sourie
addEventListener(MouseEvent.MOUSE_MOVE, hrule1_deplacer);
}
// fin de traitement sur la ligne de séparation
protected function hrule1_mouseUpHandler(event:MouseEvent):void
{ // détache la fonction sur l'évenement de déplacement de la sourie
removeEventListener(MouseEvent.MOUSE_MOVE, hrule1_deplacer);
cursorManager.removeAllCursors();
}
// traitement tanq que le click est sur la ligne de séparation
protected function hrule1_deplacer(event:MouseEvent):void
{
//mouseY par rapport au haut de l'appli,
hrule1_caller(mouseY-35); //35:hauteur du titre
}
protected function hrule1_caller(y:Number):void
{
//hrule.y par rapport au haut de la titleWindows
hrule1.y = y; //35:hauteur du titre
// !!! dépend de la hauteur du hrule !!!
// fonctionne tres bien avec la taille par défaut
if (hrule1.y-gridListingDetail.y-3 < gridListingDetail.minHeight) {
gridListingDetail.height = gridListingDetail.minHeight;
hrule1.y = gridListingDetail.height+3+gridListingDetail.y;
}
else {
gridListingDetail.height = hrule1.y-gridListingDetail.y-3;
}
gridSaisies.y = hrule1.y+5;
gridSaisies.height = (winEncaiss.height-35)-hrule1.y-19;
}
CHAPITRE 4 - AIR
4.1. Connecter un webservice
La première chose que nous allons faire est de dire à Flash de charger certaines
bibliothèques à partir de Flash Builder. Ces bibliothèques sont essentielles
pour que notre application communique avec un service Web, mais pour une raison
quelconque, ces bibliothèques ne sont pas incluses par Flash. Heureusement, ces
bibliothèques sont fournies par une installation par défaut de Flash Builder, et
surtout, elles fonctionnent lorsque vous dites à Flash de les utiliser.
Dans "paramètres de publication", cliquez sur le bouton Modifier situé à droite
de la propriété Paramètres d'ActionScript 3. Sur l'onglet bibliothèque, cliquez
sur "Rechercher le Chemin" et naviguez jusqu'à l'emplacement des librairies de
Flash Builder:
C:\Program Files (x86)\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\frameworks\libs
Il est maintenant possible de connecter un webservice:
package as3air {
public class WSDL {
import mx.rpc.soap.*;
import mx.rpc.events.*;
import mx.rpc.AbstractOperation;
import mx.rpc.wsdl.WSDLBinding;
import mx.collections.ArrayCollection;
public var WSDLURL;
public var operation;
public var params;
var ws:WebService;
var bLoaded;
var fctResult,fctError,fctSend,fctStatus,fctTrigger;
var ev;
// constructor
public function WSDL() {
this.WSDLURL = '';
this.ws = new WebService;
this.operation = '';
this.params = new Array();
this.fctResult = null;
this.bLoaded = false;
}
function loadWS()
{
if (!this.bLoaded) {
this.ws.addEventListener(LoadEvent.LOAD, BuildServiceRequest);
this.ws.loadWSDL(this.WSDLURL);
}
}
function BuildServiceRequest(evt:LoadEvent)
{
trace(this.WSDLURL+" loaded");
this.bLoaded = true;
this.ws.addEventListener(ResultEvent.RESULT, fctResult);
if (this.fctTrigger != undefined)
this.fctTrigger();
this.fctTrigger = undefined;
}
private function fctResultEvent(evt:ResultEvent)
{
this.ev.target.results = evt.result;
this.fctResult(this.ev)
}
private function fctFaultEvent(evt:FaultEvent)
{
}
public function addEventListener (sEvt, fct) {
if (!this.bLoaded) {
loadWS();
}
switch (sEvt) {
case 'result': this.ws.addEventListener(ResultEvent.RESULT, fct);
fctResult = fct; break;
case 'send': this.fctSend = fct; break;
case 'status': this.ws.addEventListener(FaultEvent.FAULT, fct); break;
}
}
// Execution du WSDL
public function trigger() {
// Creation valeurs de retour
this.ev = new Array;
this.ev['target'] = new Array;
var aTarget = new Array;
aTarget['operation'] = this.operation;
aTarget['results'] = "";
aTarget['params'] = this.params;
aTarget['fctResult'] = this.fctResult;
this.ev['target'] = aTarget;
if (!this.bLoaded) {
this.fctTrigger = this.trigger;
loadWS();
return;
}
trace(this.WSDLURL+" call");
if (this.fctSend != null)
this.fctSend(this.ev);
// Exécution via SOAPClient
if (this.operation == "executeselect")
this.ws.executeselect(this.params[0], this.params[1], this.params[2],
this.params[3]);
if (this.operation == "ExecuteselectGroupe") {
for (var i=0; i<this.params[1].length; i++)
this.params[1][i] = reformate(params[1][i]);
this.ws.ExecuteselectGroupe(this.params[0], this.params[1],
this.params[2], this.params[3]);
}
if (this.operation == "InterfaceSRT")
{
this.ws.InterfaceSRT(this.params[0], this.params[1], this.params[2],
this.params[3], this.params[4], this.params[5], this.params[6]);
}
}
// Pour palier au fait que Flash AS3 webservice transforme le <> en <>
private function reformate(str:String):String
{
return (str.replace("<>"," not like "));
}
}
}
import as3air.WSDL;
var WSDL_BaseConnectMulti:WSDL = new WSDL();
function reponseWSDLMulti(ev:Object)
{
var tabResult:Object=ev.result;
var tabParams:Object=ev.target.params;
if (tabResult.length > 0)
if (String(tabResult[0].substr(0,6)) == 'ERREUR')
trace('Erreur');
_root.tabScript=(tabResult as ArrayCollection).source;
_root.resultON=true;
}
WSDL_BaseConnectMulti.addEventListener("result", reponseWSDLMulti);
réf: connecter un webservice
https://www.kirupa.com/flash/connecting_web_service_pg1.htm
4.2. Appeler une application:
Attention Flash génère mal le fichier xml en mettant desktop en premier. Il faut
absolument que extendedDesktop apparaise en premier pour que cela fonctionne
après déploiement. Vérifier dans Projectname-app.xml le tag supportedProfiles:
extendedDesktop desktop
Par conception, cette méthode ne fonctionne pas avec l'UAC activé. Dans ce cas
il vaux mieu utiliser File.openWithDefaultApplication
Autre chose: pour que cela fonctionne après l'installation de l'application air,
il faut un installeur natif en EXE (il faudra prévoir un autre methode de mise à
jour).
package
{
import flash.desktop.NativeProcess;
import flash.desktop.NativeProcessStartupInfo;
import flash.events.ProgressEvent;
import flash.filesystem.File;
import mx.controls.Alert;
import Base64;
import flash.utils.ByteArray;
public class PlatformPackaging
{
private var nativeProcess:NativeProcess;
private var isErrorOccured:Boolean;
private var batFile:File;
private var cmdFile:File;
private var strOLE:String;
private var sPrm:String;
public var FctRetour:Function; // AH
public var PrmRetour:String; // AH
private function get isWindows():Boolean {
return true;
}
public function PlatformPackaging() { }
public function start(strOLE:String,sPrm:String):void
{
this.strOLE = strOLE;
this.sPrm = sPrm;
if(isWindows)
{
//batFile = File.applicationDirectory.resolvePath("cmd/my_command.bat");
//cmdFile = new File("c:\\Windows\\System32\\cmd.exe");
cmdFile = new File("c:/Windows/Jade140AutoExe.exe");
}
proceedToPackaging();
}
private function proceedToPackaging():void {
var processArgs:Vector.<String> = new Vector.<String>;
//processArgs.push("/c");
//processArgs.push(batFile.nativePath);
processArgs.push(this.strOLE);
processArgs.push(this.sPrm);
//var workingDirectory:File
// = File.applicationDirectory.resolvePath("publish/");
var workingDirectory:File
= File.applicationDirectory.resolvePath("c:\\Windows\\");
var nativeProcessStartupInfo:NativeProcessStartupInfo
= new NativeProcessStartupInfo();
nativeProcessStartupInfo.arguments = processArgs;
nativeProcessStartupInfo.executable = cmdFile;
nativeProcessStartupInfo.workingDirectory = workingDirectory;
nativeProcess = new NativeProcess();
nativeProcess.addEventListener(ProgressEvent.STANDARD_ERROR_DATA,
onStandardErrorOutputDataHandler);
nativeProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA,
onStandardOutputDataHandler);
nativeProcess.start(nativeProcessStartupInfo);
}
private function onStandardErrorOutputDataHandler(event:ProgressEvent) : void
{
var certResponse:String = nativeProcess.standardError.readUTFBytes(
nativeProcess.standardError.bytesAvailable);
trace("PlatformPackaging:"+certResponse);
if (this.FctRetour != null)
this.FctRetour(certResponse,"ERREUR Javascript",null, null);
nativeProcess.removeEventListener(ProgressEvent.STANDARD_ERROR_DATA,
onStandardOutputDataHandler);
nativeProcess.exit();
}
//Alert.show(certResponse,'Error');
function onStandardOutputDataHandler(event:ProgressEvent):void
{
var status:String = nativeProcess.standardOutput.readUTFBytes(
nativeProcess.standardOutput.bytesAvailable);
var decoded:ByteArray = Base64.decode(status);
trace ("status="+status+".");
trace ("decoded="+decoded.toString());
var arTmp = decoded.toString().split("&");
if ((this.FctRetour != null) && (arTmp.length > 0))
{
this.FctRetour(arTmp[2].substr(9,64000),arTmp[1].substr(7,64000),
null, null);
}
}
}
}
import PlatformPackaging;
var pp = new PlatformPackaging;
pp.start("lectureCONFIG","");
réf: nativeProcess
https://stackoverflow.com/questions/13579621/how-to-executes-a-bat-file-on-local-machine-from-adobe-air-application
réf: base64
http://www.sociodox.com/base64.html
réf: UAC
https://community.adobe.com/t5/air/nativeprocess-fails-to-work-correctly-with-uac/td-p/2890475
4.3. Update framework
Voici comment ajouter un contrôle de mise à jour à votre fichier .fla .
Pour commencer, nous avons besoin d'ajouter les fenêtres de mise à jour:
Recupérer le fichier applicationupdater_ui.swc contenu dans le SDK AIR > 2.5
"AIRSDK_Compiler.zip\frameworks\libs\air" ou dans Flash Builder 4.7
C:\Program Files\Adobe\Adobe Flash Builder 4.7 (64 Bit)
\sdks\4.6.0\frameworks\libs\air\applicationupdater_ui.swc
Placez ces 2 librairies dans un dossier "Libs" à côté de votre fichier .fla.
Recupérer les fichiers d'icones
C:\Program Files (x86)\Adobe\Adobe Flash Builder 4.7\sdks\4.6.0\samples\icons
Récupérer le fichier "air_update_flash.zip" depuis le site d'adobe
https://www.adobe.com/devnet/air/articles/air_update_framework.html
Dans Flash CS5:
- Fichier, parametres de publication; Lecteur, icone clé plate
- Sélectionner AIR 2.5
- Onglet Icones, vérifier l'emplacement des icones
icone 16x16 : as3air/AppIconsForAIRPublish/AIRApp_16.png
icone 32x32 : as3air/AppIconsForAIRPublish/AIRApp_32.png
icone 48x48 : as3air/AppIconsForAIRPublish/AIRApp_48.png
icone 128x128 : as3air/AppIconsForAIRPublish/AIRApp_128.png
- Onglet Signature, créer un certificat
- Fichier, parametres de publication; Script, icone clé plate
- dialecte: ActionScript 3.0
- cocher Déclarer automatiquement les occurrences de scène
- ajoutter dans les bibliothèque Libs/applicationupdater_ui.swf
- Coller myWindow.as à la racine du projet
- Coller le movieClip myWindow depuis air_update_flash.fla
- Publier le fichier AIR (sous Flex définir un dossier d'exportation)
Dans IIS
1. placer le fichier .air et le update_flash.xml dans un dossier du serveur
2. Modifier le nom et la version dans le fichier xml, et l'url dans flash
3. ajouter un type mime dans IIS: AIR application/octet-stream
Dans la fenêtre Actions de votre animation Flash, saisissez le code suivant :
// AIR specific
var bConfigAir:Boolean = false;
CONFIG::AIR
{
bConfigAir = true;
import as3air.updaterframework;
var url = "http://ocucopc0335/botp/updater/update_flash.xml";
var upd:updaterframework = new updaterframework(url);
}
// AIR end
package as3air {
public class updaterframework {
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.utils.Dictionary;
import air.update.ApplicationUpdater;
import air.update.events.StatusFileUpdateEvent;
import air.update.events.StatusUpdateErrorEvent;
import air.update.events.StatusFileUpdateErrorEvent;
import air.update.events.DownloadErrorEvent;
import air.update.events.StatusUpdateEvent;
import air.update.events.UpdateEvent;
import flash.events.ErrorEvent;
import flash.events.MouseEvent;
import air.update.events;
import flash.desktop.NativeApplication;
import flash.display.NativeWindow;
import flash.display.NativeWindowInitOptions;
import flash.display.NativeWindowSystemChrome;
import flash.display.NativeWindowType;
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import fl.controls.Button;
import Namespace;
import XML;
import air.update.ApplicationUpdaterUI;
import flash.geom.Point;
var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI();
var window:NativeWindow;
var windowContent:myWindow = new myWindow();
var existentListeners:Dictionary = new Dictionary();
public var sNm:String;
public var sVersionNumber:String;
//initialize the updater; gets called when the application is loaded
public function updaterframework(sUrl):void {
trace("initializeUpdater");
setApplicationNameAndVersion();
appUpdater.updateURL = sUrl;
//we can hide the dialog asking for permission for checking for a new update;
//if you want to see it just leave the default value (or set true).
appUpdater.isCheckForUpdateVisible = false;
//if isFileUpdateVisible is set to true, File Update, File No Update,
//and File Error dialog boxes will be displayed
appUpdater.isFileUpdateVisible = true;
//if isInstallUpdateVisible is set to true,
//the dialog box for installing the update is visible
appUpdater.isInstallUpdateVisible = true;
//we set the event handlers for INITIALIZED nad ERROR
appUpdater.addEventListener(UpdateEvent.INITIALIZED, onUpdate);
appUpdater.addEventListener(ErrorEvent.ERROR, onError);
appUpdater.addEventListener(StatusUpdateErrorEvent.UPDATE_ERROR,
onStatusUpdateError);
appUpdater.addEventListener(ProgressEvent.PROGRESS,
onDownloadProgress);
appUpdater.addEventListener(UpdateEvent.DOWNLOAD_COMPLETE,
onDownloadComplete);
appUpdater.addEventListener(DownloadErrorEvent.DOWNLOAD_ERROR,
onDownloadError);
//initialize the updater
appUpdater.initialize();
}
//listener for INITIALIZED event of the applicationUpdater;
function onUpdate(event:UpdateEvent):void {
//start the process of checking for a new update and to install
appUpdater.checkNow();
}
//Handler function for error events triggered by ApplicationUpdater.initialize
function onError(event:ErrorEvent):void {
trace(event);
createWindow();
displayWindowError(event.errorID, event.text);
}
//error listener for an error when the updater could not download or
//interpret the update descriptor file.
function onStatusUpdateError(event:StatusUpdateErrorEvent):void {
createWindow();
displayWindowError(event.subErrorID, event.text);
}
//error listener for DownloadErrorEvent.
//Dispatched if there is an error while connecting or
//downloading the update file. It is also dispatched for invalid HTTP statuses
//(such as “404 - File not found”).
function onDownloadError(event:DownloadErrorEvent):void {
createWindow();
displayWindowError(event.subErrorID, event.text);
}
//listener for the ProgressEvent when a download of the new version is in progress
function onDownloadProgress(event:ProgressEvent):void {
windowContent.bar.setProgress(event.bytesLoaded, event.bytesTotal);
}
//listener for the complete event for downloading the application
//just close the window; the downloaded version will be automatically installed,
//and then the application gets restarted
function onDownloadComplete(event:UpdateEvent):void {
closeWindow(null);
}
//sets the state of the window in error display mode
function displayWindowError(errorId:int, errorText:String):void {
windowContent.title = "Error";
windowContent.enableDescription = true;
windowContent.description = "Error ID: " + errorId + ". " + errorText;
windowContent.buttonLeft.visible = false;
windowContent.buttonRight.label = "Close";
windowContent.bar.visible = false;
addEventToButton(windowContent.buttonRight, MouseEvent.CLICK, closeWindow);
}
//create a window using NativeWindow, and as a content myWindow class
function createWindow():void {
if (window == null) {
var pt:Point = new Point;
var options:NativeWindowInitOptions = new NativeWindowInitOptions();
options.systemChrome = NativeWindowSystemChrome.STANDARD;
options.type = NativeWindowType.NORMAL;
window = new NativeWindow(options);
window.x = 300;
window.y = 200;
pt.x = 450;
pt.y = 254;
window.minSize = pt;
//window.width = 550;
window.stage.stageHeight = 430;
window.stage.stageWidth = 450;
window.stage.scaleMode = StageScaleMode.NO_SCALE;
window.stage.align = StageAlign.TOP_LEFT;
window.stage.addChild(windowContent);
windowContent.bar.visible = false;
}
//window.alwaysInFront = true;
window.visible = true;
}
//close the window
function closeWindow(event:Event):void {
window.close();
}
//hide the window
function hideWindow():void {
window.visible = false;
}
//sets the application name and version in the main window
function setApplicationNameAndVersion():void {
var appXML:XML = NativeApplication.nativeApplication.applicationDescriptor;
var ns:Namespace = appXML.namespace();
sNm = appXML.ns::name;
sVersionNumber = appXML.ns::versionNumber;
}
//add to the given button, the listener for given type.
//we use a dictionary to store for each button the listener registered.
//when this function gets called, first we remove any registered listener.
//Next we register the listener on the button, and next we save to dictionary.
function addEventToButton(button:Button, type:String, listener:Function):void {
//remove existent listneres
if (existentListeners[button] != null) {
var arr:Array = existentListeners[button] as Array;
button.removeEventListener(type, arr[0]);
}
existentListeners[button] = [];
button.addEventListener(type, listener);
existentListeners[button][0] = listener;
button.visible = true;
}
}
}
Fichier update.xml
<?xml version="1.0" encoding="utf-8"?>
<update xmlns="http://ns.adobe.com/air/framework/update/description/2.5">
<versionNumber>1.0</versionNumber>
<url>http://www.ladressedevotresite/Appliz.air</url>
<description><![CDATA[
This version has fixes for the following known issues:
*First issue
*Second issue
]]></description>
</update>
Pour l'instant, la version 1.0, empêche le déclenchement de la mise à jour, car
c'est la même que celle de l'application qui tourne.
Dans la pratique, vous devez donc simplement créer une application Air et opter
pour un numéro de version de 1.0
Ensuite, vous pouvez diffuser votre application. Dès que vous avez besoin de
faire une mise à jour, vous changer la valeur 1. 0 du fichier update.xml en 1.1,
ainsi que celle du nouveau fichier .air que vous allez générer, vous placez sur
le serveur la nouvelle version de votre application en .air (Appli.air dans
notre exemple) et la mise à jour se fera automatiquement.
Pour une deuxième mise à jour : Générez à nouveau un . air avec la valeur 1.2 et
changez le 1.1 du fichier update.xml en 1.2 également.
Pour Deployer
- vérifier la version dans config AIR
- Le logiciel Adobe AIR doit être déjà installé sur l’ordinateur.
- Il suffit d’envoyer le fichier AIR au destinataire.
(sous forme de lien dans une page Web).
- Double-cliquez sur le fichier AIR.
- Dans la fenêtre d’installation, conservez les paramètres par défaut, puis
cliquez sur Continuer.
* Installation de l’application dans le répertoire Program Files
* Création des raccourcis
* Ajout d’une entrée dans l’application Ajout/Suppression de programmes
La génération du fichier Air pose un problème de timestamp. Pour intégrer le
timestamp, il faut générer un .AIRI et générer le AIR a partir de celui ci
ex (réf: https://forums.adobe.com/thread/2218793)
"C:\Program Files (x86)\Adobe\Adobe Flash CS5.5\AIR2.6\bin\"adt.bat
-package -storetype pkcs12 -keystore cle.p12
-tsa "http://sha256timestamp.ws.symantec.com/sha256/timestamp"
botp.air botp.airi
"C:\Program Files (x86)\Adobe\Adobe Flash CS5.5\AIR2.6\bin\"adt.bat
-package -storetype pkcs12 -keystore cle.p12
-tsa "http://sha256timestamp.ws.symantec.com/sha256/timestamp" -target native
-storetype pkcs12 -keystore cle.p12 air_update_flash.exe
air_update_flash.airi
réf
https://www.yazo.net/index.php/mettre-a-jour-une-application-air.html
https://www.adobe.com/devnet/air/articles/air_update_framework.html
https://stackoverflow.com/questions/4748610/adobe-air-error-16824-version-mismatch-while-trying-to-auto-update
https://helpx.adobe.com/air/kb/update-air-2-or-earlier.html
Pour Compiler
- ouvrir Logo.fla, Paramètres de publication
- vérifier les librairies dans config AS3 applicationupdater_ui.swc
- vérifier la présence du chemin suivant
C:\Program Files\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\frameworks\libs
- vérifier la présence des fichiers suivants ou modifier le source Image1 et PlatformPackaging:
c:\windows\jade140AutoExe.exe
C:\inetpub\BOTP\updater\update_flash.xml
4.4. Update framework pour un installeur Natif
Update Framework that comes with the AIR SDK doesn't support updates of AIR apps
packaged into native installers
Avec Flex:
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"...
xmlns:nativeUpdater="com.riaspace.nativeUpdater.*"
// Native Updater
protected function checkNativeUpdate(sBaseUrl:String ):void
{
updater.updateApplication(sBaseUrl+"/updater/update.xml");
}
<fx:Declarations>
<nativeUpdater:NativeUpdater id="updater" />
Avec CS5.5
import air.update.ApplicationUpdaterUI;
import air.update.events.UpdateEvent;
import flash.events.InvokeEvent;
import flash.desktop.NativeApplication;
import com.riaspace.nativeUpdater.NativeUpdater;
var updater:NativeUpdater = new NativeUpdater();
updater.updateApplication(sBaseUrl+"/updater/update.xml");
Facultatif : ajouter au chemin de la bibliothèque: NativeApplicationUpdater-0.5.1.swc
Pour mettre à jour
Ajouter au chemin de la bibliothèque: coltware_airxzip_v1_0_1.swc
Modifier com/riaspace.nativeUpdater\NativeUpdater.as
import com.coltware.airxzip.*;
public function unzip_botp():void{
var reader:ZipFileReader = unzip_init(updateFile);
var fileName:String = updateFile.name.substr(0, updateFile.name.lastIndexOf("."));
var list:Array = reader.getEntries();
for each(var entry:ZipEntry in list){
if(!entry.isDirectory()){
var sTmp:String = fileName+".exe";
if(entry.getFilename().toLowerCase() == sTmp.toLowerCase() ){
// ByteArray with unziped data
var loadedBytes:ByteArray = reader.unzip(entry);
// Creating new FileStream to write downloaded bytes into
updateUnzippedFile = File.createTempDirectory().resolvePath(sTmp);
var destFileStream:FileStream = new FileStream;
destFileStream.open(updateUnzippedFile, FileMode.WRITE);
// Writing loaded bytes into the FileStream
destFileStream.writeBytes(loadedBytes);
destFileStream.close();
}
}
}
}
protected function installUpdate():void
{
// Running the installer using NativeProcess API
var info:NativeProcessStartupInfo = new NativeProcessStartupInfo;
unzip_botp();
info.executable = updateUnzippedFile;
//info.executable = updateFile;
var process:NativeProcess = new NativeProcess;
process.start(info);
// Exit application for the installer to be able to proceed
NativeApplication.nativeApplication.exit();
}
réf:
https://github.com/pwalczyszyn/nativeapplicationupdater/blob/master/src/com/riaspace/nativeUpdater/NativeApplicationUpdater.as
https://github.com/brucelane/vpDude/blob/master/src/com/riaspace/nativeUpdater/NativeUpdater.as
4.5. Air avec Flex
Flex Builder, Error timestamp
https://forums.adobe.com/thread/2218793
adt.bat -sign -storetype YOUR_CERTIFICATE -tsa "http://sha256timestamp.ws.symantec.com/sha256/timestamp" "YOUR_PROJECT.airi" "YOUR_PROJECT.air"
adt -package -storetype pkcs12 -keystore CERTIFICATE.p12 -tsa "http://sha256timestamp.ws.symantec.com/sha256/timestamp" -target native -storetype pkcs12 -keystore CERTIFICATE.p12 YOUR_APP.exe YOUR_APP.airi
"C:\Program Files (x86)\Adobe\Adobe Flash CS5.5\AIR2.6\bin\"adt.bat -package -storetype pkcs12 -keystore cle.p12 -tsa "http://sha256timestamp.ws.symantec.com/sha256/timestamp" -target native -storetype pkcs12 -keystore CERTIFICATE.p12 air_update_flash.exe air_update_flash.airi
Flex Builder, Error default cible
réparer le fichier .actionScriptProperties
<buildTargets>
<buildTarget buildTargetName="default">
<airSettings airCertificatePath="I:/Users/alvaro.hermo.BLANCHARDSTOWN/Documents/FLEX/BOTP_TestDesign2/cle.p12" airTimestamp="true" version="1">
<airExcludes/>
</airSettings>
<actionScriptSettings version="1"/>
</buildTarget>
</buildTargets>
Quick ref guide
https://my.safaribooksonline.com/9780596155247
https://www.adobe.com/devnet/archive/actionscript/articles/as3_quick_ref.html
https://techgyo.com/_root-in-as3-actionscript-3
https://stackoverflow.com/questions/305320/from-as2-to-as3-what-is-the-equvalent-of-root
CHAPITRE 5 - Animate CC
5.1. Fonctionnement de base
AnimateCC permet de réaliser des animations comme avec flash avec la technologie
canvas d'html5 et javascript. Il inclut le framework createjs qui permetb un
fonctionnement similaire a flash avec des movieClips et des timelines, dans
lequels on peut inclure du code en javascript.
Il est également possible de créer des élement dom html5 pour les superposer sur
le canvas, et de pouvoir les utiliser dans la scene. Cependant il faudra une
gestion particuliere de ces élement car il ne se comporterons pas comme un
movieClip.
Pour importer des fichiers js, le mieu est d'écrire le code suivant sur la 1 ère
image de la scene:
// What I do is adding all my JS utilities to the html on-the-fly from Animate with appenChild
function loadScripts(urls, idx) {
if (idx == undefined)
idx = 0;
var aUrl = urls.split(',');
if (idx >= aUrl.length)
return;
var url = aUrl[idx];
var body = document.getElementsByTagName('body')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
if (idx+1 < aUrl.length)
{
//Internet explorer
if (script.readyState){ //IE
var callback = function() {
loadScripts(urls, idx+1);
};
script.onreadystatechange = function() {
if (this.readyState == 'complete') {
script.onreadystatechange = null;
callback();
}
}
}
else {
//real browsers
script.onload = function() {
loadScripts(urls, idx+1);
};
}
}
body.appendChild(script);
}
root = this;
loadScripts(
'TextInput.js,'
+ 'image1.js,'
);
Comme dans flash, vous pouvez dessiner une forme et la transformer en movieClip
reutilisable. Dans AnimateCC, ce sont des DisplayObject
Vous pouvez utiliser toute la puissance de javascript. Le mieux étand d'utiliser
les méthodes d'extentions. Par exemple ici une fonction qui parcours tous les
elements pour retrouver le nom d'instance du movieClip. En effet Animate cc ne
renseigne pas bien le name jusqu'a la version 20.0.1 (build 19255)
function initTextInput(sNm, parent)
{
if (!root[sNm].hasOwnProperty('name'))
Object.defineProperty(root[sNm], 'name', {value: "", writable: true});
}
createjs.DisplayObject.prototype.getName = function() {
if (!this.name && this._cacheName === undefined) {
var parent = this.parent;
var keys = Object.keys(parent);
var len = keys.length;
while (--len) {
if (parent[keys[len]] === this) {
this._cacheName = keys[len];
break;
}
}
}
return this.name || this._cacheName;
}
Pour savoir dans quel movieClip on est, on peut utiliser la classe lib
Depuis Animate CC 20.0.2 lib n'est plus accessible
var lib = AdobeAn.getComposition(AdobeAn.bootcompsLoaded[0]).getLibrary();
if (root[sNm] instanceof lib.mcTextInput)
Avec createjs, la gestion des evenements est semblable a flash, chaque movieclip
peut déclencher des evenements click, mouseout, mais pas d'evenement keydown
Pour keydown il faudra passer par le dom html; par l'objet window ou par un
objet input rendu invisible, sur lequel on ajoute des ecouteur d'evenement
keydown et input.
Object.defineProperty(stage, 'focus', {value: null, writable: true});
function windowKeyDownHandler(e) {
for (var i=0; i < root.children.length; i++)
{
if (root.children[i] == stage.focus)
{
if (root.children[i].hasOwnProperty('onKeyDown'))
if (root.children[i].onKeyDown != null)
root.children[i].onKeyDown(ev);
break;
}
}
}
window.addEventListener("keydown", windowKeyDownHandler.bind(root), true);
function _unFocus(ev)
{
stage.focus = null;
}
root.addEventListener("click", _unFocus.bind(root), true);
Il existe un nouvel événement tick, qui est déclenché autant de fois par
secondes que de frames par secondes. Il est tres pratique pour synchroniser
l'element dom avec l'element movieClip
root[sNm].on("tick", mcTextTick.bind(parent));
function mcTextTick(ev)
{
var mc = ev.currentTarget;
}
Certains evenements doivent etre activés
stage.enableMouseOver(30);
réf: doc animateCC
https://edutechwiki.unige.ch/fr/Animate_CC_2015_HTML5_Canvas-_Symboles_et_clips
réf: parcours des elements animateCC
https://community.adobe.com/t5/animate/movieclip-instance-names-not-available-from-name-property-in-html5-canvas/td-p/10769699?page=1&profile.language=fr
réf: jeux 2d avec createjs
https://docs.microsoft.com/fr-fr/windows/uwp/get-started/get-started-tutorial-game-js2d
réf: intro easeljs
http://www.webisn.byethost5.com/js/easeljs/easeljs_intro.pdf
5.2. Etape par etape
https://theblog.adobe.com/step-by-step-html5-ad-creation-with-adobe-animate-cc/
CHAPITRE 6 Three.js
77 millisecondes