Banner z obietnicami
Jeżeli należysz do naszego klubu superbohaterów, musisz go chwalebnie reprezentować. Powinieneś byś silny, wytrwały i nieugięty, jak każdy superbohater. Tak przynajmniej może się wydawać. Prawda jest jednak taka, że nawet najlepsi z nas czasami potrzebują wsparcia. Szczególnie ostatnie lata, lockdown, inflacja i wiele podobnych rzeczy każdego z nas może przemielić jak maszynka do mięsa.
Czy wiesz, że w obecnych czasach co piąte dziecko ma problemy psychiczne, a w naszym kraju mężczyźni znajdują się czołówce samobójstw w Europie? Można by tak wymieniać i wymieniać. Czasy nie są za miłe, a my nie jesteśmy niezniszczalni.
Gdzieś w początkowych rozdziałach wspomniałem tobie o pewnej najważniejszej rzeczy. Dalej jestem zdania, że jest to rzecz najważniejsza w programowaniu. Ale jak to mówi przysłowie - "w zdrowym ciele zdrowy duch". Ale i bez zdrowego ducha ciało nie może być zdrowe. I w tym miejscu wkraczają współtowarzysze superbohaterów - trenerzy, dietetycy ale i psychoterapeuci. Wszyscy oni będą mieli coraz więcej do zrobienia.
W poniższym tekście zajmiemy się stworzeniem przykładowego baneru. Osobiście nie jestem jakimś ekspertem od reklamy. Ale... Ostatnimi czasy coraz częściej męczę AI o różne tematy, tak i tym razem pogadałem sobie z nią o powyższych problemach. To z kolei wydało mi się ciekawym pomysłem na stworzenie naszego dzieła.
W każdym razie będziemy tworzyć takie cacko:
Banner jest prezentacją oryginalnej rozmowy, jaką odbyłem z ChatGPT. Żeby ją przedstawić, będziemy potrzebowali kilku "klocków", z których zbudujemy banner. Po pierwsze przyda nam się mechanizm, który będzie służył do wypisywania tekstów litera po literze. Po drugie musimy zaanimować przejścia między kolejnymi wypowiedziami - tu zastopować, tam płynnie przejść itp.
Naszą pracę podzielmy na kilka punktów:
napisanie klasy do wypisywania tekstów
dodatkowe funkcje do animacji i spowalniania
realne odpytywanie AI?
Klasa TypeWriter
Naszą pracę rozpoczniemy od stworzenia klasy TypeWriter.
Zasada działania naszej maszyny piszącej będzie całkiem prosta. Całe pisanie będzie składało się z wykonywanych po sobie kolejnych akcji, które za pomocą funkcji będziemy odkładać do osobnej tablicy.
export class TypeMachine {
#actions = []; //tablica akcji
#text = ''; //tekst który aktualnie wypisujemy
#count = 0; //dodatkowa zmienna - przyda się do liczenia którą literę wypisujemy
constructor() {
//na razie pusty
}
}Wszystkie powyższe zmienne dzięki poprzedzeniu je znakiem # stworzyliśmy jako prywatne. W konstruktorze tworzymy opcje naszej maszyny - działanie takie samo jak w innych naszych projektach.
Funkcja write
Jak u Hitchcocka. Zaczynamy od najcięższej rzeczy czyli funkcji write().
Każda odkładana akcja będzie obietnicą na której wykonanie spokojnie poczekamy.
Po pierwsze dokładamy tekst, który za chwilę za pomocą funkcji typeText() i interwału będziemy wypisywać.
Tekst wypisywany będzie za każdym razem od jego początku do zmiennej #count, którą zwiększamy w interwale. Przykładowo:
Jeżeli ktoś odpali naszą funkcję z czasem 0, cały przekazany w parametrze tekst od razu wypiszemy dodając do zmiennej #count jego długość. Przyda to się, jeżeli w wypisywanym tekście będziemy chcieli zmienić wygląd za pomocą html.
Tak to będzie działać. Na koniec funkcji zwracamy this czyli samego siebie. Dzięki temu wszystkie funkcje będziemy mogli łączyć w łańcuch tak samo jak w przypadku innych metod dla innych obiektów:
Funkcja typeText
Kolejną metodą, którą napiszemy będzie prywatna funkcja typeText(). Posłuży ona do wypisywania samego tekst. Nasz tekst może być wypisywany w różnych miejscach. Czasami będziemy chcieli wypisać go w konsoli debuggera, a innym razem w kilku częściach baneru na stronie. Nie możemy więc tego zakodować na sztywno. Zamiast tego użyjemy funkcji zwrotnej, którą przekażemy do konstruktora:
Dzięki temu odpowiedni kod przekażemy przy tworzeniu pojedynczej instancji naszej maszyny:
Funkcja pause
Jak przypatrzysz się rozmowie z banera, wypisywanie tekstu nie jest jednolite. W pierwszej wypowiedzi zawahałem się (pauza), wprowadziłem korektę (usunięcie kilku liter), znowu zawahałem się, po czym pisałem dalej.
Zacznijmy od funkcji dodającej możliwość zaczekania z pisaniem kolejnych liter:
Funkcja back
Żeby zasymulować kasowanie tekstu, musimy cofnąć się ze zmienną #count. Posłuży do tego funkcja back():
Funkcja wymaga podania liczby znaków do cofnięcia. Jeżeli zamiast liczby podamy -1, wtedy zacznie kasować wszystkie litery aż do początku.
Możemy też stworzyć dodatkową funkcję pomocniczą, która posłuży do kasowania całego tekstu:
Funkcja runFn
Kolejną funkcją, która nam się przyda, będzie ta, która posłuży do odpalania naszego "customowego" kodu. Podczas pisania tekstu możesz chcieć w pewnej chwili odpalać dodatkowe funkcje - np. podczas cofania kursora może się dodawać jakaś dodatkowa klasa, albo zmieniać tło. Posłuż do tego funkcja runFn():
Funkcja start
Ostatnią funkcją będzie start(), która posłuży do wystartowania całego pisania.
Nasza klasa jest gotowa :). Przykładowe jej użycie może mieć postać:
Animowanie dymków rozmowy
Pierwszy krok mamy załatwiony. Przejdźmy więc do kolejnych, czyli animowania całej rozmowy.
Zacznijmy od pobrania odpowiednich elementów i utworzenia podstawowych zmiennych:
Nasza rozmowa składa się z 4 dymków, które mieszczą się w elemencie .banner-inner. Pokażmy pierwszy dymek, po czym użyjmy w nim naszej piszącej maszyny. Do pokazania dymku moglibyśmy użyć biblioteki GreenSock, która nie tylko ma praktycznie nieograniczone możliwości animacji, ale i jest bajecznie prosta w użyciu:
Mega wygodna sprawa (polecam!)...
W naszym przypadku jednak chcemy tylko animować zwykłe opacity. Możemy to zrobić samym CSS i dodaniem odpowiedniej klasy dla elementu. Ja skorzystam tutaj z metody animate.
Trochę więcej kodu, ale mniej do ściągnięcia danych przez użytkownika. Będziemy chcieli pokazywać resztę dymków, dlatego kod odpowiedzialny za animację wynieśmy do osobnej funkcji:
Po pokazaniu dymka, chcemy chwilkę odczekać zanim tekst zacznie się pisać, dzięki czemu efekt będzie bardziej realny. Napiszmy dodatkową funkcję służącą do opóźniania dalszego kodu:.
A następnie dodajmy samo pisanie tekstu korzystając z naszej klasy:
Drugim dymkiem będzie odpowiedź ChatGPT. Żeby to zasygnalizować, dodamy do dymku dodatkową klasę .is-wait, która za pomocą odpowiedniego stylowania stworzy dodatkowy element ::before, który będzie symulował mrugający kursor:
Pozostaje napisać funkcję pokazującą drugi dymek:
i podobnie pozostałe dwa dymki:
Demo masz na początku strony...
Jedyną rzeczą, którą w nim dodałem, do odpalanie całej animacji w momencie, gdy baner zacznie wjeżdżać na ekran.
Bonus - odpowiedzi z ChatGPT
W powyższym kodzie teksty były wpisane na sztywno (ale wiedz, że to są praktycznie oryginalne teksty).
W ramach testu możemy pokusić się o użycie na naszym banerze realnych odpowiedzi, które uzyskamy bezpośrednio od ChatGPT.
Po pierwsze musisz wejść na stronę https://platform.openai.com/docs/api-reference i w prawym górnym rogu się zarejestrować. Po zarejestrowaniu znowu na tej same stronie przy twoim awatarze (prawy górny róg) otwórz menu i z opcji wybierz "View API keys". Wygeneruj nowy klucz. Będziesz musiał go użyć przy połączeniu z API.
Połączenie zrobimy za pomocą zwykłego fetch według opisu ze strony api. W naszym przypadku musimy zmienić tylko funkcje, gdzie odpowiada AI.
Czy to się nadaje na realny baner? Nie za bardzo. Poniżej nagrałem ci film z pierwszego lepszego testu. Ogólnie jest nieźle, ale w poniższym przypadku dostałem odpowiedzi po polsku, po 3 próbie część przyszła po angielsku. Podejrzewam, że trzeba by się przyjrzeć parametrom, które udostępnia api. Ważniejsze jednak jest to, skąd mam wiedzieć, w jakim humorze AI będzie za kilka dni?. A jeżeli zacznie wrzucać ludzkości? Wtedy akurat najlepiej zacząć przenosić swoje kodowanie do schronu, no ale i nasz baner by ucierpiał...
Last updated