События JavaScript keydown и keyup
Клавиатурные события JavaScript: различия keydown и keyup, объект KeyboardEvent (key и code, модификаторы, repeat), примеры горячих клавиш и навигации.
Введение в клавиатурные события JavaScript
Клавиатурные события JavaScript позволяют странице реагировать в момент, когда пользователь нажимает или отпускает клавишу. Они лежат в основе поиска по мере ввода, горячих клавиш, управления в играх и доступной навигации с клавиатуры. В этой главе рассматриваются два события, которые используются чаще всего, — keydown и keyup: объясняется, чем они отличаются, разбирается объект KeyboardEvent, получаемый каждым обработчиком, и приводятся практические запускаемые примеры.
Если вы только начинаете работать с событиями, сначала прочитайте Введение в события браузера и Обработка событий в DOM.
keydown и keyup: краткое сравнение
Оба события срабатывают на элементе, который в данный момент находится в фокусе (или на document, если ни один элемент специально не сфокусирован). Разница в том, когда именно в жизненном цикле нажатия они срабатывают:
| Событие | Срабатывает, когда… | Повторяется при удержании? | Типичное применение |
|---|---|---|---|
keydown | Клавиша нажата | Да — многократно | Горячие клавиши, перемещение в игре, блокировка ввода |
keyup | Клавиша отпущена | Нет — один раз за нажатие | Определение конца нажатия, обновление интерфейса |
Одиночное нажатие клавиши порождает одно событие keydown, а затем одно keyup. Удержание клавиши вызывает keydown снова и снова (автоповторы можно определить через event.repeat), а keyup срабатывает только один раз — когда клавиша наконец отпущена.
Устаревшее событие
keypressобъявлено deprecated и не должно использоваться в новом коде. Чтобы реагировать на текст, вводимый пользователем, используйте вместо него событиеinput.
Подробнее о keydown и keyup
Событие keydown
Событие keydown возникает, когда пользователь нажимает клавишу на клавиатуре. Оно срабатывает до того, как символ вставляется в поле, — именно поэтому здесь уместно вызывать event.preventDefault(), чтобы заблокировать ввод. Это событие удобно везде, где важен момент самого нажатия: в играх, при реализации возможностей специальных возможностей или в интерактивных элементах управления.
Пример события keydown
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Example of Keydown Event</title>
<style>
.highlight { background-color: yellow; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const inputField = document.getElementById('inputField');
inputField.addEventListener('keydown', function(event) {
console.log('Key down:', event.key);
if (event.key === "Enter") {
this.classList.add('highlight');
event.preventDefault(); // Prevents the default action of the enter key
}
});
});
</script>
</head>
<body>
<input type="text" id="inputField" placeholder="Press 'Enter' to highlight" />
</body>
</html>Код прослушивает событие keydown на поле ввода и проверяет, является ли нажатая клавиша «Enter». Если да, он изменяет цвет фона поля на жёлтый (класс highlight) и предотвращает стандартное поведение при нажатии Enter — отправку формы или другие типичные действия.
Событие keyup
Событие keyup срабатывает при отпускании клавиши, после события keydown (обратите внимание: устаревшее событие keypress объявлено deprecated и редко используется в современной веб-разработке). Это событие подходит для случаев, когда нужно знать, что нажатие завершилось, — например, при обновлении интерфейса или управлении мультимедийным контентом.
Пример события keyup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Example of Keyup Event</title>
<style>
.normal { background-color: transparent; }
.active { background-color: lightgreen; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const textArea = document.getElementById('textArea');
textArea.addEventListener('keyup', function(event) {
console.log('Key up:', event.key);
if (event.key === "Control") {
this.classList.remove('active');
this.classList.add('normal');
}
});
textArea.addEventListener('keydown', function(event) {
if (event.key === "Control") {
this.classList.add('active');
}
});
});
</script>
</head>
<body>
<textarea id="textArea" rows="4" cols="50" placeholder="Press and release 'Control' to see the effect"></textarea>
</body>
</html>Этот код заставляет текстовую область менять цвет фона на светло-зелёный (класс active) при нажатии клавиши Control и возвращает его к прозрачному (класс normal) при её отпускании.
Объект KeyboardEvent
Каждый обработчик keydown и keyup получает объект KeyboardEvent. Знание его ключевых свойств позволяет писать надёжную логику обработки клавиатуры.
key и code
Эти два свойства легко перепутать, а неверный выбор — самая частая причина ошибок при работе с клавиатурой:
event.key— символ или именованное значение, которое производится с учётом раскладки клавиатуры и модификаторов. Нажатие клавишиAдаёт"a"или"A"при зажатом Shift. Именованные клавиши:"Enter","Escape","ArrowLeft"," "(пробел).event.code— физическая клавиша на клавиатуре, независимо от раскладки или модификаторов. Одна и та же физическая клавиша всегда соответствует"KeyA"— будь то вводa,Aили другой раскладки.
Используйте key, когда важен вводимый символ (текстовый ввод, горячие клавиши, понятные пользователю). Используйте code, когда важна позиция клавиши — например, управление в игре через WASD, которое должно работать независимо от раскладки.
document.addEventListener('keydown', function (event) {
console.log(event.key, event.code);
});
// Pressing Shift+A on QWERTY logs: "A" "KeyA"
// Pressing the space bar logs: " " "Space"Клавиши-модификаторы и repeat
Событие также сообщает, какие клавиши-модификаторы удерживаются, и является ли нажатие автоповтором ОС:
event.altKey,event.ctrlKey,event.shiftKey,event.metaKey— boolean-значения, равныеtrue, пока соответствующий модификатор удерживается. (metaKey— это Cmd на macOS и клавиша Windows на других платформах.)event.repeat—true, когда удерживаемая клавиша снова автоматически вызываетkeydown. Проверяйте это свойство, чтобы игнорировать автоповторы.
document.addEventListener('keydown', function (event) {
// Cross-platform "save" shortcut, ignoring auto-repeat.
if ((event.ctrlKey || event.metaKey) && event.key === 's' && !event.repeat) {
event.preventDefault();
console.log('Save triggered');
}
});Прямое чтение флагов модификаторов (как показано выше) надёжнее, чем отслеживание отдельной переменной вроде ctrlPressed, потому что флаги гарантированно синхронизированы с реальным состоянием, даже если пропустить событие keyup.
Расширенное использование клавиатурных событий в JavaScript
Использование мощи клавиатурных событий keydown и keyup способно превратить обычные веб-приложения в высокоинтерактивные, доступные и эффективные платформы. Ниже рассмотрены более сложные сценарии: пользовательские горячие клавиши, управление в игре и реализация специальных возможностей.
Реализация пользовательских горячих клавиш
Горячие клавиши позволяют пользователям быстро выполнять действия, повышая продуктивность и удобство работы. В следующем примере показано, как создать простую горячую клавишу (Ctrl + S) для имитации сохранения — её можно адаптировать для запуска конкретных функций в реальных приложениях.
Пример пользовательских горячих клавиш
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Custom Hotkeys Example</title>
<script>
document.addEventListener('DOMContentLoaded', function () {
let ctrlPressed = false;
document.addEventListener('keydown', function(event) {
if (event.key === "Control") {
ctrlPressed = true;
}
// Use toLowerCase() for case-insensitive matching
if (event.key.toLowerCase() === "s" && ctrlPressed) {
alert('Saving your progress!');
event.preventDefault(); // Prevent default to stop other actions like browser shortcuts
}
});
document.addEventListener('keyup', function(event) {
if (event.key === "Control") {
ctrlPressed = false;
}
});
});
</script>
</head>
<body>
<p>Press <strong>Ctrl + S</strong> to simulate a save action.</p>
</body>
</html>Управление в игре
Управление с клавиатуры критически важно для браузерных игр. В следующем примере реализовано простое управление стрелками для перемещения объекта-игрока внутри игрового поля — базовый шаблон, который можно расширить до более сложной игровой механики.
Пример управления в игре
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Game Control Example</title>
<style>
#gameArea {
width: 300px;
height: 300px;
border: 1px solid black;
position: relative;
}
#player {
width: 50px;
height: 50px;
background-color: red;
position: absolute;
top: 125px;
left: 125px;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
const player = document.getElementById('player');
// Note: offsetLeft/Top don't account for container padding or scroll offsets.
// For production, consider using getBoundingClientRect() or adding padding offsets.
let posX = player.offsetLeft;
let posY = player.offsetTop;
document.addEventListener('keydown', function(event) {
switch (event.key) {
case "ArrowUp":
posY -= 10;
break;
case "ArrowDown":
posY += 10;
break;
case "ArrowLeft":
posX -= 10;
break;
case "ArrowRight":
posX += 10;
break;
}
player.style.left = posX + 'px';
player.style.top = posY + 'px';
});
});
</script>
</head>
<body>
<div id="gameArea">
<div id="player"></div>
</div>
<p>Use arrow keys to move the red square within the game area.</p>
</body>
</html>Улучшение доступности
Улучшение доступности помогает сделать веб-приложения удобными для людей с ограниченными возможностями. В следующем примере события keydown используются для навигации по ссылкам с помощью клавиш-стрелок, что обеспечивает клавиатурную навигацию для пользователей, которые не могут пользоваться мышью.
Пример улучшения доступности
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Accessibility Navigation Example</title>
<script>
document.addEventListener('DOMContentLoaded', function () {
const links = document.querySelectorAll('a');
let currentFocus = 0;
links[currentFocus].focus();
document.addEventListener('keydown', function(event) {
if (event.key === "ArrowDown") {
currentFocus = (currentFocus + 1) % links.length;
links[currentFocus].focus();
event.preventDefault();
}
if (event.key === "ArrowUp") {
currentFocus = (currentFocus - 1 + links.length) % links.length;
links[currentFocus].focus();
event.preventDefault();
}
});
});
</script>
</head>
<body>
<nav>
<a href="#home">Home</a>
<a href="#about">About</a>
<a href="#services">Services</a>
<a href="#contact">Contact</a>
</nav>
<p>Use the Up and Down arrow keys to navigate between the links.</p>
</body>
</html>Эти примеры не только демонстрируют техническую реализацию событий keydown и keyup, но и показывают их практическое применение для повышения интерактивности и доступности веб-приложений. Используя описанные возможности, разработчики могут создавать более привлекательный и инклюзивный пользовательский опыт.
Заключение
Клавиатурные события keydown и keyup незаменимы при создании динамичных и интерактивных веб-приложений. Запомните главное: keydown срабатывает (и повторяется) при нажатии, keyup срабатывает один раз при отпускании, event.key возвращает символ, а event.code — физическую клавишу; флаги модификаторов вместе с event.repeat позволяют реализовывать надёжные горячие клавиши. Приведённые примеры — отправная точка для добавления клавиатурного взаимодействия в ваши собственные проекты.
Связанные главы
- Введение в события браузера — как события работают на высоком уровне.
- Обработка событий в DOM —
addEventListener, обработчики и их удаление. - События: change, input, cut, copy, paste — реакция на текст, фактически попавший в поле.
- Фокусировка: focus и blur — естественное дополнение к клавиатурной навигации.
- Всплытие и перехват — как клавиатурные события распространяются по DOM.