Как можно узнать координаты текущего положения мыши при нажатии левой кнопки
Перейти к содержимому

Как можно узнать координаты текущего положения мыши при нажатии левой кнопки

Размер, прокрутка, координаты элемента, а также координаты курсора мышки (точки нажатия) | JavaScript

Координаты курсора мышки относительно экрана монитора, страницы или окна браузера

Демонстрация screenX/screenY, pageX/pageY, clientX/clientY

  • экрана монитора ( screenX / Y ),
  • HTML-дкумента ( pageX / Y ),
  • области просмотра окна браузера ( clientX / Y ).

Образец (щелчок по любому месту зелёного прямоугольника):

Определить элемент, который находится под курсором

document.elementFromPoint( X , Y ) возвращает верхний элемент, который находится на координатах ( X , Y ) относительно верхнего левого угла области просмотра окна браузера.

Образец (щелчок по любому месту зелёного прямоугольника):

Дополнение: этот же код применяется чтобы узнать место, куда нажал пользователь сенсорного устройства (планшет, телефон).

Координаты курсора мышки внутри элемента (div, img)

В Mozilla Firefox не работают offsetX и offsetY . Самое простое решение проблемы указано тут:

Образец (щелчок по любому месту зелёного прямоугольника):

Дополнение: этот же код применяется чтобы узнать место, куда нажал пользователь сенсорного устройства (планшет, телефон).

Координаты расположения элемента

Расстояние от верхнего/левого края окна браузера до элемента

Демонстрация getBoundingClientRect()

Метод elem.getBoundingClientRect() возвращает в px координаты элемента относительно верхнего левого угла области просмотра окна браузера

Образец (прокрутка или изменение окна браузера, изменение размера элемента):

elem.getBoundingClientRect().width/height поддерживаются с IE9 [developer.mozilla.org]. Кроссбраузерное решение:

Расстояние от правого/нижнего края окна браузера до элемента

Чтобы узнать отступ справа или снизу от элемента до края области просмотра окна браузера:

Образец (прокрутка или изменение окна браузера, изменение размера элемента):

Позиция одного элемента относительно другого

Рассчитать позицию одного элемента относительно другого (например, потомка относительно предка) можно, если получить разницу их координат (например, координаты родителя вычесть из координат дочернего элемента):

Смещение относительно elem.offsetParent

elem.offsetParent возвращает ближайшего родителя, имеющего position не static , если у самого элемента elem установлено position: absolute; . Положение элемента относительно elem.offsetParent показывают elem.offsetLeft / Top (IE≥8).

Размер элемента: ширина, высота, прокрутка

Получить значение свойства CSS можно благодаря getComputedStyle(elem[, pseudo]) . Предварительно советую ознакомиться с блочной моделью CSS.

Образец (щелчок по прямоугольнику с серой рамкой, его изменение или прокрутка содержимого):

Размер монитора, страницы, окна браузера: ширина, высота, прокрутка

Размер страницы, учитывающий transform и margin для <html> , который можно получить, пока страница не была прокручена.

Обработчик события onclick

Cобытие click — это одно из событий мыши в JavaScript. О нём уже было сказано в прошлой теме. Здесь мы рассмотрим его более подробно. Напомню, что обработчик события onclick срабатывает при нажатии на элементе левой кнопкой мыши.

Координаты указателя мыши

Объект события click имеет свойства, которые содержат координаты того места, на котором был произведён клик. Свойства clientX и clientY содержат координаты указателя мыши относительно окна браузера. Свойства pageX и pageY содержат координаты относительно документа. Координаты отсчитываются от левого верхнего угла. Указанные свойства есть и у других объектов событий мыши.

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

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

Прокрутите ещё немного страницу и кликните примерно в том же месте блока. Вы увидите, что координаты относительно документа не изменились, ведь блок не поменял своё положение в документе. А координаты относительно окна браузера изменились, потому что указатель мыши находился в другом месте окна.

Определение координат клика иногда используется на практике для размещения в этом месте каких-то элементов страницы.

Клик с нажатой клавишей

У объекта события click есть свойство shiftKey , которое содержит true , если клик был сделан при нажатой клавише Shift. Если клик был без Shift, то свойство содержит false . Это свойство используется для того, чтобы обработчик выполнил какие-то действия, только если клик был с нажатой клавишей Shift. Подобные свойства есть для других клавиш:

metaKey — для Mac

Добавим в обработчик такой код:

Если сделать клик в блоке с нажатой клавишей Shift, то появится сообщение. В остальном, действия обработчика не изменились.

Клик правой кнопкой

Событие contextmenu — это нажатие правой кнопки мыши. Объект этого события имеет в основном такие же свойства, как объект события click . При нажатии правой кнопки мыши обычно появляется контекстное меню браузера. Появление этого меню можно отменить. Добавим блоку обработчик события:

Как получить координаты мыши

Довольно часто JavaScript-программистам, необходимо знать координаты курсора мыши относительно окна браузера.

Решение очень простое на самом деле, ниже показан пример и сам исходный код решения.

