HTML, CSS, JS: шахматное поле,
часть 4: движение фигур
В предыдущих трех постах (1, 2, 3) я описал создание шахматного поля на веб-странице с помощью языка разметки HTML и языка описания стилей CSS, с использованием входящей в CSS технологии Flexbox. Кроме этого, я добавил на шахматное поле шахматные фигуры (источник изображений). В этом посте я добавлю в проект возможность передвигать шахматные фигуры мышью с помощью скрипта на языке программирования JavaScript.
Включен ли JavaScript в браузере
В современных браузерах интерпретатор JavaScript (движок) встроен по умолчанию. Обычно в настройках браузера есть возможность отключения исполнения скриптов JavaScript с веб-страниц. Но абсолютное большинство пользователей этой настройкой не пользуется, разрешая браузеру выполнять эти скрипты.
В хорошем веб-приложении редкая ситуация, когда пользователь отключил исполнение скриптов в своем браузере, тоже должна быть обработана. Например, можно сообщить пользователю, что часть функций веб-страницы не будет работать при отключенном JavaScript. Но в этом посте я не буду прописывать эту обработку в скрипте.
Добавление скриптов на веб-страницу
Очень часто начинающие веб-программисты неправильно добавляют скрипт на языке JavaScript на веб-страницу, в результате скрипт не работает так, как ожидает веб-программист, или скрипт как будто бы вообще не запускается.
Если скрипт должен манипулировать элементами веб-страницы, то нужно обеспечить определенный порядок загрузки веб-страницы, чтобы всё работало так, как хочется. Сначала браузер должен прочитать код веб-страницы на языке HTML и создать объектную модель документа (DOM), а только затем следует запускать скрипт.
Для обеспечения такого порядка работы многие веб-программисты вставляют скрипты в конец тела (body) веб-страницы или в самый конец файла с кодом на языке HTML. Это работает, но я предпочитаю вставлять скрипты в конец элемента head веб-страницы, в котором описывается информация (метаданные) о веб-странице. Например, вот так:
<head>
<!-- ... -->
<script src="movePiece.js" defer></script>
</head>
Обратите внимание на свойство defer, без него скрипт загрузится раньше элементов тела веб-страницы. А поскольку этот мой скрипт будет использовать элементы тела веб-страницы, то без этого свойства он работать не будет. В переводе на русский «defer» означает «отложить», то есть это указание браузеру отложить запуск данного скрипта на момент после полной загрузки веб-страницы и окончания построения объектной модели документа.
Скрипт движения фигуры
Код скрипта я пишу в файле movePiece.js, который подключен на веб-страницу описанным выше способом.
Движение фигур в этом проекте можно реализовать множеством разных способов. Мне нужно было только показать студентам возможность придания веб-страницам интерактивности, поэтому я в этом проекте выбирал способы попроще, где это возможно.
Сначала я хотел использовать способ «drag and drop», при котором пользователь захватывает на веб-странице желаемый объект мышью и перетаскивает его в нужное место, где отпускает. Но в итоге я отказался от этой идеи в пользу способа попроще. Тем, кто всё же хочет попробовать способ «drag and drop», рекомендую прочесть соответствующую главу в учебнике learn.javascript.ru.
Мы выбрали алгоритм, по которому пользователь первым кликом основной кнопкой мыши выбирает фигуру, которую хочет переместить. Вторым кликом основной кнопкой мыши пользователь выбирает поле назначения, в которое он хочет переместить выбранную ранее фигуру. Вот какой код получился:
let piece; // передвигаемая фигура
// получить все элементы веб-страницы, представляющие шахматные поля
let chessFields = document.querySelectorAll(".square");
// назначить каждому из шахматных полей обработчик клика основной кнопкой мыши
for (let field of chessFields) {
field.onclick = movePiece;
}
// функция-обработчик клика основной кнопкой мыши
function movePiece(event) {
if (event.target.tagName == "IMG") { // выбор передвигаемой фигуры
piece = event.target;
}
else if (event.target.tagName == "DIV") { // передвижение выбранной фигуры
// если фигура выбрана
if (piece) {
// если на поле назначения нет фигуры
if (!event.target.firstElementChild) {
event.target.append(piece);
}
}
}
}
Для хранения выбранной фигуры используем переменную piece.
Ранее в коде веб-страницы на языке HTML мы назначили класс square всем 64-м шахматным полям. Поэтому в скрипте легко смогли выбрать эти шахматные поля по селектору .square.
Сам алгоритм выбора и передвижения фигуры реализован в функции movePiece, но чтобы эта функция вызывалась при каждом клике основной кнопкой мыши по нужным элементам веб-страницы, нужно как-то связать функцию movePiece и нужные элементы. Это мы проделываем в цикле for с помощью свойства onclick нужных элементов веб-страницы.
Вообще, есть несколько более сложный, но более гибкий метод привязки — с помощью метода addEventListener. Я выбрал привязку с помощью свойства onclick из-за того, что это проще, но если кто-нибудь всё же хочет попробовать метод addEventListener, то рекомендую начать с чтения соответствующей главы в учебнике learn.javascript.ru. Одно из преимуществ метода addEventListener состоит в том, что он позволяет привязать к одному и тому же событию на нужном элементе несколько функций-обработчиков, а свойство onclick нужного элемента — только одну функцию-обработчик.
Как выбранный алгоритм определяет, с какой целью вы кликнули основной кнопкой мыши — для выбора фигуры или для указания поля назначения выбранной фигуры? Это зависит от названия элемента, по которому вы кликнули (IMG или DIV). Обратите внимание, что названия элементов мы получили с буквами в верхнем регистре, это важно.
Внутри функции-обработчика у нас есть доступ к информации о событии через первый параметр функции, в нашем случае мы назвали его event. Свойство target параметра event содержит элемент веб-страницы, по которому пользователь кликнул мышью.
При реализации перемещения фигуры мы написали несколько проверок с помощью условий if, убирающих несколько ненужных эффектов.
Передвижения фигур не учитывают правила передвижения шахматных фигур. В нашем проекте любую выбранную фигуру можно переставить на любое свободное поле. Также не реализованы взятие фигур противника, рокировка и ряд других манипуляций фигурами, необходимых по правилам игры в шахматы. Это оставлено на тех, кто захочет продолжить развитие этого проекта.
В принципе, без реализации взятия фигур даже детский мат на нашей доске сложно показать. Но задача продемонстрировать, как может работать скрипт на языке JavaScript на веб-странице, выполнена. Из этого примера можно также понять, с какой целью в браузерах используются скрипты на языке JavaScript (для придания веб-странице интерактивности, то есть веб-страница начинает реагировать на действия пользователя).
Результат
Начало демонстрации одного из вариантов детского мата черным:
1. e2-e4 e7-e5
2. Сf1-c4 Сf8-c5
3. Фd1-f3 Кb8-c6
4. Фf3×f7#

Можно посмотреть на получившееся поле и попередвигать фигуры на поле онлайн: https://textpub.neocities.org/my/chess-board/v2.2/.
Развитие проекта
Если найду время, добавлю сохранение позиции в файл и загрузку позиции из файла. Для этого имеет смысл добавить отдельные скрипты на языке JavaScript.