Как получить положение мыши без событий (без перемещения мыши)?

Можно ли получить позицию мыши с помощью JavaScript после загрузки страницы без какого-либо события движения мыши (без движения мыши)?


person Norbert Tamas    schedule 08.04.2010    source источник
comment
Нет ничего плохого в событии mousemove. Просто в некоторых случаях пользователи не двигают мышью. Спасибо за Ваш ответ.   -  person Norbert Tamas    schedule 08.04.2010
comment
Норберт Тамас, ответ @ SuperNova (который не был добавлен до этого года) показывает, что mouseenter отлично работает для этого, потому что он срабатывает при загрузке страницы (если мышь находится в области просмотра). Неужели в 2010 так не работало, или просто никто не подумал попробовать?   -  person Peter Hansen    schedule 23.11.2014
comment
@CrescentFresh В некоторых случаях (например, в пользовательских скриптах) вы не хотите замедлять работу браузера, добавляя много mousemove событий.   -  person Tomáš Zato - Reinstate Monica    schedule 29.11.2014
comment
Возможно в FF с наведением указателя мыши, но не в IE и Chrome.   -  person Elad    schedule 27.05.2015
comment
Или, в игре, ваша камера перемещается по игровому миру, а персонаж смотрит на мышь (типичный стиль шутера сверху вниз), но если пользователь не перемещает мышь, она центрируется не в той точке, когда вы двигаетесь, если вы полагаетесь только на движение мыши. Однако в этом нет ничего страшного, мы просто сохраняем мировые координаты указателя и позволяем людям запрашивать их.   -  person kamranicus    schedule 22.08.2015
comment
Для повышения производительности этого решения * Создайте элемент с высотой 1 пиксель и шириной 100% и добавьте: псевдокласс hover * Сканируйте сверху документа по одному пикселю за раз, чтобы найти положение Y * После получения координаты Y выполните сканирование ось X (на этот раз размер элемента может быть только 1px x 1px)   -  person Pawel    schedule 22.09.2015
comment
@Pawel Вы говорите, что когда вы перемещаете элемент, как только он оказывается под мышью, он может вызвать событие? В следующем jsfiddle оставьте указатель мыши под черной полосой и дождитесь, пока черная полоса не пройдет под ней, не двигаясь, и увидите, что события mouseover и mouseenter не срабатывают. jsfiddle.net/bowp569a.   -  person trusktr    schedule 18.02.2020
comment
@Pawel То же самое с использованием псевдоселектора :hover, но он не работает без фактического перемещения мыши: jsfiddle.net / z9w20f53   -  person trusktr    schedule 18.02.2020


Ответы (14)


Реальный ответ: нет, это невозможно.

Хорошо, я только что придумал способ. Наложите на свою страницу div, охватывающий весь документ. Внутри него создайте (скажем) 2000 x 2000 <a> элементов (чтобы псевдокласс :hover работал в IE 6, см.), Каждый размером 1 пиксель. Создайте :hover правило CSS для тех <a> элементов, которые изменяют свойство (скажем, font-family). В обработчике загрузки циклически переберите каждый из 4 миллионов элементов <a>, проверяя currentStyle / getComputedStyle(), пока не найдете тот, у которого наведен шрифт. Экстраполируйте этот элемент обратно, чтобы получить координаты в документе.

N.B. НЕ ДЕЛАЙТЕ ЭТОГО.

person Tim Down    schedule 08.04.2010
comment
ха-ха - в какой-то момент вам стоит погуглить и посмотреть, сможете ли вы выяснить, сколько людей на самом деле реализовали это - person Pointy; 08.04.2010
comment
На самом деле, это реализуемо без большой нагрузки на процессор (я думаю. Я не тестировал это). На dom ready создайте элементы ‹a› с помощью javascript, переместите курсор мыши и удалите все элементы ‹a›. На mousemouse у вас должна быть другая функция для определения положения мыши. Во всяком случае, это было весело. - person machineaddict; 16.08.2012
comment
Возможно, это можно сделать с помощью двоичного поиска? Цикл создает пару <a> элементов, покрывающих заданные прямоугольники (я полагаю, используя абсолютное позиционирование <img> элементов), каждый раз сжимая прямоугольники. Да, это смешно, но невозможно получить эту информацию до первого движения мыши. - person Darius Bacon; 29.05.2013
comment
stackoverflow.com/a/8543879/27024 говорит, что наведение не срабатывает, пока мышь не переместится в первый раз. Это мешает этой схеме. - person Darius Bacon; 29.05.2013
comment
@DariusBacon: этот связанный ответ кажется неправильным: jsbin.com/utocax/3. Так что да, этот подход может быть практичным в некоторых ситуациях. - person Tim Down; 29.05.2013
comment
@TimDown небольшая часть меня надеялась увидеть 4 миллиона элементов ‹a›, пока загружалась страница с примером jsbin: D - person Jaak Kütt; 19.04.2014
comment
Вы могли бы реализовать это намного эффективнее, используя принцип «разделяй и властвуй», например. бинарный поиск. Тогда вам нужно всего два элемента ‹a›. - person Mark K Cowan; 10.09.2014
comment
Я думаю, что могу просто подождать, пока мышь не сдвинется с места, и не поджечь процессор. - person trinalbadger587; 23.06.2015
comment
Хотя это забавное решение звучит нелепо, но работает, на самом деле это не рабочее решение. У него та же проблема, что и раньше: события наведения не возникают, когда мышь не двигается. Вы можете покрыть свою страницу парящими элементами сколько угодно, и они по-прежнему не будут зависать при обновлении страницы, пока мышь не переместится. Но тогда вы могли бы просто ответить на событие mousemove. - person timetowonder; 29.01.2016
comment
@timetowonder: Я не уверен, что это всегда было верно для всех браузеров и операционных систем. Я почти уверен, что у меня был простой пример, работающий по крайней мере в одном браузере одновременно. - person Tim Down; 29.01.2016
comment
Я не понимаю, почему за это вообще голосуют, если в той же теме есть реальный ответ. - person polkovnikov.ph; 09.02.2016
comment
@ polkovnikov.ph Когда я писал это, реального ответа не было, и если настоящий ответ работает, то с тех пор поведение браузера изменилось. Однако я согласен с тем, что это не должен быть общепринятым ответом. - person Tim Down; 10.02.2016
comment
Это в некотором роде удивительно, поскольку это явный крайний случай для SOF. С одной стороны, у вас есть четко продуманный ответ, который реально работал на момент написания, и которые [устаревшие ответы] являются частью характера исторических данных в целом. С другой стороны, это решение является совершенным взломом, в то время как в полной мере воплощает в себе чистейший дух изобретательности и изобретательности, лежащих в основе SOF! Я хочу видеть ответы, подобные этому, и я второй (или третий на данном этапе), что это не обязательно должен быть принятый ответ. - person Jacksonkr; 31.01.2019
comment
@Pointy, возможно, вам стоит поделиться одной из этих ссылок для людей, которые гуглили и нашли этот вопрос в верхней части результатов поиска. - person gillonba; 30.01.2021
comment
@gillonba, это, по сути, непрактичный шутливый ответ на вопрос, сделанный 11 лет назад. - person Pointy; 30.01.2021

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

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

var x = null;
var y = null;
    
document.addEventListener('mousemove', onMouseUpdate, false);
document.addEventListener('mouseenter', onMouseUpdate, false);
    
function onMouseUpdate(e) {
  x = e.pageX;
  y = e.pageY;
  console.log(x, y);
}

function getMouseX() {
  return x;
}

function getMouseY() {
  return y;
}

Вы также можете установить для x и y значение null при событии mouseleave. Таким образом, вы можете проверить, находится ли пользователь на вашей странице с курсором.

