Автор оригинала: FreeCodeCamp Community Member.
Я любил Dragonball Z как малыша, и все еще люблю его как взрослый.
Среди смешного количества преобразований оригинальный супер Сайян остается моим любимым.
Ничто не совсем как оригинал
Я также люблю Rxjs, тем больше я выравниваю с ним, так почему бы не комбинировать эти два для окончательного выключения?
Пойду супер Сайян
С четырьмя листами спрайтов и немного HTML, CSS и RXJS мы можем воссоздать эту легендарную трансформацию!
Это то, что мы будем делать. Увлекательно, верно?! ?
Настраивать
Все на мой github Отказ
cd ./wherever-you-want git clone [https://github.com/yazeedb/dbz-rxjs](https://github.com/yazeedb/dbz-rxjs) cd dbz-rxjs
Открыть index.html
В вашем любимом браузере и проекте в вашем любимом текстовом редакторе, и вы готовы к работе!
Нет NPM установить
S сегодня?
И идти вперед, я буду использовать аббревиатуру “SSJ” вместо “супер Сайяна” для краткости.
Первый день тренировки
Вы заметите, что Гоку уже движется. Поскольку мы сосредотачиваемся на RXJS, мы просто пронизим отправную точку проекта.
Вот главный HTML:
Hold any key to POWER UP!
Дно Div
есть Class = "База"
, что соответствует этому CSS:
.base, .ssj { width: 120px; height: 250px; animation: stand 0.8s steps(2) infinite; } .base { background-image: url('img/goku-standing-sheet.png'); }
Это устанавливает ширину, высоту Goku и постоянную анимацию.
Если вы посмотрите на его базовые/SSJ Sprite Shies, это две разные позиции, и мы переключаемся между ними каждые 0,8 секунды.
Переключение обрабатывается к нижней части still.css
:
@keyframes stand { from { background-position: 0px; } to { background-position: -255px; } }
То же самое для питания:
@keyframes powerup { from { background-position: 0px; } to { background-position: -513px; } }
Мы накроем счетчик питания, когда мы манипулируем его.
Освоение элементов DOM
index.html
уже включает в себя RXJS @ 6.2.1
через CDN, так что вы покрыты.
В app.js
Давайте поймаем элементы DOM, которые мы заинтересованы в:
const sprite = document.querySelector('#sprite'); const meterContainer = document.querySelector('#meter-container'); const meter = document.querySelector('#meter');
Я предпочитаю псевдоним Document.Queryselector
Итак, использование этого не заставляет меня запястья.
const $ = document.querySelector.bind(document);** const sprite = $('#sprite'); const meterContainer = $('#meter-container'); const meter = $('#meter');
Далее мы создадим Главная
функция и немедленно назвать это.
// ... const main = () => { // do something }; main();
Ресив вверх
Вот Главная
фрагмент первого кода:
const main = () => { const { fromEvent } = rxjs; const begin = fromEvent(document, 'keydown'); const end = fromEvent(document, 'keyup'); };
Goku должен включаться, когда ключ удерживается, и останавливайтесь, когда этот ключ отпустит. Мы можем использовать Извент
Оператор для создания двух наблюдаемых:
начать
: Уведомляет, когда пользователь нажимает ключ вниз Отказконец
: Уведомляет всякий раз, когда пользователь давай пойдем ключа.
Тогда мы можем Подписаться к этим выбросам и действовать на них. Чтобы получить анимацию питания, дайте Сприт
PowerUp
имя класса.
begin.subscribe(() => { sprite.classList.add('powerup'); });
Он работает, но нажав ключ, заставляет его навсегда включаться …
Мы также должны подписаться на конец
наблюдаемый, поэтому мы знаем, когда ключ отпустил.
end.subscribe(() => { sprite.classList.remove('powerup'); });
Теперь он поддерживает вверх и вниз по вашей команде.
Строительство Scouter
Любой вентилятор DBZ видел Scouter, маленькие очки, используемые для отслеживания уровней мощности (пока, как эпизод 20 …).
Обязательная> 9000 шуток
Когда саяны влагали, их уровень мощности растет. Немыслимый, верно?
Нам нужен способ отслеживать уровень мощности Гоку, когда он поднимается, и вызвать трансформацию SSJ после того, как сказал, 100 баллов.
Мы можем начать свою мощность в 1 и увеличить его, пока пользователь удерживает ключ вниз.
Операторы RXJS
Операторы находятся в том, где RXJS действительно сияет. Мы можем использовать чистые функции для описания того, как данные должны преобразовать через поток.
Когда пользователь удерживает ключ вниз, давайте преобразуем эти выбросы в число, которое со временем увеличивается.
Сканирование
Оператор сканирования идеально подходит для этого. Это как Array.reduce
, но это излучает Как это уменьшает Отказ
Например, если у вас есть массив номеров:
nums = [1, 2, 3, 4, 5];
И хочу добавить их, Уменьшить
это отличный выбор.
nums.reduce((a, b) => a + b, 0); // 15
Что, если вы хотите увидеть каждое добавление, как это происходит?
Введите сканировать
Отказ Вы можете запустить это в консоли нашего приложения.
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)
Посмотрите, как рост выбросов со временем? Мы можем сделать это с Гоку, когда он поддерживает!
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'); });
Мы начинаем его уровень в 1
и увеличить его на 1 каждый раз, когда КДУЩЬЮ
события пожаров.
И Нажмите оператор Оператор позволяет нам быстро регистрировать значение, не нарушая трубопровод.
Моя сила бесконечно приближается к максимуму!
Собирается супер Сайян
Мы тренировали тяжело, пришло время трансформироваться.
сканировать
Оператор отслеживает уровень мощности Goku. Теперь нам нужно пойти SSJ, когда он излучает 100.
Я построил карту Уровни: преобразования
Отказ Вы можете поставить его прямо выше Главная
Отказ
const powerLevels = { 100: { current: 'base', next: 'ssj' } }; const main = () => { // ... };
Это излишки, но следует упростить добавление будущих преобразований.
Когда уровень мощности достигает номера в этом Powerlevels
карта, мы удалим его Текущий
класс от Сприт
и добавьте Следующий
учебный класс.
Это позволяет нам плавно идти от одного преобразования к следующему.
Вот код.
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); });
Карта и фильтр
Добавление . PowerUp
Класс сейчас бывает внутри Нажмите
потому что это всегда должно случиться. Трансформация SSJ Однако не должен всегда случается.
Использование карта
последний уровень мощности становится записью в Powerlevels
карта. Мы используем Фильтр
Чтобы проверить, существует ли запись и имеет .Next
свойство.
Если это так, это означает, что Goku может пойти еще дальше за пределами! Наше . Подписаться
будет поменяться Текущий
и Следующий
Как названия классов на Сприт
Отказ
Конечный результат?
Сил-о-Метр
У тебя так весело, как я, верно? К сожалению, наш пользователь не будет.
Они не могут видеть, насколько высокий уровень мощности Goku! Они не узнают, как открыть консоль devtools. Мы должны исправить это!
Давайте улучшим наш UX, заполнив счетчик мощности. Вы можете поставить это выше Главная
Отказ
const fillMeter = (level) => { const limit = 100; if (level >= limit) { return; } const containerWidth = meterContainer.offsetWidth; const newWidth = (level / limit) * containerWidth; meter.style.width = `${newWidth}px`; };
И назовите это внутри Нажмите
Отказ
tap((level) => { console.log({ level }); sprite.classList.add('powerup'); fillMeter(level); });
И здесь мы идем:
Идти даже дальше
Разблокировка больше преобразований – это просто вопрос добавления спрайтов и обновление наших Powerlevels
карта. Если вы заинтересованы, отправьте PR на репо И мы обязательно поговорим.
Вот …| Оригинальный лист спрайта Отказ Наслаждаться!