вернуться к уроку

Поместите мяч в центр поля

важность: 5

Исходный документ выглядит так:

Каковы координаты центра поля?

Вычислите их и используйте, чтобы поместить мяч в центр поля:

  • Элемент должен позиционироваться за счёт JavaScript, а не CSS.
  • Код должен работать с любым размером мяча (10, 20, 30 пикселей) и любым размером поля без привязки к исходным значениям.

P.S. Да, центрирование можно сделать при помощи чистого CSS, но задача именно на JavaScript. Далее будут другие темы и более сложные ситуации, когда JavaScript будет уже точно необходим, это – своего рода «разминка».

Открыть песочницу для задачи.

Мяч имеет CSS-свойство position:absolute. Это означает, что координаты left/top измеряются относительно ближайшего спозиционированного элемента, которым является #field (т.к. у него есть CSS-свойство position:relative).

Координаты отсчитываются от внутреннего верхнего левого угла поля:

Ширина и высота внутреннего поля – это clientWidth/clientHeight. Таким образом, его центр имеет координаты (clientWidth/2, clientHeight/2).

…Но если мы установим мячу такие значения ball.style.left/top, то в центре будет не сам мяч, а его левый верхний угол:

ball.style.left = Math.round(field.clientWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight / 2) + 'px';

Вот как это выглядит:

Для того, чтобы центр мяча находился в центре поля, нам нужно сместить мяч на половину его ширины влево и на половину его высоты вверх:

ball.style.left = Math.round(field.clientWidth / 2 - ball.offsetWidth / 2) + 'px';
ball.style.top = Math.round(field.clientHeight / 2 - ball.offsetHeight / 2) + 'px';

Внимание, подводный камень!

Код выше стабильно работать не будет, потому что <img> идёт без ширины/высоты:

<img src="ball.png" id="ball">

Если браузеру неизвестны ширина и высота изображения (из атрибута HTML-тега или CSS-свойств), он считает их равными 0 до тех пор, пока изображение не загрузится.

При первой загрузке браузер обычно кеширует изображения, так что при последующей загрузке оно будет доступно тут же, вместе с размерами. Но при первой загрузке значение ширины мяча ball.offsetWidth равно 0. Это приводит к вычислению неверных координат.

Мы можем исправить это, добавив атрибуты width/height тегу <img>:

<img src="ball.png" width="40" height="40" id="ball">

…Или задав размеры в CSS:

#ball {
  width: 40px;
  height: 40px;
}

Открыть решение в песочнице.