person SuperNova    schedule 10.04.2014
comment
Казалось бы, это единственный действительно полезный ответ, что кажется странным. Действительно (в последних версиях Firefox, Chrome и IE11) центр мыши срабатывает при загрузке страницы и предоставляет правильные координаты. Изменилось ли поведение браузера в этой области за последние несколько лет? - person Peter Hansen; 23.11.2014
comment
На самом деле, mouseenter, похоже, не добавляет никакой ценности. Я тестировал следующий jsfiddle в Chrome и IE, и они не показывают координаты, пока вы не наведете указатель мыши на внутренний документ (панель результатов): jsfiddle.net/xkpd784o/1 - person Mariano Desanze; 14.05.2015
comment
@Proton: переместите указатель мыши на панель результатов в область панели результатов ДО того, как страница будет полностью загружена, и не перемещайте чем. После загрузки страница сразу узнает положение мыши. Никакого движения мыши не требуется. Таким образом, mouseenter также запускается, когда страница загружена и мышь находится внутри области документа. То есть то, чего изначально хотела ОП. Никто другой не дает такого ответа. - person SuperNova; 15.05.2015
comment
Потенциально полезным дополнением является добавление функции для события mouseleave, которая устанавливает для x и y обратно значение null или 'undefined'. - person rtpax; 14.12.2016
comment
@ brillout.com Я только что протестировал его в Chrome 57 под Windows: работает как шарм. Что не сработало в вашем тесте? - person SuperNova; 24.04.2017
comment
chrome 68, используя jsfiddel выше, предупреждение возникает при первом перемещении мыши, а не при загрузке, даже если мышь перемещается в отображаемую область до завершения загрузки страницы. - person junvar; 04.08.2018
comment
Кажется, проблема со скрипкой (сейчас) или используемыми фреймами на jsfiddle. Помещение кода в пустой html-файл, запущенный локально или через http, для меня работает как шарм (chrome 68) - person SuperNova; 06.08.2018
comment
Не работает. Я только что тестировал пустую страницу в Chrome, Firefox и Edge. Ни mouseenter, ни mousemove не срабатывают при загрузке страницы, даже если курсор находится внутри страницы. См. Мой ответ для лучшего решения: stackoverflow.com/a/52141050/362006 - person Salman von Abbas; 03.09.2018
comment
Как и выше, я провел различные тесты в Firefox и Chrome, и это не работает при обновлении, хотя оно работает в Chrome после обновления при перемещении мыши, но это не то, что мы хотим. - person Paul Feakins; 14.01.2020
comment
Производители браузеров, кажется, исправили это. Мой ответ - с 2014 года, и он работал несколько лет. - person SuperNova; 20.01.2020

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

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

var cursor_x = -1;
var cursor_y = -1;
document.onmousemove = function(event)
{
 cursor_x = event.pageX;
 cursor_y = event.pageY;
}
setInterval(check_cursor, 1000);
function check_cursor(){console.log('Cursor at: '+cursor_x+', '+cursor_y);}

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

person JHarding    schedule 24.01.2012
comment
Вы прочитали тему этого поста? OP спрашивает, как получить координаты мыши без использования события. Тем не менее, ваш пост предлагает использовать событие onmousemove. - person jake; 18.12.2012
comment
@jake Хотя OP специально запросил метод, не связанный с событием, этот ответ принесет пользу другим, которые пришли сюда в поисках ответа и, возможно, обходного пути. Кроме того, я бы рассмотрел этот ответ частично в рамках темы, поскольку, насколько мне известно, это лучший способ получить позицию курсора в любой момент времени без необходимости напрямую использовать события. Тем не менее, ответ можно было бы сформулировать в большей степени, указав факт и предложив способ избежать придирок в комментариях. - person jpeltoniemi; 01.04.2013
comment
@Pichan Это не принесло мне пользы, потому что я искал способ заполнить эту переменную cursorX/Y до того, как произойдет какое-либо событие. - person polkovnikov.ph; 09.02.2016
comment
очень немногие пользователи не запускают события мыши - person SuperUberDuper; 30.08.2016
comment
Осторожно, содержать слушателя mousemove может быть дорого. Я бы посоветовал воссоздать слушателя в интервале и уничтожить слушателя после того, как вы получите координаты. - person KRB; 01.03.2017
comment
есть ли ссылки для подтверждения заявки @KRB? - person kevzettler; 10.11.2018

Ответ @Tim Down неэффективен, если вы визуализируете 2,000 x 2,000 <a> элементов:

Хорошо, я только что придумал способ. Наложите свою страницу на div, который покрывает весь документ. Внутри него создайте (скажем) 2 000 x 2 000 элементов (чтобы псевдокласс: hover работал в IE 6, см.), Каждый размером 1 пиксель. Создайте правило CSS: hover для тех элементов, которые изменяют свойство (скажем, font-family). В обработчике загрузки циклически переберите каждый из 4 миллионов элементов, проверяя currentStyle / getComputedStyle (), пока не найдете тот, у которого наведен шрифт. Экстраполируйте этот элемент обратно, чтобы получить координаты в документе.

N.B. НЕ ДЕЛАЙТЕ ЭТОГО.