Двигай курсором или нажимай левой кнопкой мыши по экрану и наблюдай как меняются координаты.

Исходный код | HTML-исходного кода
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

Разъяснение

Объект MouseCoords имеет 2 метода MouseCoords.getX(e) и MouseCoords.getY(e) , которые принимают параметр e (event) , самое главное этот параметр получить, после какого-либо события (движение мыши, клик по области экрана и т.д.)

Затем на примере описываются 2 события:

  1. document.onmousemove — движение курсором мыши по экрану;
  2. document.onclick — клик левой кнопкой мыши по любому месту на экране.

В этих событиях создается event и передается в качестве параметра методам объекта MouseCoords .

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

Данный скрипт позволяет выводить координаты курсора как в statusbar-е, так и в заданном месте странички.

Текущие координаты курсора:

Для получения текущих координат курсора на экране сайта вставьте на свою страничку следующий скрипт:

Далее, в том месте странички, где необходимо получить координаты курсора (если необходимо), вставляем элемент .

Если Вы все правильно сделали, то при перемещении курсора мыши по экрану браузера внутри элемента и в statusbar-е должны отображаться текущие координаты курсора.

Конечно можно, но для этого придется воспользоваться библиотекой JQuery:

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/mouse-events-basics.

В этой главе мы глубже разберёмся со списком событий мыши, рассмотрим их общие свойства, а также те события, которые связаны с кликом.

Типы событий мыши

Условно можно разделить события на два типа: «простые» и «комплексные».

Простые события

Комплексные события

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

Порядок срабатывания событий

Одно действие может вызывать несколько событий.

Например, клик вызывает сначала mousedown при нажатии, а затем mouseup и click при отпускании кнопки.

В тех случаях, когда одно действие генерирует несколько событий, их порядок фиксирован. То есть, обработчики вызовутся в порядке mousedown → mouseup → click .

Кликните по кнопке ниже и вы увидите, какие при этом происходят события. Попробуйте также двойной клик.

На тест-стенде ниже все мышиные события записываются, и если между событиями проходит больше 1 секунды, то они для удобства чтения отделяются линией. Также присутствуют свойства which/button , по которым можно определить кнопку мыши. Мы их рассмотрим далее.

Каждое событие обрабатывается независимо.

Например, при клике события mouseup + click возникают одновременно, но обрабатываются последовательно. Сначала полностью завершается обработка mouseup , затем запускается click .

Получение информации о кнопке: which

При обработке событий, связанных с кликами мыши, бывает важно знать, какая кнопка нажата.

Для получения кнопки мыши в объекте event есть свойство which .

На практике оно используется редко, т.к. обычно обработчик вешается либо onclick – только на левую кнопку мыши, либо oncontextmenu – только на правую.

Возможны следующие значения:

  • event.which == 1 – левая кнопка
  • event.which == 2 – средняя кнопка
  • event.which == 3 – правая кнопка

Это свойство не поддерживается IE8-, но его можно получить способом, описанным в конце главы.

Правый клик: oncontextmenu

Это событие срабатывает при клике правой кнопкой мыши:

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

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

В примере ниже встроенное меню показано не будет:

Модификаторы shift, alt, ctrl и meta

Во всех событиях мыши присутствует информация о нажатых клавишах-модификаторах.

Например, кнопка ниже сработает только на Alt+Shift+Клик:

На компьютерах под управлением Windows и Linux есть специальные клавиши Alt , Shift и Ctrl . На Mac есть ещё одна специальная клавиша: Cmd , которой соответствует свойство metaKey .

В большинстве случаев там, где под Windows/Linux используется Ctrl , на Mac используется Cmd . Там, где пользователь Windows нажимает Ctrl + Enter или Ctrl + A , пользователь Mac нажмёт Cmd + Enter или Cmd + A , и так далее, почти всегда Cmd вместо Ctrl .

Поэтому, если мы хотим поддерживать сочетание Ctrl +click или другие подобные, то под Mac имеет смысл использовать Cmd +click. Пользователям Mac это будет гораздо комфортнее.

Более того, даже если бы мы хотели бы заставить пользователей Mac использовать именно Ctrl +click – это было бы затруднительно. Дело в том, что обычный клик с зажатым Ctrl под Mac работает как правый клик и генерирует событие oncontextmenu , а вовсе не onclick , как под Windows/Linux.

Решение – чтобы пользователи обоих операционных систем работали с комфортом, в паре с ctrlKey нужно обязательно использовать metaKey .

В JS-коде это означает, что для удобства пользователей Mac нужно проверять if (event.ctrlKey || event.metaKey) .

Координаты в окне: clientX/Y

Все мышиные события предоставляют текущие координаты курсора в двух видах: относительно окна и относительно документа.

Пара свойств clientX/clientY содержит координаты курсора относительно текущего окна.

При этом, например, если ваше окно размером 500×500, а мышь находится в центре, тогда и clientX и clientY будут равны 250.

Можно как угодно прокручивать страницу, но если не двигать при этом мышь, то координаты курсора clientX/clientY не изменятся, потому что они считаются относительно окна, а не документа.

