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

Итак, у меня было событие, вызванное элементом, на который я нажал. MouseEvent предоставляет нам несколько способов определить, где мы щелкнули. Вот краткое изложение:

  • MouseEvent.clientX / MouseEvent.clientY ~ Координаты события мыши относительно области просмотра. Расчет с левой стороны и верхней части окна просмотра.
  • MouseEvent.movementX / MouseEvent.movementY ~ Координаты события мыши относительно последнего события мыши.
  • MouseEvent.offsetX / MouseEvent.offsetY ~ Координаты события мыши относительно края заполнения на целевом узле. Вычисляется из левого заполнения и верхнего заполнения.
  • MouseEvent.pageX / MouseEvent.pageY ~ Координаты события мыши относительно всего документа. Вычисляется с левой и верхней сторон всего документа, даже если он прокручивается вне поля зрения.
  • MouseEvent.screenX / MouseEvent.screenY ~ Координаты события мыши относительно всего экрана пользователя. Рассчитывается от левой и верхней сторон экрана. Если используется несколько экранов, значение рассчитывается, соответственно, для крайнего левого и самого верхнего экранов.

Это дает нам большую гибкость при обработке событий мыши. В моем случае я пытался определить горизонтальное положение мыши внутри определенного элемента. Я выбрал параметр MouseEvent.offsetX, так как он давал мне позицию относительно элемента, к которому был прикреплен прослушиватель событий.

Теперь мне просто нужно было вычислить ширину элемента, на который я нажал, и рассчитать процент в зависимости от того, как далеко в элементе я нажал. Некоторые способы сделать это: с помощью свойств offset HTMLElements API, с помощью метода getBoundingClientRect класса элемента или с помощью метода getComputedStyle оконных интерфейсов. Каждый из них дает немного отличающуюся информацию, поэтому один из них может лучше соответствовать вашему варианту использования, чем другой.

HTMLElements имеют ряд связанных с ними свойств смещения. В моем случае HTMLElement.offsetWidth дал мне свойство ширины, которое мне нужно было, чтобы определить, как далеко я щелкнул в div, и было легко вычислить мой горизонтальный процент, разделив мое значение offsetX на ширину моих элементов и умножив на 100. Но, возможно, вам нужно больше вариантов. Ниже приведен краткий обзор некоторых свойств смещения HTMLElement.

  • HTMLElement.offsetHeight ~ Возвращает высоту элемента, включая отступы и границы. Не содержит никаких псевдоэлементов, таких как ::before или ::after.
  • HTMLElement.offsetWidth ~ Возвращает ширину элемента, включая отступы и границы. Не содержит никаких псевдоэлементов, таких как ::before или ::after.
  • HTMLElement.offsetTop ~ Возвращает расстояние между внешней границей верхней границы текущего элемента и внутренней частью верхней границы родительского узла.
  • HTMLElement.offsetLeft ~ Возвращает расстояние между внешней стороной левой границы текущего элемента и внутренней стороной левой границы его родительского узла.

Для определения позиционирования могут быть полезны методы offsetTop и offsetLeft, но важно знать, на чем основан результат. Возвращаемый номер позиции смещения — это количество пикселей от края выбранного элемента, до края родительского элемента выбранных элементов, и родительский элемент может меняться в зависимости на вашем коде.

  • HTML.offsetParent ~ Ближайший родительский элемент, который был позиционирован, если эта позиция не равна:static, initial, который возвращается к static, revert, который указывает либо на static, либо на initial, как было определено ранее, unset, который по умолчанию равен initial или none. Все остальные позиционированные элементы могут быть offsetParent. Если ни один из родителей не был позиционирован, это ближайший элемент td, th или table. Если ни один из них не существует, родительский элемент возвращается к элементу body.

Еще один способ определить позиционирование — использовать метод Element class’ Element.getBoundingClientRect(). Вызов этого метода для элемента возвращает вам объект, содержащий ряд различных свойств. Однако здесь вам возвращаются значения положения относительно окна просмотра, а не документа. Объект getBoundingClientRect() содержит следующие свойства:

  • top / bottom / left / right / x / y ~Каждое свойство содержит расстояние между внешним краем его границы и краем окна просмотра. Это расстояние рассчитывается только от левой и верхней сторон окна просмотра. Таким образом, левое значение плюс ширина элемента равняется правому значению, а верхнее значение плюс высота элемента равняется нижнему значению. x и y имеют те же значения, что и left и top.
  • height / width ~ Содержит высоту/ширину элемента, включая отступы и границы. Не содержит никаких псевдоэлементов, таких как ::before или ::after.

Если вам нужно выполнять вычисления на основе области просмотра, а не позиции элемента на странице, или если что-то мешает вам использовать свойство смещения, это может быть хорошим вариантом для вас. Стоит отметить, что getBoundingClientRect() не так эффективен, как offsetX. Вероятно, это не будет иметь большого значения в большинстве ситуаций, но полезно помнить, когда это действительно имеет значение.

Другим способом получения ширины элемента является метод getComputedStyle() интерфейса Window:

  • getComputedStyle(element, pseudoElement)~ Возвращает объект, содержащий все свойства css, примененные в данный момент к этому объекту. Псевдоэлемент является необязательным.

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

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