2010-04-08 4 views
208

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

+3

Неа! Зачем? Что случилось с подключением события mousemove? –

+41

Ничего плохого в событии mousemove. В некоторых случаях пользователи не перемещают мышь. Спасибо за Ваш ответ. –

+2

Норберт Тамас, @ ответ SuperNova (который не был добавлен до этого года) показывает, что mouseenter отлично работает для этого, потому что он срабатывает при загрузке страницы (если мышь находится в окне просмотра). Разве это не сработало так в 2010 году, или это просто, что никто не думал попробовать? –

ответ

252

Настоящий ответ: Нет, это невозможно.

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

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

+67

ха-ха - в какой-то момент вы должны google вокруг и посмотреть, можете ли вы выяснить, сколько людей действительно реализовало это. – Pointy

+24

Упрощенный, только для чистое веселье. –

73

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

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

var cursorX; 
var cursorY; 
document.onmousemove = function(e){ 
    cursorX = e.pageX; 
    cursorY = e.pageY; 
} 
setInterval(checkCursor, 1000); 
function checkCursor(){ 
    alert("Cursor at: " + cursorX + ", " + cursorY); 
} 

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

+17

Вы читали тему этого сообщения? OP спрашивает, как получить координаты мыши без использования события. Однако ваш пост предполагает использование события onmousemove. – jake

+44

@jake Хотя OP специально запросил метод, не связанный с событиями, этот ответ приносит пользу другим, которые пришли сюда, чтобы найти ответ и, возможно, обходной путь. Кроме того, я бы рассмотрел этот ответ частично в теме, поскольку, насколько я знаю, это лучший способ получить позицию курсора в любой момент времени, не используя непосредственно события. Тем не менее, ответ мог бы быть сформулирован более подробно с указанием факта и предлагать способ избежать комментариев в комментариях. – jpeltoniemi

+1

@Pichan Мне это не помогло, потому что я искал способ заполнить эту переменную 'cursorX/Y' до того, как произойдет какое-либо событие. –

0
var x = 0; 
var y = 0; 

document.addEventListener('mousemove', onMouseMove, false) 

function onMouseMove(e){ 
    x = e.clientX; 
    y = e.clientY; 
} 

function getMouseX() { 
    return x; 
} 

function getMouseY() { 
    return y; 
} 
+12

Разве это не требует от пользователя перемещения мыши? –

2

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

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

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

Это не поможет пользователям, что перемещаться на этой странице, кроме родителя средств стр.

1

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

jsfiddle.net/5XzeE/4/

+2

Не работает для меня в Firefox 28. –

78

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

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; 
} 

function getMouseX() { 
    return x; 
} 

function getMouseY() { 
    return y; 
} 

Вы также можете установить й и у к нулю на MouseLeave-событии. Таким образом, вы можете проверить, находится ли пользователь на вашей странице с помощью курсора.

+10

Это, кажется, единственный действительно полезный ответ здесь, что кажется странным. Действительно (в последних версиях Firefox, Chrome и IE11), mouseenter запускается при загрузке страницы и предоставляет правильные координаты. Изменено ли поведение браузера в этой области за последние несколько лет? –

+1

На самом деле «mouseenter», похоже, не добавляет никакого значения.Я протестировал со следующим jsfiddle в Chrome и IE, и они не отображают шнуры, пока вы не поместите мышь во внутренний документ (панель результатов): http://jsfiddle.net/xkpd784o/1/ –

+1

@Proton: Переместите указатель мыши на панель результатов в область конечной панели. ПЕРВАЯ страница полностью загружена и не перемещается. После onload страница сразу же знает положение мыши. Движение мыши не требуется. Таким образом, mouseenter также запускается, когда страница загружается, а мышь находится внутри области документа. То есть, чего первоначально хотел ОП. Никто другой не дает такого ответа. – SuperNova

8

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

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

ответа
3

@ Тим Дауна не производительный, если сделать 2000 х 2000 <a> элементов:

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

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

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

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

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

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

Если вам не нужно определять положение мыши точно в пиксель, но скажите, что точность 10px в порядке. Вы повторите шаги не более 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 раз, и вы будете иметь точное положение мыши.

0

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

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

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

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

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

+0

Для меня он возвращает 'undefined' независимо. Можете ли вы рассказать о том, как использовать это? – tresf

+0

Он будет возвращать 'undefined', если курсор не зависал ни один элемент (или когда браузер потерял фокус). Вам может потребоваться установить временной интервал, если вы тестируете консоль. – StefansArya

+0

Спасибо. 'setTimeout' работал. Я использовал jsfiddle, и вы правы, он никогда не попадал в событие hover, потому что он перерисовывает DOM каждый раз, когда вы нажимаете play. Я бы рекомендовал добавить этот намек другим. – tresf

0

Riffing on @SuperNova's answer, вот подход, использующий классы 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));