Anzeige
Tutorialbeschreibung

Ein kleines Text- Wechselspiel

Ein kleines Text- Wechselspiel

Ich möchte Euch hier beschreiben wie ein solcher Effekt erstellt wird:
www.sd-fx.de/psdtuts/statikfiles/textspielerei.swf

U.A. geht es in diesem Tut um:
createEmptyMovieClip(), createTextField(), TextFormat(), setInterval,charAt(), einem bisschen Ablaufspielerei und einigen kleineren AS Tricks.
Das komplette Tutorial besteht ausschliesslich aus Actionscript, somit gibt es leider keine Bilder die ich anhängen könnte. Ich könnte Euch ein Bild vom fertigen Effekt anhängen, da dieser aber nur auf einen einzelnen Satz einfluss nimmt könnte ich zwar einen Screen dieses Satzes machen (hab ich auch gemacht), den Satz 'ich bin ein Text' zu einem Screen zu machen und hier aufzuspielen kam mir dann aber doch ein bisschen seltsam vor ;). Ausserdem tritt der Effekt nur in unregelmässigen Intervallen auf, und die Änderung im richtigen Moment zu "knipsen" ist gar nicht so einfach. Schaut Euch also lieber das Ergebniss unter dem obigen Link an.
Voraussetzung für diesen Workshop ist eine Flashversion die AS2 (>= MX2004) unterstützt und ein bisschen Interesse an Actionscript.
Eigentlich kann jeder diesen Workshop mitmachen, richtig verstehen wird ihn aber wohl eher  der etwas versiertere Flasher.


Vorwort:

Sodele, nachdem das erste so gut ankam, hier mein zweites Tut. Achtung: Dies ist um Längen komplizierter als das Erste.

Eigentlich wollte ich ja erst einen kleinen *.flv player oder eine Flashkennung mit Euch basteln, jetzt bin ich aber gestern über einen Thread im Forum gestolpert, den 'DanielAndres' aufgemacht hat. Das Thema ist mir sofort als potentielles Tutorial ins Auge gesprungen und selbiges habe ich dann auch daraus gemacht. Hier also erstmal das fertige Ergebniss, Player und  Flashkennung folgen in den nächsten Tagen.

Der Link zum entsprechenden Forumsthread:
www.psd-tutorials.de/modules/Forum/69_flash-technische-fragen/26232-benoetige-hilfe-bei-text-animation.html#post332530

Viel Spass also mit dem folgenden Workshop.



Schritt 1 'Jeder Weg beginnt mit Variablen':

Wie Ihr dem Forumsthread und dem Beispiel entnehmen könnt haben wir also einen Text der auf der Bühne steht. Alles in allem erstmal nichts besonderes, aber bei näherer Betrachtung stellen wir fest, das sich ab und an einzelne Buchstaben in diesem Text für ganz kurze Zeit ändern.
Erstellen wir also erstmal den Text, den wir nachher auf der Bühne sehen wollen. Nennen wir den String 'mystring' und füllen wir Ihn mit Text:


var mystring:String = 'Ich bin ein Text und ich steh hier halt so rum.';


Von diesem Text sollen sich also einzelne Buchstaben in andere verwandeln. Also erstellen wir uns einen weiteren String, der die 'Ersatz'- Zeichen enthält. Nennen wir ihn 'ersatzstring'. Bitte beachtet das Ihr in diese 'Pattern' keine Anführungszeichen einfügt, oder, wenn Ihr das tut, das Ihr diese ausklammert.
 

var ersatzstring:String = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789()/&%$§"!*:;';


Jetzt erstellen wir uns noch 3 weitere Variablen:

var maxchange:Number =5;
var maxdauer:Number = 3;
var count:Number = 0;

'maxchange' gibt an wie oft sich der entsprechende Buchstabe pro Durchlauf maximal ändern soll, bevor er wieder der 'original' Buchstabe wird.
'maxdauer' ist die Zeit in Sekunden, die es maximal braucht bis der Effekt das nächste mal auftritt.
'count' ist eine Hilfsvariable die wir in einer der folgenden Methoden hochzählen lassen und mit maxchange vergleichen. Darauf werde ich aber später noch näher eingehn.

Schritt 2 'Die Textformate':

Wie Ihr seht sind die einzelnen Buchstaben des Textes unterschiedlich formatiert. Um in Flash ein (dynamisches) Textfeld formatieren zu können gibt es TextFormat 'Objekte'. In ein solches steckt man, ähnlich wie in CSS, sämtliche Formatierungen und weist nachher dem entsprechenden Textfeld nur noch das TextFormat 'Objekt' zu. (ich habe 'Object' hier eingeklammert weil meiner Meinung nach der Begriff Object nicht ganz zutreffend ist, das ist aber eine lange und andere Geschichte)
Erstellen wir also zunächst einmal unser -hmpf- na gut unser 'Object'.

