Как проверить нажатие клавиши несколько раз в js?

Я пытаюсь создать таймер кубирования. Когда я нажимаю и удерживаю пробел, таймер должен стать зеленым. Когда я отпускаю, таймер должен начать работать. При повторном нажатии таймер должен остановиться. А потом все это должно повториться.

Мне нужно проверить, если:

  1. Пробел был нажат.
  2. Пробел был отпущен.
  3. Пробел был снова нажат.

У меня есть этот код:

var down = false;
document.addEventListener('keydown', function () {
    if (event.code === 'Space') {
        if (down) return;
        down = true;
        console.info('Waiting...')
    }
}, false);

document.addEventListener('keyup', function () {
    if (event.code === 'Space') {
        down = false;
        console.info('Start')
    }
}, false);

// I need some Stop function here

Проблема в том, что когда я нажимаю пробел, а затем отпускаю и снова нажимаю, он выполняет 4 функции. Но мне нужно запустить 3 разных. И тогда я должен быть в состоянии сделать то же самое снова.

Как я могу это сделать?

Не могли бы вы уточнить, что вы пытаетесь сделать, что ожидаете увидеть и что видите на самом деле?

Miguel Rivera Rios 14.07.2023 21:29

Я пытаюсь создать таймер кубирования. Когда я нажимаю и удерживаю пробел, таймер должен стать зеленым. Когда я отпускаю, таймер должен начать работать. При повторном нажатии таймер должен остановиться. А потом все это должно повториться.

Timur Arazmedov 14.07.2023 21:34
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать KeyboardEvent::repeat, чтобы проверить, есть ли у вас первое событие нажатия клавиши:

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat

Также обратите внимание, что window.event устарел:

https://developer.mozilla.org/en-US/docs/Web/API/Window/event

Таким образом, логика состоит в том, чтобы использовать автоматы с конечным состоянием и переключаться между состояниями при нажатии клавиш. Когда состояние изменяется, вызывается функция из объекта transitions - поместите туда свою логику для выполнения при изменении состояния:

let state = 'stopped';

const transitions = {
  waiting: state => console.info(state),
  started: state => console.info(state),
  stopped: state => console.info(state),
};

document.addEventListener('keydown', changeState);
document.addEventListener('keyup', changeState);

function changeState({code, repeat, type: action}){

  if (code !== 'Space' || repeat){
    return;
  }
  
  // this allows to have more event types and states in the future without cluttering
  const actions = {
    keydown: () => state === 'stopped' ? 'waiting' : 'stopped',
    keyup: () => state === 'stopped' ? state : 'started',
  };
  
  // determine the next state 
  const next = actions[action]();
  // if the next state is different, commit it to the current and execute transition
  next === state || transitions[state = next](state);
  
}

Он делает то же самое на самом деле. Поясню по-другому: мне нужно 3 функции. Один для режима ожидания. Второй для запуска какой-то функции (Пуск). Третий для остановки функции. Когда я нажимаю один раз, запускается первая функция. Когда я отпускаю, запускается функция Start. При повторном нажатии запускается функция Stop. Вы можете помочь с этим?

Timur Arazmedov 14.07.2023 21:42

@TimurArazmedov исправлено и улучшено

Alexander Nenashev 14.07.2023 21:51

Большое спасибо! Но как я могу вставить свои функции?

Timur Arazmedov 14.07.2023 21:55

@TimurArazmedov удалил лишнее if. вы также можете проголосовать за мой ответ (стрелка вверх), чтобы я был вознагражден дополнительными 10 баллами и мотивирован помочь вам в будущем, спасибо

Alexander Nenashev 14.07.2023 21:58

@TimurArazmedov добавил transitions объект, куда вы можете поместить свои функции

Alexander Nenashev 14.07.2023 22:03

Большое спасибо!

Timur Arazmedov 14.07.2023 22:06

@TimurArazmedov улучшил код, позволяющий иметь логику состояния без ifs. он мог бы быть более сложным для понимания, но более лаконичным и гибким

Alexander Nenashev 14.07.2023 22:18

Другие вопросы по теме