Подтвердить что ты не робот

Событие mousemove запускается onscroll, даже если мышь не была перемещена по хромированию

Я пытался ответить на проблему с пользовательским выпадающим списком, но был оспорен непоследовательным поведением в Chrome и FF.

DEMO: http://jsfiddle.net/fyeht/ [Добавлена ​​возможность прокрутки для большей ясности]

См. ниже изображение. Элементы списка можно перемещать с помощью клавиш со стрелками.

Воспроизвести проблему:

  • Открыть консоль в Chrome (F12)
  • Нажмите на элемент в списке (вы заметили, что некоторые события вошли в консоль)
  • Используйте клавишу со стрелкой вниз, чтобы перейти к следующему элементу в списке.
  • Наконец, проблема заметна, когда вы достигнете последнего элемента в представлении и прокрутите стрелку вниз. Проверьте журнал, чтобы увидеть 'scroll', 'mouse enter' и 'mouse move' [проверить новое демо]

Проблема заключается в достижении конца рассматриваемых элементов, она прокручивается. Хотя мышь не тронута, она запускает события mouseenter и mousemove в Chrome. В FF, при прокрутке, он вызывает только mouseenter, который имеет смысл.

enter image description here

Вопрос (ы):

  • Почему mousemove срабатывает, когда мышь нетронутая?
  • Является ли это просто несогласованностью браузера? Не удалось найти документацию о событиях, вызванных при прокрутке? (никогда не знал, что это сделал)

Отправлен отчет об ошибке: https://code.google.com/p/chromium/issues/detail?id=241476

4b9b3361

Ответ 1

В вашем примере я вижу, что и Chrome, и FF запускают события DOM mouseenter, когда мышь остается нависшей над <ul>, и нажатие клавиши вниз вызывает запуск браузера для прокрутки, чтобы вывести выбранный <li>.

Однако только Chrome дополнительно запускает события mousemove. Одно из очевидных различий уже в объектах событий mouseenter, которые два раза выбраны для Chrome, значения MouseEvent.offsetX и MouseEvent.offsetY включены, тогда как в FF эти свойства undefined. Итак, когда этот ввод запускается, Chrome уже решил, что мышь "переместилась".

Поскольку значения контекста события MouseEvent.screenX и MouseEvent.screenY не изменяются между экземплярами MouseEvent, зависящими от прокрутки, можно было бы различить "искусственный" mouseenter/ mousemove и "подлинный", сохраняя эти значения из предыдущих событий.

Спецификация событий DOM

Спецификация события уровня 2 DOM для mousemove:

Событие mousemove происходит, когда указывающее устройство перемещается, когда оно находится над элементом.

Уровень 3 (рабочий черновик) по существу тот же:

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

Похоже, что это может быть связано с тем, интерпретируется ли "перемещается" относительно или нет.

Кроме того, в разделе спецификации уровня 3 для порядка событий мыши указано, что когда указатель перемещается в элемент, он запускает mouseover, mouseenter и mousemove, в этом порядке. Каждый случай, который указан, всегда содержит эти три вместе, поэтому, возможно, можно понять, что если вы собираетесь запускать событие mouseenter, вы также должны запускать mousemove событие, которое соответствует вводу элемента.

Ответ 2

Я действительно сомневаюсь, что здесь существует некорректность браузера. Вы должны создать событие mousemove, которое выводит координаты x и y. Вероятно, вы увидите, что мышь действительно двинулась немного. Если это так, попробуйте использовать плагин hoverIntent, чтобы устранить такие проблемы.

EDIT:

Используя клавиши со стрелками вверх и вниз, я теперь могу реплицировать проблему. Да, это похоже на какую-то ошибку! Бьюсь об заклад, дельта треугольника mousemove крошечная. Может быть, курсор перемещает один или два пикселя? Я бы сказал, чтобы преодолеть это, добавьте проверку функции mousemove, которая сравнивает предыдущие координаты x-y mousemove с текущими координатами x-y mousemove. Определите, если это больше, чем несколько пикселей. Если это так, вы знаете, что это настоящая mousemove. Если это меньше, вы можете это сделать как хром-ошибку.

ДАЛЬНЕЙШЕЕ ИЗДАНИЕ:

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

Ответ 3

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

Не только перемещение мыши и мыши над событиями, создаваемыми в толпе браузером, они не являются очень хорошим показателем намерений пользователей. Infact эти события являются полезным источником энтропии. В той степени, в которой есть некоторые незначительные различия, это в контексте того, насколько полезны эти "микро-события" индивидуально. Чтобы работать с ними, вы должны разработать способ фильтровать их для намерения пользователя, которое вы хотите связать с действиями более высокого уровня. Любой разумный метод, который вы выберете, чтобы понять эти события, вероятно, обнаружит эти события перемещения по прокрутке как мусор. Именно здесь ваш смысл стоит отметить и принять в ужасе. Первым этапом будет отфильтровать события на основе элементов и значений координат. Это может помочь создать модель конечного автомата. Вы можете регистрировать и регистрировать обработчики в ответ на другие события. Вы определили этот случай, когда вы хотите изменить отзывчивое состояние, если или критерии реакции, если ключевой элемент имеет полосу прокрутки. Если элемент или его родительский элемент имеет вертикальную полосу прокрутки, выталкивают движения мыши с относительно высокими значениями X.

Возможно, вы захотите также игнорировать мышь, если он стрелял с движением мыши в этом контексте. Становится нецелесообразным обрабатывать каждое из этих микро-событий по одному, даже если вы меняете состояние, регистрируя или отменяя регистрацию обработчиков. Дополнительная информация может быть извлечена путем создания буфера fifo последовательности событий. Зарегистрируйте обработчики событий, чтобы добавить новое событие в буфер. Вы также можете собирать информацию из событий таймера в этом буфере, чтобы установить больше контекста. Вы можете создать объект, который удерживает fifo в массиве. Это будет похоже на очередь, но не в том смысле, что это место, где события ждут обработки. Вместо этого ваша программа ждет вычисления шаблонов в буфере и на основе шаблонов срабатывает более высокий уровень событий, принимает или отклоняет различные типы событий и расширяет, сокращает или сохраняет содержимое буфера. Затем вы можете оценивать события перемещения для изменений в x и y, а также создавать условия, заданные при прокрутке мыши и событиях перемещения мыши, которые вы продемонстрировали.

Ответ 4

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

Представьте себе, что вы, как Земля, чашечка кофе стоят на столе как мышь, прокручиваемый список как Солнце: если вы (окно) не двигаетесь, положение чашки кофе (мышь) находится на том же месте для вас; но для Солнца (списка) он увидит, что Земля и чашка кофе движутся.