Am iubit DragonBall Z în copilărie și încă o iubesc ca adult.
Printre numărul ridicol de transformări, originalul Super Saiyan rămâne preferatul meu.
Nimic asemănător originalului
Îmi place, de asemenea, RxJS cu cât mă ridic mai mult cu el, așa că de ce să nu le combin pe acestea două pentru confruntarea supremă?
Conţinut
Să mergem Super Saiyan
Cu patru foi sprite și un pic de HTML, CSS și RxJS, putem recrea această transformare legendară!
Asta vom face. Emoționant, nu ?! ?
Înființat
Totul este pornit GitHub-ul meu.
cd ./wherever-you-want
git clone [https://github.com/yazeedb/dbz-rxjs](https://github.com/yazeedb/dbz-rxjs)
cd dbz-rxjs
Deschis index.html
în browserul dvs. preferat și proiectul în editorul de text preferat, și sunteți gata de plecare!
Nu npm install
e azi?
Și înainte, voi folosi acronimul „SSJ” în loc de „Super Saiyan” pentru scurtă durată.
Prima zi de antrenament
Veți observa că Goku se mișcă deja. Întrucât ne concentrăm pe RxJS, vom defecta doar punctul de plecare al proiectului.
Iată HTML-ul principal:
<div id="root">
<div id="meter-container">
<span>Hold any key to POWER UP!</span>
<div id="meter"></div>
</div>
<div id="sprite" class="base"></div>
</div>
Fundul div
are class="base"
, care corespunde acestui CSS:
.base,
.ssj {
width: 120px;
height: 250px;
animation: stand 0.8s steps(2) infinite;
}
.base {
background-image: url('img/goku-standing-sheet.png');
}
Aceasta setează lățimea, înălțimea și animația în picioare a lui Goku.
Dacă te uiți la foile sale sprite de bază / ssj, sunt două poziții diferite și trecem între ele la fiecare 0,8 secunde.
Comutarea este gestionată spre partea de jos a style.css
:
@keyframes stand {
from {
background-position: 0px;
}
to {
background-position: -255px;
}
}
Același lucru pentru pornire:
@keyframes powerup {
from {
background-position: 0px;
}
to {
background-position: -513px;
}
}
Vom acoperi contorul de alimentare când îl vom manipula.
Stăpânirea elementelor DOM
index.html
include deja RxJS@6.2.1
prin CDN, deci ești acoperit.
În app.js
, să captăm elementele DOM care ne interesează:
const sprite = document.querySelector('#sprite');
const meterContainer = document.querySelector('#meter-container');
const meter = document.querySelector('#meter');
Prefer să fiu alias document.querySelector
deci folosirea lui nu-mi provoacă dureri la încheietura mâinii.
const $ = document.querySelector.bind(document);**
const sprite = $('#sprite');
const meterContainer = $('#meter-container');
const meter = $('#meter');
Apoi, vom crea un main
funcția și numiți-o imediat.
// ...
const main = () => {
// do something
};
main();
Pornirea
Aici este main
primul fragment de cod:
const main = () => {
const { fromEvent } = rxjs;
const begin = fromEvent(document, 'keydown');
const end = fromEvent(document, 'keyup');
};
Goku ar trebui să se aprindă atunci când o tastă este ținută apăsată și să se oprească atunci când cheia este eliberată. Putem folosi fromEvent
operator pentru a crea două observabile:
-
begin
: Notifică când utilizatorul apasă o tastă jos. -
end
: Notifică ori de câte ori utilizatorul sa mergem a unei chei.
Atunci putem Abonati-va la aceste emisii și acționează asupra lor. Pentru a obține animația de putere, dați sprite
powerup
numele clasei.
begin.subscribe(() => {
sprite.classList.add('powerup');
});
Funcționează, dar apăsând o tastă îl determină să pornească pentru totdeauna …
De asemenea, trebuie să ne abonăm la end
observabil, deci știm când a fost eliberată cheia.
end.subscribe(() => {
sprite.classList.remove('powerup');
});
Acum, el pornește în sus și în jos la porunca ta.
Construirea unui Scouter
Orice fan DBZ a văzut un scouter, micii ochelari folosiți pentru a urmări nivelurile de putere (până la episodul 20 …).
Obligatoriu> 9000 glumă
Pe măsură ce Saiyanii se alimentează, nivelul lor de putere crește. De neconceput, nu?
Avem nevoie de o modalitate de a urmări nivelul de putere al lui Goku pe măsură ce urcă și de a declanșa transformarea SSJ după, de exemplu, 100 de puncte.
Putem începe oprirea la 1 și o putem crește în timp ce utilizatorul ține apăsată o cheie.
Operatori RxJS
Operatorii sunt locul în care RxJS strălucește cu adevărat. Putem folosi funcții pure pentru a descrie modul în care datele ar trebui să se transforme prin flux.
Când utilizatorul ține apăsată o cheie, să transformăm aceste emisii într-un număr care crește în timp.
Scanează
operator de scanare este perfect pentru asta. E ca și cum Array.reduce
, dar emite pe măsură ce se reduce.
De exemplu, dacă aveți o serie de numere:
nums = [1, 2, 3, 4, 5];
Și doresc să le adun, reduce
este o alegere excelentă.
nums.reduce((a, b) => a + b, 0);
// 15
Ce se întâmplă dacă doriți să vedeți fiecare adăugare așa cum se întâmplă?
introduce scan
. Puteți rula acest lucru în consola aplicației noastre.
const { from } = rxjs;
const { scan } = rxjs.operators;
from([1, 2, 3, 4, 5])
.pipe(scan((a, b) => a + b, 0))
.subscribe(console.log);
// 1 (0 + 1)
// 3 (1 + 2)
// 6 (3 + 3)
// 10 (6 + 4)
// 15 (10 + 5)
Vedeți cum cresc emisiile în timp? Putem face asta cu Goku pe măsură ce el se alimentează!
const { fromEvent } = rxjs;
const { scan, tap } = rxjs.operators;
const begin = fromEvent(document, 'keydown');
const end = fromEvent(document, 'keyup');
begin
.pipe(
scan((level) => level + 1, 1),
tap((level) => {
console.log({ level });
})
)
.subscribe(() => {
sprite.classList.add('powerup');
});
Începem nivelul lui la 1
și creșteți-l cu 1 de fiecare dată keydown
incendii de eveniment.
Si operator robinet operatorul ne permite să înregistrăm rapid valoarea fără a deranja conducta.
Puterea mea se apropie infinit de MAXIM!
Merge Super Saiyan
Ne-am antrenat din greu, este timpul să ne transformăm.
scan
operatorul urmărește nivelul de putere al lui Goku. Acum trebuie să mergem SSJ când emite 100.
Am construit o hartă a levels: transformations
. O puteți pune chiar deasupra main
.
const powerLevels = {
100: {
current: 'base',
next: 'ssj'
}
};
const main = () => {
// ...
};
Este exagerat, dar ar trebui să simplifice adăugarea de viitoare transformări.
Când nivelul de putere atinge un număr în care powerLevels
hartă, o vom elimina current
clasa din sprite
și adăugați next
clasă.
Acest lucru ne permite să trecem ușor de la o transformare la alta.
Iată codul.
const { fromEvent } = rxjs;
const { filter, map, scan, tap } = rxjs.operators;
const begin = fromEvent(document, 'keydown');
const end = fromEvent(document, 'keyup');
begin
.pipe(
scan((level) => level + 1, 1),
tap((level) => {
console.log({ level });
sprite.classList.add('powerup');
}),
map((level) => powerLevels[level]),
filter((level) => level && level.next)
)
.subscribe(({ current, next }) => {
sprite.classList.remove(current);
sprite.classList.add(next);
});
Hartă și filtrare
Adăugarea powerup
ora se întâmplă acum în interiorul tap
, pentru că ar trebui să se întâmple întotdeauna. Cu toate acestea, transformarea SSJ, nu ar trebui întotdeauna se întâmplă.
Folosind map
, cel mai recent nivel de putere devine o intrare în powerLevels
Hartă. Folosim filter
pentru a verifica dacă există intrarea și are o .next
proprietate.
Dacă da, înseamnă că Goku poate merge și mai departe! Al nostru .subscribe
va schimba current
și next
ca nume de clasă pe sprite
.
Rezultatul final?
Masurator de putere
Te distrezi la fel de mult ca mine, nu? Din păcate, utilizatorul nostru nu o va face.
Nu pot vedea cât de mare este nivelul de putere al lui Goku! Nu vor ști cum să deschidă consola DevTools. Trebuie să remediem acest lucru!
Să ne îmbunătățim UX-ul umplând contorul de putere. Puteți pune acest lucru mai sus main
.
const fillMeter = (level) => {
const limit = 100;
if (level >= limit) {
return;
}
const containerWidth = meterContainer.offsetWidth;
const newWidth = (level / limit) * containerWidth;
meter.style.width = `${newWidth}px`;
};
Și spune-i înăuntru tap
.
tap((level) => {
console.log({ level });
sprite.classList.add('powerup');
fillMeter(level);
});
Și iată-ne:
Mergând și mai departe dincolo
Deblocarea mai multor transformări este doar o chestiune de a adăuga sprite și de a le actualiza powerLevels
Hartă. Dacă sunteți interesat, trimiteți un PR pe repo și cu siguranță vom vorbi.
Iată foaie sprite originală. Bucurați-vă!
#Mergeți #SUPER #SAIYAN #RxJS #Observables
Mergeți SUPER SAIYAN cu RxJS Observables