Но вам не обязательно отображать 4 миллиона элементов одновременно, вместо этого используйте двоичный поиск. Просто используйте вместо этого 4 элемента <a>:

  • Шаг 1. Рассмотрите весь экран как начальную область поиска.
  • Шаг 2. Разделите область поиска на 2 x 2 = 4 прямоугольных <a> элемента.
  • Шаг 3. Используя функцию getComputedStyle(), определите, в каком прямоугольнике наведен курсор мыши.
  • Шаг 4: Уменьшите область поиска до этого прямоугольника и повторите, начиная с шага 2.

Таким образом, вам нужно будет повторить эти шаги не более 11 раз, учитывая, что ваш экран не шире 2048 пикселей.

Таким образом, вы сгенерируете максимум 11 x 4 = 44 <a> элементов.

Если вам не нужно определять положение мыши с точностью до пикселя, но допустим, что точность 10 пикселей - это нормально. Вы должны повторить эти шаги не более 8 раз, поэтому вам нужно будет нарисовать не более 8 x 4 = 32 <a> элементов.

Кроме того, создание и последующее уничтожение <a> элементов не выполняется, поскольку DOM обычно работает медленно. Вместо этого вы можете просто повторно использовать исходные 4 <a> элемента и просто настраивать их top, left, width и height по мере выполнения шагов.

Теперь создание 4 <a> тоже излишество. Вместо этого вы можете повторно использовать один и тот же элемент <a> при тестировании на getComputedStyle() в каждом прямоугольнике. Таким образом, вместо разделения области поиска на 2 x 2 <a> элемента просто повторно используйте один <a> элемент, перемещая его со свойствами стиля top и left.

Итак, все, что вам нужно, это один элемент <a>, измените его width и height максимум 11 раз и измените его top и left максимум 44 раза, и вы получите точное положение мыши.

person Alex Peterson    schedule 10.04.2017

Вы можете попробовать что-то похожее на то, что предложил Тим Даун, но вместо того, чтобы иметь элементы для каждого пикселя на экране, создайте всего 2-4 элемента (блока) и динамически измените их расположение, ширину и высоту, чтобы разделить все же возможные местоположения на экране. на 2-4 рекурсивно, таким образом быстро находя реальное местоположение мыши.

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

person AlexTR    schedule 11.02.2015

Самое простое решение, но не на 100% точное

$(':hover').last().offset()

Результат: {top: 148, left: 62.5}
Результат зависит от размера ближайшего элемента и возвращает undefined, когда пользователь переключил вкладку

person StefansArya    schedule 10.01.2018
comment
Для меня он независимо возвращает undefined. Не могли бы вы рассказать, как это использовать? - person tresf; 08.03.2018
comment
Он вернет undefined, когда курсор не наведен на какой-либо элемент (или когда браузер потерял фокус). Вам может потребоваться установить временной интервал, если вы тестируете с консоли. - person StefansArya; 10.03.2018
comment
Спасибо. setTimeout работал. Я использовал jsfiddle, и вы правы, он никогда не запускал событие зависания, потому что он перерисовывает DOM каждый раз, когда вы нажимаете кнопку воспроизведения. Я бы порекомендовал добавить эту подсказку другим. - person tresf; 10.03.2018
comment
Мне не нужно точное положение мыши, но я просто хочу знать, что мышь находится в крайнем правом или крайнем левом положении без объекта события, поэтому ваше решение работает в моем случае ... спасибо - person Swap-IOS-Android; 30.10.2018

Вот мое решение. Он экспортирует свойства window.currentMouseX и window.currentMouseY, которые можно использовать где угодно. Сначала он использует позицию наведенного элемента (если есть), а затем слушает движения мыши, чтобы установить правильные значения.

(function () {
    window.currentMouseX = 0;
    window.currentMouseY = 0;

    // Guess the initial mouse position approximately if possible:
    var hoveredElement = document.querySelectorAll(':hover');
    hoveredElement = hoveredElement[hoveredElement.length - 1]; // Get the most specific hovered element

    if (hoveredElement != null) {
        var rect = hoveredElement.getBoundingClientRect();
        // Set the values from hovered element's position
        window.currentMouseX = window.scrollX + rect.x;
        window.currentMouseY = window.scrollY + rect.y;
    }

    // Listen for mouse movements to set the correct values
    window.addEventListener('mousemove', function (e) {
        window.currentMouseX = e.pageX;
        window.currentMouseY = e.pageY;
    }, /*useCapture=*/true);
}())

