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

Передвигать мяч по полю

важность: 5

Сделайте так, что при клике по полю мяч перемещался на место клика.

Требования:

  • Мяч после перелёта должен становиться центром ровно под курсор мыши, если это возможно без вылета за край поля.
  • CSS-анимация не обязательна, но желательна.
  • Мяч должен останавливаться у границ поля, ни в коем случае не вылетать за них.
  • При прокрутке страницы с полем ничего не должно ломаться.

Замечания:

  • Код не должен зависеть от конкретных размеров мяча и поля.
  • Вам пригодятся свойства event.clientX/event.clientY

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

Мяч под курсор мыши

Основная сложность первого этапа – сдвинуть мяч под курсор, т.к. координаты клика e.clientX/Y – относительно окна, а мяч позиционирован абсолютно внутри поля, его координаты left/top нужно ставить относительно левого-верхнего внутреннего (внутри рамки!) угла поля.

Чтобы правильно вычислить координаты мяча, нужно получить координаты угла поля и вычесть их из clientX/Y:

var field = document.getElementById('field');
var ball = document.getElementById('ball');

field.onclick = function(e) {

  var fieldCoords = field.getBoundingClientRect();
  var fieldInnerCoords = {
    top: fieldCoords.top + field.clientTop,
    left: fieldCoords.left + field.clientLeft
  };

  ball.style.left = e.clientX - fieldInnerCoords.left + 'px';
  ball.style.top = e.clientY - fieldInnerCoords.top + 'px';

};

Далее мяч нужно сдвинуть на половину его ширины и высоты ball.clientWidth/clientHeight, чтобы он оказался центром под курсором.

Здесь есть важный «подводный камень» – размеры мяча в исходном документе не прописаны. Там просто стоит <img>. Но на момент выполнения JavaScript картинка, возможно, ещё не загрузилась, так что высота и ширина мяча будут неизвестны (а они необходимы для центрирования).

Нужно добавить width/height в тег <img> или задать размеры в CSS, тогда на момент выполнения JavaScript будет знать их и передвинет мяч правильно.

Код, который полностью центрирует мяч, вы найдете в полном решении:

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