var kleinbuchst:TextFormat = new TextFormat();

Diesem weisen wir auch gleich die Eigenschaften font und size zu

kleinbuchst.font = "Courier";
kleinbuchst.size = 10;

Die Bezeichnung 'kleinbuchst' und die des folgenden 'grossbuchst' sind Leichen aus der Entwicklung diese Scripts. Ich wollte ursprünglich nur alle Grossen Buchstaben umfärben. Da dies aber einer weiteren, recht kniffligen Methode bedurft hätte, die schon fast ein eigenes Tut sein könnte habe ich mich entschieden doch besser nur die jeweils ersten Buchstaben eines Wortes anders zu formatieren. (leider gibt es in Flash keine Überprüfung à la isUpperCase() sondern nur toUpperCase(), oder weiss da jemand mehr als ich?)
Um also die ersten Buchstaben zu formatieren erzeugen wir noch das Object 'grossbuchst' und weisen ihm seine Eigenschaften font, size, bold und color zu:

var grossbuchst:TextFormat = new TextFormat();
grossbuchst.font = "Arial";
grossbuchst.color = 0xFF0000;
grossbuchst.size = 15;
grossbuchst.bold = true;
Schritt 3 'Erstmal überlegen':

So, über das weitere verfahren habe ich lange nachgedacht und schwanke eigentlich immernoch zwischen zwei Varianten. Es gäbe die Möglichkeit jedem Buchstaben einen eigenen Prottypen zuzuweisen, der steuert ob und wann sich ein Buchstabe ändert. Wenn jetzt aber jeder Buchstabe sein eigenes Interval besässe und weiterhin auch noch ein eigenes onEnterFrame, würde ab einer gewissen Textlänge die CPU Auslastung doch deutlich zunehmen. Der Vorteil des protos wäre allerdings das der Effekt bei mehreren Buchstaben gleichzeitig auftreten könnte. Ich habe hier aber eben den etwas übersichtlicheren, Prozessorschonenderen Weg verwendet, der aber eben nur bei jeweils einem Buchstaben auftritt.
Des Weiteren gäbe es sicher die Möglichkeit den ganzen Text in einem Textfeld zu belassen, was uns auch einen Zeilenumbruch ermöglichen würde und den Text via css zu formatieren. Auf die Verwendung von Flash mit css möchte ich in einem späteren Tutorial eingehn und deswegen also die folgende Variante:

Um jeden Buchstaben einzeln anzusprechen ist es in diesem Fall ratsam die einzelnen Buchstaben des strings 'mystring' in ein Array zu packen, die einzelnen Elemente in einzelne Clips zu packen und dann zu plazieren. So können wir einfach über einen Index die einzelnen Elemente ansprechen und abändern.
Gehn wir also Schritt für Schritt wie folgt vor.
Zunächst schreiben wir eine Methode die den Text zerlegt und in ein Array packt:

function wandeln(derstring) {
    var txtArr:Array = new Array();
    for (var i:Number = 0; i<derstring.length; i++) {
        txtArr.push(derstring.charAt(i));
    }
    return txtArr;
}
Warum ich hier den string 'mystring' nicht direkt in der Methode anspreche sondern ihn als Parameter übergebe wird später klar.
charAt(i) funktioniert  wie der Index in einem Array (array[i]) und gibt den entsprechenden Buchstaben im string 'mystring' unter dem Index i zurück. diesen stopfen wir in das Array 'txtArray'
Mit trace(wandeln(mystring) ) könnt Ihr Euch anschaun wie unser Array jetzt aufgebaut ist.

Schritt 4 'Der erste Aufbau':

Um jetzt nicht nur im Ausgabefenster, sondern auch auf der Bühne etwas zu sehen baun wir uns also eine Methode, die die einzelnen Elemente aus userem Array in MC packt und diese auf der Bühne plaziert. Nennen wir sie 'aufbau':