Composr CMS Источник: https://github.com/ocproducts/composr/фиксация/a851c19f925be20bc16bfe016be42924989f262e#дифф-b162dc9c35a97618a96748639ff41251R1202

person Salman von Abbas    schedule 02.09.2018

Я реализовал поиск по горизонтали / вертикали (сначала сделайте div, полный ссылок с вертикальными линиями, расположенными по горизонтали, затем сделайте div, полный ссылок с горизонтальными линиями, расположенных вертикально, и просто посмотрите, какая из них находится в состоянии наведения), как идея Тима Дауна выше, и работает довольно быстро. К сожалению, не работает в Chrome 32 на KDE.

jsfiddle.net/5XzeE/4/

person user2958613    schedule 06.11.2013
comment
очевидно, эти уловки больше не работают, если пользователь явно не перемещает мышь. :( - person trusktr; 18.02.2020

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

document.body.addEventListener('click',function(e)
{
    console.log("cursor-location: " + e.clientX + ',' + e.clientY);
});
person Lonnie Best    schedule 28.06.2017

Опираясь на ответ @ SuperNova, вот подход с использованием классов ES6, который сохраняет контекст для this правильным в вашем обратном вызове:

class Mouse {
  constructor() {
    this.x = 0;
    this.y = 0;
    this.callbacks = {
      mouseenter: [],
      mousemove: [],
    };
  }

  get xPos() {
    return this.x;
  }

  get yPos() {
    return this.y;
  }

  get position() {
    return `${this.x},${this.y}`;
  }

  addListener(type, callback) {
    document.addEventListener(type, this); // Pass `this` as the second arg to keep the context correct
    this.callbacks[type].push(callback);
  }

  // `handleEvent` is part of the browser's `EventListener` API.
  // https://developer.mozilla.org/en-US/docs/Web/API/EventListener/handleEvent
  handleEvent(event) {
    const isMousemove = event.type === 'mousemove';
    const isMouseenter = event.type === 'mouseenter';

    if (isMousemove || isMouseenter) {
      this.x = event.pageX;
      this.y = event.pageY;
    }

    this.callbacks[event.type].forEach((callback) => {
      callback();
    });
  }
}

const mouse = new Mouse();

mouse.addListener('mouseenter', () => console.log('mouseenter', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove A', mouse.position));
mouse.addListener('mousemove', () => console.log('mousemove B', mouse.position));

person Patrick Berkeley    schedule 02.02.2018

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

Вы можете использовать код JHarding на своей родительской странице, чтобы последняя позиция всегда была доступна в глобальной переменной:

var cursorX;
var cursorY;
document.onmousemove = function(e){
    cursorX = e.pageX;
    cursorY = e.pageY;
}

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

person Community    schedule 17.10.2013

Не положение мыши, но, если вы ищете текущее положение курсора (для таких случаев, как получение последнего набранного символа и т. Д.), То нижеприведенный фрагмент работает нормально.
Это даст вам курсор. индекс, относящийся к текстовому контенту.

window.getSelection().getRangeAt(0).startOffset
person GorvGoyl    schedule 11.12.2020

Я думаю, что у меня может быть разумное решение без подсчета div и пикселей .. lol

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

По сути, мы постоянно отслеживаем фиктивный div без движения мыши.

// create a div(#mydiv) 1px by 1px set opacity to 0 & position:absolute;

Ниже приведена логика ..

var x,y;


$('body').mousemove(function( e ) {

    var x = e.clientX - (window.innerWidth / 2);
    var y = e.clientY - (window.innerHeight / 2);
 }


function looping (){

   /* track my div position 60 x 60 seconds!
      with out the mouse after initiation you can still track the dummy div.x & y
      mouse doesn't need to move.*/

   $('#mydiv').x = x;    // css transform x and y to follow 
   $('#mydiv)'.y = y;

   console.log(#mydiv.x etc)

   requestAnimationFrame( looping , frame speed here);
}  
person joshua    schedule 18.01.2019

person    schedule
comment
Разве для этого не требуется, чтобы пользователь двигал мышью? - person Paul Hiemstra; 09.11.2012
comment
Да, но только первый ход. Затем, когда он переместился, мы уже знаем пиксель X Y - person mmonteirocl; 05.11.2020