July 7th, 2021

JavaScript: координаты углов поля

Решил задачу «Найдите координаты точек относительно окна браузера» к подразделу 1.11 «Координаты» второй части учебника по JavaScript.

HTML-страница из этой задачи, отображенная в браузере, визуально похожа на HTML-страницу из задачи про помещение футбольного мяча в центр футбольного поля, про решение которой я писал в прошлом посте.

В принципе, суть обсуждаемой задачи и ее решение довольно просты. На HTML-странице задано зеленое прямоугольное поле с толстой черной границей. Для этого используется HTML-элемент div, которому на языке HTML задан идентификатор field. Стиль для этого HTML-элемента (как и для других HTML-элементов) задан в отдельном файле index.css. Взглянуть на код заданной HTML-страницы можно в песочнице.

У меня в браузере («Microsoft Edge» на движке «Chromium») это поле выглядит так (картинка):



Тонкая серая линия сверху и слева от поля является краем окна браузера. Я ее оставил на картинке, чтобы было видно, где находится поле относительно окна браузера.

По условиям задачи требуется найти координаты:

1) левого верхнего угла вышеописанного поля, включая толстую черную границу;
2) правого нижнего угла вышеописанного поля, включая толстую черную границу;
3) левого верхнего угла зеленого поля (без границы);
4) нижнего правого угла зеленого поля (без границы).

Пишем код (это и есть решение задачи):
let rect = field.getBoundingClientRect();

console.log("Точка 1: x = " + rect.x +     ", y = " + rect.y);
console.log("Точка 2: x = " + rect.right + ", y = " + rect.bottom);

console.log("Точка 3: x = " + (rect.x + field.clientLeft) +
                   ", y = " + (rect.y + field.clientTop));

console.log("Точка 4: x = " + (rect.x + field.clientLeft + field.clientWidth) +
                   ", y = " + (rect.y + field.clientTop + field.clientHeight));

Про метод getBoundingClientRect, про возвращаемый этим методом объект (в нашем скрипте мы его сохраняем в переменную rect) и про свойства этого объекта рассказано в подразделе 1.11 «Координаты» (к которому относится данная задача) второй части обсуждаемого учебника.

Координаты rect.x, rect.y, rect.right и rect.bottom — это координаты прямоугольника, включающего в себя толстую черную границу заданного поля.

Про свойства clientLeft, clientTop, clientWidth и clientHeight было рассказано в подразделе 1.9 «Размеры и прокрутка элементов» второй части обсуждаемого учебника.

Дополнительно

Повторюсь, задача простая. Но ее авторы, наверное, решили запутать и/или развлечь читателя учебника и навесили на задачу кучу всяких рюшечек.

Во-первых, авторы решили показать на заданной HTML-странице пронумерованными красными стрелками точки, координаты которых требуется найти с помощью скрипта на языке JavaScript. Каждая такая стрелка тоже создана с помощью собственного отдельного HTML-элемента div, стиль которого тоже задан в уже упомянутом файле index.css с помощью CSS-класса triangle-right.

Вообще, эти стрелки (вернее, представляющие их HTML-элементы div) в исходном коде заданной HTML-страницы расположены после (ниже) HTML-элемента div, представляющего наше поле. Однако, благодаря виду позиционирования position: relative;, указанному в CSS-классе triangle-right, их можно сдвигать относительно их первоначальной позиции. Что и сделано с помощью указания величин этих сдвигов в свойстве style HTML-элементов div, представляющих стрелки.

Первоначальная позиция стрелок (картинка):



Стрелки сдвинуты из первоначальной позиции в новые позиции (картинка):



В конструировании самой стрелки на первый план выходит граница (border) HTML-элемента. Возьмем HTML-элемент div и определим ему достаточно толстую границу (к примеру, 20px), причем с каждой стороны — разного цвета. Ширину HTML-элемента возьмем в 50px. У меня в браузере это выглядит так (картинка):



Код:
<!-- в заголовочной части HTML-страницы -->
<style>
  #box {
    border-left: 20px solid red;
    border-top: 20px solid green;
    border-right: 20px solid blue;
    border-bottom: 20px solid black;
    width: 50px;
  }
</style>
<!-- в теле HTML-страницы -->
<div id="box">Текст</div>

На картинке видно, что так как браузер вынужден делить границу нашего HTML-элемента на четыре части, чтобы окрасить каждую в разный цвет, с каждой стороны от HTML-элемента образуется трапеция своего цвета. Уменьшая ширину и высоту в стиле HTML-элемента (эти размеры не включают границу), будем уменьшать место для содержимого HTML-элемента. При этом трапеция с каждой из сторон будет стремиться превратиться в треугольник. Вот так (картинка):



Код:
<!-- в заголовочной части HTML-страницы -->
<style>
  #box {
    border-left: 20px solid red;
    border-top: 20px solid green;
    border-right: 20px solid blue;
    border-bottom: 20px solid black;
    width: 0;
    height: 0;
  }
</style>
<!-- в теле HTML-страницы -->
<div id="box">Текст</div>

На картинке видно, что хоть место для содержимого HTML-элемента схлопнулось, само содержимое (надпись «Текст») всё еще остается видимым. Это происходит потому, что по умолчанию CSS-свойство overflow у нашего HTML-элемента (по правилам языка CSS) принимает значение visible. Если нам не нужно, чтобы в данном случае надпись «Текст» была видна, можно в стиле нашего HTML-элемента прописать указание, к примеру, overflow: auto; (это один из вариантов).

Далее действуем в зависимости от того, какая стрелка нам нужна (указывающая вправо, указывающая влево, указывающая вверх, указывающая вниз). Например, в нашем случае нам нужна стрелка, указывающая вправо. Чтобы сконструировать такую стрелку, вообще уберем из стиля определение правой границы HTML-элемента (у нас она синяя), таким образом ее вообще не станет при отображении HTML-элемента в браузере. А верхнюю и нижнюю границы сделаем невидимыми (прозрачными, цвета transparent). Вообще их убрать мы не можем, так как с их помощью регулируется высота нашей стрелки. У меня в браузере получилось следующее (картинка):



Код:
<!-- в заголовочной части HTML-страницы -->
<style>
  #box {
    border-left: 20px solid red;
    border-top: 20px solid transparent;
    border-bottom: 20px solid transparent;
    width: 0;
    height: 0;
  }
</style>
<!-- в теле HTML-страницы -->
<div id="box">Текст</div>

Сдвинуть содержимое нашего HTML-элемента (надпись «Текст») левее или правее можно с помощью CSS-свойства text-indent, а сдвинуть это содержимое повыше или пониже можно с помощью CSS-свойства line-height (авторы обсуждаемой задачи сделали это через определение CSS-свойства font, вот так: font: 12px/1 monospace;, здесь 1 после знака дроби и есть определение CSS-свойства line-height).

Во-вторых, авторы вставили в заголовочную часть заданной HTML-страницы скрипт, который вызывается каждый раз при нажатии на левую (вернее, основную, она не всегда левая) кнопку мыши. Этот скрипт выводит координаты точки на экране, в которой нажата мышка, в содержимое HTML-элемента div с идентификатором coords на заданной HTML-странице. Этот HTML-элемент расположен на заданной HTML-странице выше нашего поля. Первоначально в этом HTML-элементе размещен текст «(координаты покажутся здесь)», но после срабатывания скрипта этот текст будет замещен на координаты, к примеру «287:162» (это расстояние по горизонтали и вертикали в пикселях от верхнего левого угла области просмотра браузера).

Предполагается, что с помощью этой функциональности ученик сможет проверить полученные им координаты заданных в условии задачи углов поля.