function aufbau(dasarray):Void {
    for (var i:Number = 0; i<dasarray.length; i++) {
        if (dasarray[i-1] == " " || i == 0) {
            var container:MovieClip = this.createEmptyMovieClip("container", i);
            var label:TextField = container.createTextField("label", this.getNextHighestDepth(), (0+10*i), 0, 20, 20);
            label.text = dasarray[i];
            label.setTextFormat(0, 1, grossbuchst);
        } else {
            var container:MovieClip = this.createEmptyMovieClip("container", i);
            var label:TextField = container.createTextField("label", this.getNextHighestDepth(), (0+10*i), 5, 20, 20);
            label.text = dasarray[i];
            label.setTextFormat(0, 1, kleinbuchst);
        }
    }
}
Zur Erklärung:
Wir empfangen in unserer Methode ein Array ('dasArray'). Dies wird als Parameter bei Aufruf der Methode übergeben und besteht entweder aus unserem ursprünglichen Array was uns die Methode 'wandeln' zurück gibt oder aus unserem abgeänderten Array, welches wir in einem der nächsten Schritte  in der Methode  'machmal'  erstellen.
Der Aufbau der for- schleife sollte klar sein, solange i=0 und niedriger als die Länge unseres Arrays ist mach folgendes:

In der  eingeschachtelten if Bedingung entscheiden wir :  ist i=0,  also  sprechen wir das Erste Element an oder  ist  das Vorhergehende Element im Array ein Leerzeichen dasarray[i-1] == " ", dann trifft die Bedingung zu, ansonsten wird else ausgeführt.
In dieser If Bedingung passiert dann folgendes:
1. erstellen wir einen neuen, leeren MC, benennen ihn als Container und setzen ihn auf die Tiefe i. Hier würde getNextHighestDepth() nicht funktionieren, da wir später wollen, das der erstellt MC wieder überschrieben wird.
2. erstellen wir im MC container ein Textfeld, nennen es Label und geben Ihm eine Tiefe (diesmal können wir getrost NextHighestDepth nehmen), eine Position x und y sowie eine Breite und eine Höhe. Die position x lassen wir anhand von i und einer geschätzen Breite der entsprechenden MCs (10) berechnen '0+10*i'
3. bestücken wir das Textfeld 'label' mit dem Element was im Array 'dasarray' an i-ter Position liegt.
4 weisen wir dem Textfeld die Formatierung zu. 'label.setTextFormat(0, 1, grossbuchst);' 0 und 1 gibt an, das die Formatierung vom nullten bis zum ersten Buchstaben zutreffen soll.

Selbiges passiert fast genau so im else. Hier sind nur zwei kleine Unterschiede zu beachten:
1. wir weisen ihm nicht die Formatierung 'grossbuchst' sondern eben 'kleinbuchst' zu
2. wir versetzen die position y um 5 Pixel. Dies tun wir, weil 'grossbuchst' eine Grössere size hat als 'kleinbuchst' und uns ansonsten der Text ein wenig komisch formatiert vorkäme.

Mit 'aufbau(wandeln(mystring));' in einer neuen Zeille könnt Ihr Euch anschaun wie das Ergebniss ohne Effekt auf der Bühne aussieht. Diese Zeile könnt Ihr getrost stehen lassen, ich werde sie aber am Ende des Codes noch einmal eintragen. Später werden wir noch eine weitere Methode aufrufen und der Übersicht halber lege ich den Aufruf beider Methoden lieber zusammen. Ihr seht das wir 'aufbau' aufrufen, und das Array übergeben welches uns 'wandeln' zurückgibt wenn wir ihm 'mystring' übergeben.

So, von nun an wird es noch ein bisschen komplizierter. Ich glaube wir sollten erstmal ein kleines Päuschen einlegen und uns einen Kaffee gönnen.

Schritt 5 'Der eigentliche Effekt':

Wie sagte einst mein Physiklehrer immer: 'Herrschaften, laßt Euch nicht erschlagen'. Hätte nie gedacht das ich diesen, sorry Sch*** Spruch jemals selber verwende. Der folgende Teil wird jetzt recht happpig, aber ruhig bleiben, ich will versuchen das kommende so gut es geht zu erklären.

Zunächst einmal die folgenden 3 Methoden am Stück:


function machmal():Void {
    clearInterval(myinterval);
    var stelle:Number = random(mystring.length);
    this.onEnterFrame = function() {
        wechselletter = ersatzstring.charAt(random(ersatzstring.length));
        var temparray:Array = wandeln(mystring);
        temparray[stelle] = wechselletter;
        aufbau(temparray);
        count++;
        if (count>=maxchange) {
            count = 0;
            timer(random(maxdauer*1000));
            delete this.onEnterFrame;
            aufbau(wandeln(mystring));
        }
    };
}
function timer(dauer) {
    myinterval = setInterval(this, "machmal", dauer);
}

Noch die beiden Aufrufe:

aufbau(wandeln(mystring));
timer(random(maxdauer*1000));

Und jetzt die Erklärungen:
Gehn wir mal eins nach dem anderen durch, so wie der Ablauf das auch tut.

Die beiden Aufrufe:
Wie schon erwähnt (und weiter oben gemacht) lassen wir mit 'aufbau(wandeln(mystring));' unseren Text das erste Mal auf der Bühne erscheinen.
Der Aufruf 'timer(random(maxdauer*1000));' spricht die Methode 'timer' an und übergibt eine Zahl die wir in 'timer' als 'dauer' empfangen. Diese Dauer ist ein Zufallswert zwischen 0 und unserer 'maxdauer' *1000. Wir multiplizieren mit 1000 weil wir diese Zahl in unserer Methode timer an ein Interval weitergeben. Da ein Interval mit Millisekunden arbeitet , wir aber unter 'maxdauer' nur eine 3 angegeben haben würde der Effekt  nur alle 3 Millisekunden auftreten. Deswegen multiplizieren wir mit 1000, da eine Sekunde aus 1000 Millisekunden besteht . Der Effekt sollte also irgendwann zwischen 0 Millisekunden und 3 Sekunden passieren.

Die Methode 'timer':

Wir empfangen also, wie bereits beschrieben unsere Dauer als Parameter.
das einzige was timer noch tut, ist ein Interval zu starten und Ihm einen Identifier zuzuweisen. Der Identifier in diesem Fall ist 'myinterval ' über ihn können wir das Interval ansprechen und ggf. löschen.
Ausserdem ruft das Interval nach Ablauf von 'dauer' die Methode 'machmal' auf.

Die Methode 'machmal':

-Das erste was wir in 'machmal' tun ist das eben beschriebene Interval zu löschen. Dies machen wir weil wir ja nicht wollen, das während unseres Effekt selbiger unterbrochen wird. (die Chance ist bei maximal 5 onEnterFrames recht gering, aber sicher ist sicher)

-Dann ermitteln wir per Zufall eine Zahl, Diese Zahl ist der später verwendete Index an dem der Buchstabe steht den wir wechseln lassen möchten. '  var stelle:Number = random(mystring.length);'

-Alles weitere soll per OnEnterFrame stattfinden, also 'this.onEnterFrame = function() {'

- Als erstes in diesem onEnterFrame ermitteln wir per Zufall einen Buchstaben aus unseren 'ersatzstring' . Wir nennen die Variable des Buchstabens 'wechselletter '
'wechselletter = ersatzstring.charAt(random(ersatzstring.length));'

- Dann lassen wir uns von der Methode 'wandeln' wieder das Array ausgeben welches die Methode aus 'mystring' macht und geben der Rückgabe die Bezeichnung  'temparray'  'var temparray:Array = wandeln(mystring);'

- Dann setzen wir anstatt des Elementes an der Position 'stelle' in unserem Array 'temparray' unseren eben ermittelten 'wechselletter' ' temparray[stelle] = wechselletter;' Jetzt haben wir also quasi ds selbe array welches uns wandeln zurückgeben würde, nur das ein Zufälliger Buchstabe in diesem Array verändert wurde

-Jetzt rufen wir die Methode 'aufbau' auf und übergeben ihr unser 'temparray'. 'aufbau' überschreibt also Blitzschnell unseren 'Text' auf der Bühne und ersetz ihn durch den leicht abgeänderten

- Um jetzt noch herauszufinden wie oft das passiert lassen wir die ganz zu Anfang erstellte Variable 'count' hochzählen.
count++;

-in der folgenden if-Bedingung prüfen wir ob unser maximalwert für count 'maxchange' schon erreicht ist. Wenn das der Fall ist, dann löschen wir den onEnterFrame, setzen count wieder auf 0, rufen timer() erneut auf und lassen aufbau() wieder den Originaltext herstellen.

-Tja, und damit beginnt der ganze Ablauf von vorne.


Schritt 6 'Der komplette Code':

Zur Kontrolle habe ich Euch hier nocheinmal den gesamten Code aufgelistet:

// Variablen
var mystring:String = 'Ich bin ein Text und ich steh hier halt so rum.';
var ersatzstring:String = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789()/&%$§"!*:;';
var maxchange:Number = 5;
var maxdauer:Number = 3;
var count:Number = 0;
// Textformate
var kleinbuchst:TextFormat = new TextFormat();
kleinbuchst.font = "Courier";
kleinbuchst.size = 10;
var grossbuchst:TextFormat = new TextFormat();
grossbuchst.font = "Arial";
grossbuchst.color = 0xFF0000;
grossbuchst.size = 15;
grossbuchst.bold = true;
// Methoden
function wandeln(derstring) {
    var txtArr:Array = new Array();
    for (var i:Number = 0; i<derstring.length; i++) {
        txtArr.push(derstring.charAt(i));
    }
    return txtArr;
}
function aufbau(dasarray):Void {
    for (var i:Number = 0; i<dasarray.length; i++) {
        if (dasarray[i-1] == " " || i == 0) {
            var container:MovieClip = this.createEmptyMovieClip("container", i);
            var label:TextField = container.createTextField("label", this.getNextHighestDepth(), (0+10*i), 0, 20, 20);
            label.text = dasarray[i];
            label.setTextFormat(0, 1, grossbuchst);
        } else {
            var container:MovieClip = this.createEmptyMovieClip("container", i);
            var label:TextField = container.createTextField("label", this.getNextHighestDepth(), (0+10*i), 5, 20, 20);
            label.text = dasarray[i];
            label.setTextFormat(0, 1, kleinbuchst);
        }
    }
}
function machmal():Void {
    clearInterval(myinterval);
    var stelle:Number = random(mystring.length);
    this.onEnterFrame = function() {
        wechselletter = ersatzstring.charAt(random(ersatzstring.length));
        var temparray:Array = wandeln(mystring);
        temparray[stelle] = wechselletter;
        aufbau(temparray);
        count++;
        if (count>=maxchange) {
            count = 0;
            timer(random(maxdauer*1000));
            delete this.onEnterFrame;
            aufbau(wandeln(mystring));
        }
    };
}
function timer(dauer) {
    myinterval = setInterval(this, "machmal", dauer);
}
aufbau(wandeln(mystring));
timer(random(maxdauer*1000));



Schritt 7 'Nachwort':

So, damit hätten wir es also geschafft. Ob wohl noch alle dabei sind?
Ich bin mir durchaus bewusst das dies ein Tutorial der etwas komplizierteren Art war. Ich hoffe ich habe es dennoch so verständlich wie Möglich formuliert. Solltet Ihr Probleme bei diesem Tut haben, bin ich gerne hier und im Forum bereit Euch zu helfen.
Ich hoffe Ihr habt ein bisschen was gelernt und hattet ein bisschen Spaß damit.
Ich verspreche auch hoch und heilig, das das nächste Tut wieder ein bisschen leichter wird!

LG B2B

PS.: Bei der Erstellung dieses Tuts sind mir ein paar Dinge aufgefallen die man mit Sicherheit hätte schöner machen können. Ich denke wenn Euch diese Dinge auch aufgefallen sind seid Ihr so gut, das Ihr dieses Tut eigentlich gar nicht hättet machen brauchen. Dumm nur das man sowas immer erst am Ende erfährt, gelle ;)

Kommentare
Achtung: Du kannst den Inhalt erst nach dem Login kommentieren.
Alternative Portrait
-versteckt-(Autor hat Seite verlassen)
  • 11.05.2007 - 15:50

is okay. danke .

Portrait von sonje
  • 10.05.2007 - 21:47

Kenne mich mit Flash leider (noch) nicht so aus, vielen Dank für das Tutorial.

Portrait von DanielAndres
  • 10.05.2007 - 19:27

Exakt wie versprochen. ;)

Vielen Dank

Portrait von gilla
  • 10.05.2007 - 17:24

Nicht schlecht das so viel AS eingebaut ist.
Finde es gut wenn mehr Tut mir Script hier kommmen.
Aber bei diesem muss ich irgendwie sagen das mir der Effekt nicht gefällt.
Wo soll man das sinnvoll verwenden könne.
Also ich denke mit Text sicherlich nicht so praktisch, aber naja muss jeder selber wissen.

Portrait von bad2be
  • 11.05.2007 - 02:59

Grüss Dich
Werde als nächstes wahrscheinlich den alten Arcade Klassiker 'Asteroids' nachbaun, wird auch schwer Scriptlastig, aber eher am Alltagsgebrauch. Vielleicht ist das ja eher was für Dich. Das Tut wird, denk och, Ende nächster Wcoche fertig.

Gruss B2B

Alternative Portrait
-versteckt-(Autor hat Seite verlassen)
  • 10.05.2007 - 08:56

Ist wirklich nicht für Einsteiger.

Portrait von dapoldi
  • 10.05.2007 - 08:40

Also vielen Dank für deine Mühe, bin in Flash totaler Anfänger, aber das sieht interessant aus, muss ich probieren.

x
×
×