Проведите мышью над полем ввода, чтобы увидеть clientX/clientY :

В той же системе координат работает и метод elem.getBoundingClientRect() , возвращающий координаты элемента, а также position:fixed .

Относительно документа: pageX/Y

Координаты курсора относительно документа находятся в свойствах pageX/pageY .

Так как эти координаты – относительно левого-верхнего узла документа, а не окна, то они учитывают прокрутку. Если прокрутить страницу, а мышь не трогать, то координаты курсора pageX/pageY изменятся на величину прокрутки, они привязаны к конкретной точке в документе.

В IE8- этих свойств нет, но можно получить их способом, описанным в конце главы.

Проведите мышью над полем ввода, чтобы увидеть pageX/pageY (кроме IE8-):

В той же системе координат работает position:absolute , если элемент позиционируется относительно документа.

Некоторые браузеры поддерживают свойства event.x/y , event.layerX/layerY .

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

Особенности IE8-

Двойной клик

Все браузеры, кроме IE8-, генерируют dblclick в дополнение к другим событиям.

  • mousedown (нажал)
  • mouseup+click (отжал)
  • mousedown (нажал)
  • mouseup+click+dblclick (отжал).

IE8- на втором клике не генерирует mousedown и click .

  • mousedown (нажал)
  • mouseup+click (отжал)
  • (нажал второй раз, без события)
  • mouseup+dblclick (отжал).

Поэтому отловить двойной клик в IE8-, отслеживая только click , нельзя, ведь при втором нажатии его нет. Нужно именно событие dblclick .

Свойство which/button

В старых IE8- не поддерживалось свойство which , а вместо него использовалось свойство button , которое является 3-х битным числом, в котором каждому биту соответствует кнопка мыши. Бит установлен в 1, только если соответствующая кнопка нажата.

Чтобы его расшифровать – нужна побитовая операция & («битовое И»):

  • !!(button & 1) == true (1-й бит установлен), если нажата левая кнопка,
  • !!(button & 2) == true (2-й бит установлен), если нажата правая кнопка,
  • !!(button & 4) == true (3-й бит установлен), если нажата средняя кнопка.

Что интересно, при этом мы можем узнать, были ли две кнопки нажаты одновременно, в то время как стандартный which такой возможности не даёт. Так что, в некотором смысле, свойство button – более мощное.

Можно легко сделать функцию, которая будет ставить свойство which из button , если его нет:

Свойства pageX/pageY

В IE до версии 9 не поддерживаются свойства pageX/pageY , но их можно получить, прибавив к clientX/clientY величину прокрутки страницы.

Более подробно о её вычислении вы можете прочитать в разделе прокрутка страницы.

Мы же здесь приведём готовый вариант, который позволяет нам получить pageX/pageY для старых и совсем старых IE:

Итого

События мыши имеют следующие свойства:

  • Кнопка мыши: which (для IE8-: нужно ставить из button )
  • Элемент, вызвавший событие: target
  • Координаты, относительно окна: clientX/clientY
  • Координаты, относительно документа: pageX/pageY (для IE8-: нужно ставить по clientX/Y и прокрутке)
  • Если зажата спец. клавиша, то стоит соответствующее свойство: altKey , ctrlKey , shiftKey или metaKey (Mac).
  • Для поддержки Ctrl + click не забываем проверить if (e.metaKey || e.ctrlKey) , чтобы пользователи Mac тоже были довольны.

Задачи

Дерево: проверка клика на заголовке

Есть кликабельное JavaScript-дерево UL/LI (см. задачу Раскрывающееся дерево).

При клике на заголовке его список его детей скрывается-раскрывается. Выглядит это так: (кликайте на заголовки)

Однако, проблема в том, что скрытие-раскрытие происходит даже при клике вне заголовка, на пустом пространстве справа от него.

Как скрывать/раскрывать детей только при клике на заголовок?

В задаче Раскрывающееся дерево это решено так: заголовки завёрнуты в элементы SPAN и проверяются клики только на них. Представим на минуту, что мы не хотим оборачивать текст в SPAN , а хотим оставить как есть. Например, по соображениям производительности, если дерево и так очень большое, ведь оборачивание всех заголовков в SPAN увеличит количество DOM-узлов в 2 раза.

Решите задачу без обёртывания заголовков в SPAN , используя работу с координатами.

Исходный документ содержит кликабельное дерево.

P.S. Задача – скорее на сообразительность, однако подход может быть полезен в реальной жизни.

Подсказка

У события клика есть координаты. Проверьте по ним, попал ли клик на заголовок.

Самый глубокий узел на координатах можно получить вызовом document.elementFromPoint(clientX, clientY).

…Но заголовок является текстовым узлом, поэтому эта функция для него работать не будет. Однако это, всё же, можно обойти. Как?

Подсказка 2

Можно при клике на LI сделать временный SPAN и переместить в него текстовый узел-заголовок.

После этого проверить, попал ли клик в него и вернуть всё как было.

На шаге 3 текстовый узел вынимается обратно из SPAN , всё возвращается в исходное состояние.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *