21.Pola tekstowe
We Flash-u mamy trzy rodzaje pól tekstowych.
- static text
- dynamic text
- input text
Pole typu static służy jedynie do umieszczania określonego tekstu na scenie.
dla takiego pola można jedynie określić krój tekstu, którym jest dany tekst wyświetlany i jego
pozycję oraz rozmiar – okienko properties.
Pole typu dynamic służy generalnie do wyświetlania wartości zmiennej stowarzyszonej z
danym oknem tekstowym – okienko Var.
Z tym oknem można również stowarzyszyć nazwą, będącą jego reprezentacją w kodzie action
scriptu – pole Instancje name. Można również zdecydować czy okno ma być jedną linią,
wieloma liniami z zawijaniem wierszy czy wieloma liniami bez zawijania wierszy.
Pole typu input test jest wykorzystywane, aby użytkownik mógł wprowadzić do aplikacji
określony tekst, który w zależności od zmiennej, która jest stowarzyszona z danym oknem
będzie interpretowana jako odpowiedni typ zmiennej.
Dla tego pola można dodatkowo ustawić maksymalną ilość wprowadzanych przez
użytkownika znaków – maximum characters oraz można spowodować aby wprowadzane
przez użytkownika znaki były kodowane gwiazdkami – password. Aby ograniczyć znaki,
które użytkownik może wprowadzać do okna należy użyć opcji Charakter...
22. Zmienne
We Flash-u mamy tylko trzy rodzaje zmiennych: liczbowe, tekstowe lub logiczne. W związku
z tym wyrażenia na zmiennych są realizowane kontekstowo.
zmienna1 = 12;
zmienna2 = 2;
zmienna3 = „test”;
zmienna4 = „zmian”;
wynik działania operacji będzie następujący:
zmienna1 + zmienna2 = 14 //zmienna liczbowa
zmienna3 + zmienna4 = „testzmian” //zmienna tekstowa
zmienna2 + zmienna3 = „test2”
//zmienna tekstowa
Aby pozwolić użytkownikowi komunikować się z aplikacją za pomocą zmiennych należy
stworzyć dwa okna tekstowe - pole tekstowe typu input text, w którym użytkownik poda
wartości i dynamic text, w którym użytkownik zobaczy rezultaty.
Można również obrabiać teksty wprowadzone przez użytkownika. Służy do tego obiekt
String
. Jeśli dana zmienna jest typu tekstowego to można na jej rzecz wywoływać metody
klasy String (Tabela poniżej).
Method summary for the String class
Method
Description
Returns the character at a specific location in a string.
Returns the value of the character at the specified index as a 16-bit integer
between 0 and 65535.
Combines the text of two strings and returns a new string.
Returns a string made up of the characters specified in the parameters.
Returns the position of the first occurrence of a specified substring.
Returns the position of the last occurrence of a specified substring.
Extracts a section of a string and returns a new string.
Splits a String object into an array of strings by separating the string into
substrings.
Returns a specified number of characters in a string, beginning at a specified
location.
Returns the characters between two indexes in a string.
Converts the string to lowercase and returns the result; does not change the
contents of the original object.
Converts the string to uppercase and returns the result; does not change the
contents of the original object.
Property summary for the String class
Property
Description
A nonzero-based integer specifying the number of characters in the specified String
object.
Ćwiczenia:
1. wykorzystując funkcję matematyczną Math.sqrt utwórz aplikację liczącą
pierwiastek kwadratowy z liczby podanej przez użytkownika.
2. Wykonaj kalkulator zgodnie z załącznikiem
3. Utwórz aplikację, która liczy długość wprowadzonego tekstu,
4. Utwórz aplikację, która sprawdza wprowadzone hasło i nie jest wrażliwa na
wielkość liter
5. Utwórz aplikację, która sprawdza, czy wprowadzony ciąg znakowy zawiera
określony podtekst.
Wgrywanie zmiennych z zewnętrznego pliku
1. Robimy puste pole tekstowe i ustawiamy we właściwościach:
Nazwa zmiennej -
text
- będzie to nazwa, którą zapiszemy w pliku tekstowym.
2. Robimy guzik, który będzie pobierał nasze zmienne :
on(release) {
loadVariables("text.txt", "_root.varTarget");
}
korzystamy ze składni
loadVariables ("url" , target [, variables])
W polu URL wpisujemy lokację naszego pliku ze zmiennymi w stosunku do naszego pliku
*.swf.
Target
- ustawia nam miejsce w które wgrywamy nasze zmienne - jesli komórka z tekstem
znajduje się wewnątrz MovieClipa lub w innym Levelu musimy to tu ustawić !
Variables
- Ustawia metodę pobierania zmiennych/danych - Don't Send, GET lub POST
Don't Send
- pobiera dane bezpośrednio z naszego pliku
GET
- używamy do malej ilości zmiennych
POST
- wysyła zmienne w oddzielnych header-ach (dobry do wysyłania dużej ilości danych)
Nas na ogół będzie interesować tylko
Don't Send
...
3. Teraz zostało nam już tylko stworzyć plik tekstowy o nazwie podanej w
Load Variables
- w
naszym przypadku będzie "text.txt". W tym pliku wpisujemy wartości naszych zmiennych:
text
= nasza zmienna, tekst czy cokolwiek innego
w naszym przypadku będzie to :
text= Zmienne wgrane pomyślnie !
I gotowe !
Oczywiście musimy pamiętac aby plik ze zmiennymi był w tym samym katalogu co nasz
*.swf - lub też odpowiednio ustawić scieżkę do tego pliku w
Load Variables
. Zastosowanie
tego typu wgrywania zmiennych ułatwia nam update'owanie naszego *.swf - jeśli chodzi o
datę czy zawarty w nim tekst. A przy kombinacji z CGI możemy np. eksportować księgę
gości czy "hall of fame" z gier ...
Tworzenie efektów na tekście
Tworzymy mechanizm wyciągania kolejnych literek oraz przypisywania ich kolejnym
wstawianym klonom symboli, nie zapominając o kontroli długości już wyświetlonego tekstu.
Najpierw jednak tworzymy MovieClip z dynamicznym polem tekstowym w środku o nazwie
zmiennej txt i nadajemy mu linkageName literka, nie zapomnijmy też o włączeniu opcji
embed fonts/all dla pola tekstowego w menu character. Do jego klonów będą ładowane
kolejne literki. Od tego momentu będziemy zajmowali się już tylko i wyłącznie
programowaniem.
Na głównym tajmlajlnie (listwie czasowej) piszemy kod:
i = 0;
h_space = 10;
x = 30;
y = 50;
tekst = "jeszcze jakis inny tekst";
this.onEnterFrame = function() {
this.attachMovie("literka", "lt"+i, i);
clip = this["lt"+i];
clip.txt = tekst.substr(i, 1);
clip._x = i*h_space+x;
clip._y = y;
if (i == tekst.length) {
delete
i;
this.onEnterFrame = undefined;
}
i++
};
W skrócie jak to działa:
Ustawiamy licznik "i" na 0, definiujemy odległość między klipami z zawierające literki
(h_space), współrzędne pierwszego klipu (x i y), oraz tekst który zostanie wyświetlony
(tekst). Następnie przypisujemy zdarzeniu onEnterFrame dla głównego tajmlajnu blok kodu
zawarty w ciele funkcji. Wykonuje on kolejne czynności:
wstawia klon Symbolu z biblioteki, na scenę nadaje mu nazwę oraz głębokość
wyświetlania.
przechowujemy referencje do tego kolnu w lokalnej zmiennej clip
przypisujemy zmiennej pola tekstowego znajdującego się we stawionym klonie
odpowiednią literkę z naszego łańcucha znaków
obliczamy pozycje docelowe x i y dla kolonu
sprawdzamy czy wartość licznika jest równa długości łańcuch czyli czy wyświetlone
zostały wszystkie literki, jeżeli tak kasujemy wartość licznika i usuwamy funkcję ze
zdarzenia onEnterFrame przypisując mu wartość niezdefiniowaną.
Następnie dodajemy do powyższego animację za pomocą skryptu. Dołączymy funkcję
przypisaną zdarzeniu onEnterFrame, ale dla każdego wstawionego klonu, dzięki czemu każdy
będzie się animował od momentu wstawienia go na scenę. Modyfikacje w kodzie zaznaczono
Boldem:
i = 0;
h_space = 10;
x = 30;
y = 50;
tekst = "jeszcze jakis inny tekst";
this.onEnterFrame = function() {
this.attachMovie("literka", "lt"+i, i);
var clip = this["lt"+i];
clip.txt = tekst.substr(i, 1);
clip._x = i*h_space+x;
clip._y = y;
clip._alpha=0
clip.onEnterFrame = function() {
if (this._alpha<100) {
this._alpha
+=
5;
} else {
this.onEnterFrame
=
undefined;
}
};
if (i == tekst.length) {
delete
i;
this.onEnterFrame
=
undefined;
}
i++
};
I cóż się dzieje, najpierw ustawiamy wartość _alpha dla klonu na 0 a następnie przypisujemy
zdarzeniu dla tego klonu blok kodu wykonujący następujące czynności: Jeżeli wartość _alpha
tego(!) klonu (stąd this, odwołujemy się do poziomu klonu a nie głównego tajmlajna) jest
mniejsza od 100 0 zwiększ wartość _alpha o 5; w innym razie (wartość _alpha >= 100) skasuj
(zmień na niezdefiniowane) zdarzenie onEnterFrame dla tego klipu.
Efekt jest taki że każdy wstawiony klon od momentu wstawienia zwiększa swoją wartość
alpha do momentu aż osiągnie ona 100. Wygląda to tak że literki pojawiają się kolejno i stają
się coraz mniej przezroczyste aż do chwili uzyskania zerowej przezroczystości (_alpha=100).
Spróbujmy teraz czegoś bardziej efektownego. Właściwie od tego momentu wszystkie
zmiany będą dotyczyły przede wszystkim definicji zdarzenia onEnterFrame dla klonów.
Powiedzmy że chcemy uzyskać efekt polegający na tym że literki pojawiają się w losowych
miejscach a następnie płynnie zajmują właściwą pozycję, tak jak by z rozsypanych literek
składała się linijka zdefiniowanego przez nas tekstu. Poparzmy jak teraz wygląda kod:
i = 0;
h_space = 10;
x = 30;
y = 50;
tekst = "jeszcze jakis inny tekst";
this.onEnterFrame = function() {
this.attachMovie("literka", "lt"+i, i);
var clip = this["lt"+i];
.substr(i, 1);
clip.txt = tekst
clip.x = i*h_space+x;
clip.y = y;
clip._x=clip.x+(random(100)-50)
clip._y=clip.y+(random(100)-50)
clip.speed=2
clip._alpha = 100;
clip.onEnterFrame = function() {
var
sx=(this._x-this.x)/this.speed
var
sy=(this._y-this.y)/this.speed
this._x-=sx
this._y-=sy
};
if (i == tekst.length) {
delete
i;
this.onEnterFrame
=
undefined;
}
i++
};
Pogrubioną czcionką zaznaczyłem zamieniony fragment kodu. Na czym polegają zmiany.
Poza tym że zmianie uległa całość onEnterFrame dla klonu to zmieniło się oraz pojawiło
nowych klika linijek przed onEnterFrame: Zamiast tak jak poprzednio docelową pozycję x i y
klonu przypisać właściwościom _x i _y przypisujemy je zmiennym o nazwach x i y.
Natomiast _x i _y są liczone na podstawie wartości x i y w ten sposób że do tych wartości są
dodawane losowe liczby. Jak to działa otóż funkcja random() losuje wartość z podanego
przedziału (tu od 0-100) następnie od wylosowanej wartości odejmujemy połowę górnej
granicy czyli 50. Dlaczego tak, ano dlatego że w takim przypadku otrzymamy liczby z
przedziału -50,50 tak więc losowe pozycje wyjściowe będą się znajdowały zarówno poniżej
jak i powyżej punktów docelowych. Dzięki czemu efekt losowego "rozsypania" literek będzie
bardziej przekonujący.
Zajmijmy się teraz zmienionym całkowicie zdarzeniem onEnterFrame. Na początku liczymy
wartości lokalnych zmiennych sx i sy są to wartości o jakie zostanie zmieniona pozycja klonu
(skok). Powstają ona poprzez podzielenie pozostałej aktualnie drogi (po osiach x i y) do
punktu docelowego na ilość odcinków podaną w zmiennej speed. Skok zostaje wykonany o
jeden taki odcinek dla _x i _y.
Co bardziej uważny czytelnik na pewno zauważy następujący fakt: Jeżeli skok odbywa się o
odcinek który jest częścią pozostałej drogi, a ilość odcinków, na które jest ona za każdym
razem dzielona, pozostaje stała, to odległość klonu od punktu do celowego będzie dążyć do
zera ale nigdy nie będzie równa zero. W przypadku tej długości tekstu nie ma to prawie
znaczenia natomiast jeżeli animowali byśmy jego większą ilość, obliczanie przesunięcia które
nie daje już żadnego wizualnego efektu (bo skok odbywa się np. o 0.000002 pixela) znacznie
spowolniło by całość animacji. Problem ten można wyeliminować za pomocą warunku
kasującego onEnterFrame dla klipu po osiągnięciu odpowiedniej bliskości punktu
docelowego.
Teraz zajmiemy się połączeniem pierwszego efektu (pojawianie się przez zmianą
przezroczystości) z tym który właśnie uzyskaliśmy. Z tym że zamienimy losowane
współrzędne wyjściowe klonów na współrzędne pobierane z kursora myszki co da efekt
literek wysypujących się z kursora.
Najpierw zmieniamy linijki w których przypisujemy klonowi losowane wartości _x i _y na:
clip._x=_xmouse
clip._y=_ymouse
clip._alpha = 0;
Oraz zmieniamy wartość początkową _alpha na 0 żeby klip był niewidoczny w momencie
wstawienia go na scenę. Dzięki temu pierwsza pozycja klonu w momencie wstawienia na
scenę będzie taka sama jak pozycja kursora myszki w tym momencie. Teraz zobaczmy jak
wygląda nowa wersja onEnterFrame dla klonu:
clip.onEnterFrame = function() {
var sa=(100-this._alpha)/this.speed
var
sx=(this._x-this.x)/this.speed
var
sy=(this._y
this._alpha+=sa
-this.y)/this.speed
this._x-=sx
this._y-=sy
};
Skok wartości _alpha jest liczony w taki sam sposób jak w przypadku _x i _y.
Idąc dalej tym śladem zanimujmy inne właściwości klonu jak np.: _rotation, _xscale i
_yscale, żeby wzbogacić animacje.
i = 0;
h_space = 10;
x = 30;
y = 50;
tekst = "jeszcze jakis inny tekst";
this.onEnterFrame = function() {
this.attachMovie("literka", "lt"+i, i);
var clip = this["lt"+i];
clip.txt = tekst.substr(i, 1);
clip.x = i*h_space+x;
clip.y = y;
clip._x=clip.x+(random(100)-50)
clip._y=clip.y+(random(100)-50)
clip._xscale=random(700)+100
clip._yscale=random(700)+100
clip._rotation=random(220)+50
clip.speed=4
clip._alpha = 0;
clip.onEnterFrame = function() {
var
sa=(100-this._alpha)/this.speed
var
sx=(this._x-this.x)/this.speed
var
sy=(this._y-this.y)/this.speed
var ssx=(this._xscale-100)/this.speed
var
ssy=(this._yscale-100)/this.speed
var
sr=(this._rotation)/this.speed
this._alpha+=sa
this._x-=sx
this._y-=sy
this._xscale-=ssx
this._yscale-=ssy
this._rotation-=sr
};
if (i == tekst.length) {
delete
i;
this.onEnterFrame
=
undefined;
}
i++
};
Całość onEnterFrame dla głównego tajmlajnu z zaznaczonymi miejscami modyfikacji
wygląda jak powyżej. Efekt jest zdecydowanie ciekawszy manipulując parametrami można
osiągnąć dużą różnorodność efektów. Jednym ze sposobów uzyskania jeszcze ciekawszej i
bardziej złożonej animacji jest wprowadzenie do obliczeń pozycji funkcji
trygonometrycznych.
i = 0;
h_space = 10;
x = 30;
y = 50;
tekst = "jeszcze jakis inny tekst";
this.onEnterFrame = function() {
this.attachMovie("literka", "lt"+i, i);
var clip = this["lt"+i];
clip.txt = tekst.substr(i, 1);
clip.x = i*h_space+x;
clip.y = y;
clip.speed=7
clip._alpha = 0;
clip.i=1
clip.range=250
clip.onEnterFrame = function() {
var
sa=(100-this._alpha)/this.speed
this.i++
this._alpha+=sa/2
this.range*=0.89
this._x=Math.sin(this.i/this.speed*2.5)*this.range+this.x
this._y=Math.cos(this.i/this.speed*2.5)*this.range+this.y
this._xscale=Math.sin(this.i/this.speed)*this.range+100
this._yscale=Math.cos(this.i/this.speed)*this.range+100
this._rotation=Math.sin(this.i/this.speed*3)*this.range
};
if (i == tekst.length) {
delete
i;
this.onEnterFrame = undefined;
}
i++
};
Można na przykład zrobić to w powyższy sposób. Co właściwie dają nam funkcje
trygonometryczne. Ich główną zaletą jest to że dla rosnących liniowo argumentów zwracają
okresowo powtarzające się wartości z przedziału od -1 do 1. Warto dodać też że jeżeli dla
tego samego rosnącego argumentu będziemy liczyć _x i _y używając odpowiednio sin i cos
(lub odwrotnie) o trzymamy ruch kołowy o po okręgu o promieniu 1 wystarczy więc
pomnożyć wynik przez np. 10 by otrzymać ruch po okręgu o promieniu 10. Dodając lub
odejmując od otrzymanych wyników kolejno np. 100 i 20, umieścimy środek okręgu w
punkcie 100,20. Na tego rodzaju użyciu funkcji trygonometrycznych opiera się powyższa
animacja. Z tą różnicą że promień maleje dążąc do zera w związku z czym ruch odbywa się
de facto nie po okręgu a po torze spiralnym, którego środkiem jest punkt docelowy
poszczególnego klipu. Dla przykładu zajmijmy się właściwością _x klipu. Powstaje ona w
następujący sposób:
Liczymy wartość sinusa dla rosnącego licznika ("i") danego klipu, aby zmiany były
łagodniejsze (dłuższy okres funkcji sinus) "i" mnożymy *2.5, następnie otrzymaną wartość
mnożymy przez malejącą wartość "range" która spełnia rolę promienia. Na koniec dodajemy
docelową wartość x. Ponieważ promień maleje i dąży do zera więc _x w końcu osiągnie
wartość zbliżoną do x czyli docelową. To samo robimy by otrzymać _y z tą różnica że
używamy funkcji cosinus, aby jak już wspomniałem uzyskać ruch po torze spiralnym. Na tej
samej zasadzie opiera się animacja pozostałych wartości, różnią się tylko poszczególne
wartości liczbowe które wpływają na efekt wizualny.
Zachęcam do eksperymentowania ze skryptem, ułatwi to zrozumienie zasady jego działania,
oraz pozwoli na tworzenie własnych nowych rozwiązań.
Ćwiczenia:
Zaimplementuj
powyższe przykłady oraz postaraj się napisać aplikację pozwalającą na
zarządzanie efektami napisów. Coś w rodzaju: