ilyachalov (ilyachalov) wrote,
ilyachalov
ilyachalov

Categories:

JavaScript: тонкости работы с событиями мыши

В процессе чтения подраздела 3.2 «Движение мыши: mouseover/out, mouseenter/leave» второй части учебника по JavaScript я экспериментировал с браузером и сделал несколько выводов, которыми можно дополнить указанный подраздел. Эта информация может пригодиться при решении примеров к этому подразделу.

Я экспериментировал в браузере «Microsoft Edge» на движке «Chromium». В экспериментах я рассматривал не все события мыши, а только mouseover (возникает при заходе курсора мыши на HTML-элемент), mouseout (возникает при уходе курсора мыши с HTML-элемента) и mousemove (возникает при движении курсора мыши над HTML-элементом).

* * *

Вообще правила работы браузера с событиями мыши определены в спецификации, которая сейчас называется «UI Events». Аббревиатура «UI» расшифровывается как «user interaction» (по-русски «взаимодействие с пользователем»). «UI Events» по-русски означает «события при взаимодействии с пользователем» (имеется в виду взаимодействие браузера с пользователем). Эту спецификацию можно почитать по следующим ссылкам:

1. https://www.w3.org/TR/uievents/
2. https://w3c.github.io/uievents/

По первой ссылке сейчас находится спецификация «UI Events» в варианте «W3C Working Draft» (по-русски «рабочий проект», это один из этапов разработки рекомендации (эквивалент стандарта) от организации «W3C», разрабатывающей стандарты для Всемирной паутины) от 30 мая 2019 года.

По второй ссылке сейчас находится спецификация «UI Events» в варианте «Editor’s Draft» от 20 июля 2021 года. «Editor’s Draft» — это, как я понимаю, свежайший снимок спецификации от людей («редакторов»), которые в данный момент занимаются ее дальнейшей разработкой.

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

* * *

В обсуждаемом подразделе учебника меня особенно заинтересовал отдел «Пропуск элементов».

В теории, когда пользователь водит мышью по HTML-странице в области просмотра браузера, генерируются три события, перечисленные выше, которые можно обработать в скрипте на языке JavaScript. Рассматриваемые события генерируются при проведении курсором мыши над конкретным HTML-элементом в порядке mouseover-mousemove-mouseout. При этом события mouseover и mouseout генерируются по одному на HTML-элемент, а событий mousemove над одним HTML-элементом между событиями mouseover и mouseout может быть множество.

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

Я бы добавил еще к этому, что (судя по моим экспериментам):

Вывод 1. Браузер может либо полностью «пропустить» HTML-элемент, либо, как минимум, сгенерировать группу из трех событий mouseover-mousemove-mouseout (каждое из этих событий по одному, событие mousemove может быть в этом случае либо одно, либо их может быть множество). То есть у меня не получилось увидеть ситуацию, когда после захода и ухода указателя мыши с HTML-элемента сгенерировалась бы только пара событий mouseover-mouseout или mouseover-mousemove или mousemove-mouseout.

Следующий вывод может показаться очевидным, но всё же:

Вывод 2. «Пропуск» HTML-элемента более вероятен, если этот элемент маленький или тонкий. Чем больше (толще) HTML-элемент, тем менее вероятен его «пропуск».

Я замерил время между генерацией трех рассматриваемых событий на одном HTML-элементе. Для этого я применил метод Date.now(). Про этот способ можно прочитать в подразделе 5.11 «Дата и время» первой части обсуждаемого учебника.

Вывод 3. Время между рассматриваемыми событиями может быть от нуля миллисекунд (минимальное) и больше. Особенно часто промежуток в ноль миллисекунд бывает между событием mouseover и первым событием mousemove над одним и тем же HTML-элементом. Но промежуток в ноль миллисекунд между mouseover и первым mousemove бывает не всегда.

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

Еще в учебнике сказано, что свойство relatedTarget объекта с информацией о произошедшем событии для трех обсуждаемых событий мыши может быть равно значению null, когда курсор мыши резко перемещается из-за пределов области просмотра браузера на HTML-элемент (для события mouseover) или, наоборот, резко перемещается с HTML-элемента за пределы области просмотра браузера (для события mouseout).

Я бы тут еще добавил, что:

Вывод 4. Для события mousemove свойство relatedTarget объекта с информацией о произошедшем событии всегда равно значению null (об этом сказано в вышеуказанной спецификации).

Я проанализировал координаты указателя курсора мыши в момент генерации событий mouseover и mouseout. Как мне казалось, в момент события захода указателя мыши на HTML-элемент координаты указателя должны быть равны координатам пикселя, находящегося в самом внешнем ряду пикселей границы (border) HTML-элемента. А в момент события ухода указателя мыши с HTML-элемента координаты указателя, как я думал, должны быть равны координатам пикселя, тоже находящегося в самом внешнем ряду пикселей границы (border) HTML-элемента. Но это представление оказалось неверным.

Вывод 5. При событии mouseover координаты указателя мыши равны координатам пикселя, либо находящегося в самом внешнем ряду пикселей границы HTML-элемента, либо находящегося несколько в глубине HTML-элемента. Чем больше скорость движения указателя мыши, тем глубже внутри HTML-элемента находится рассматриваемый пиксель. Иллюстрация:



Я сделал снимок области просмотра браузера и увеличил его в 4 раза в графическом редакторе, чтобы можно было видеть ситуацию попиксельно. На иллюстрации видно кусочек (левый верхний угол) HTML-элемента div. У него красная граница (border) толщиной в 15 пикселей, а клиентская часть этого HTML-документа (внутренние отступы padding плюс содержимое HTML-элемента) выкрашена в серый цвет. Черной пиксельной линией я изобразил движение указателя мыши (серой стрелкой показано направление движения указателя мыши, сверху вниз, на HTML-элемент). Желтым цветом отмечены пиксели, в которых может быть сгенерировано событие mouseover в зависимости от скорости движения указателя мыши.

Вывод 6. При событии mouseout координаты указателя мыши равны координатам пикселя, либо находящегося в самом внешнем ряду пикселей границы HTML-элемента, либо уже находящегося на каком-то расстоянии за пределами HTML-элемента. Иллюстрация:



Эта иллюстрация сделана по тому же принципу, что и предыдущая. На ней видно кусочек (левый нижний угол) HTML-элемента div. Черной пиксельной линией изображено движение указателя мыши (белой стрелкой показано направление движения указателя мыши, сверху вниз, из HTML-элемента). Желтым цветом отмечены пиксели, в которых может быть сгенерировано событие mouseout в зависимости от скорости движения указателя мыши.

Можно сказать, что в данном случае у браузера как-будто есть некая инерция, события несколько «запаздывают», из-за чего функция, обрабатывающая событие, получает несколько смещенные координаты.
Tags: Образование, Программирование
Subscribe

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your IP address will be recorded 

  • 0 comments