it-swarm.com.ru

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

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

244
Norbert Tamas

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

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

Нотабене НЕ ДЕЛАЙТЕ ЭТОГО.

303
Tim Down

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

109
SuperNova

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

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

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

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

79
JHarding

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

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

9
AlexTR

Ответ @Tim Down будет бесполезным, если вы отобразите 2000 x 2000 элементов <a>:

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

Нотабене НЕ ДЕЛАЙТЕ ЭТОГО.

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

  • Шаг 1: Рассмотрим весь экран как начальную область поиска
  • Шаг 2: Разделите область поиска на элементы 2 x 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 раз, и у вас будет точное положение мыши.

4
Alex Peterson

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

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

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

2
StefansArya

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

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

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

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

2
user2892032

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

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

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

jsfiddle.net/5XzeE/4/

1
user2958613

Вот мое решение. Он экспортирует 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
    document.addEventListener('mousemove', function (e) {
        window.currentMouseX = e.pageX;
        window.currentMouseY = e.pageY;
    });
}())

Composr CMS Источник: https://github.com/ocproducts/composr/commit/a851c19f925be20bc16bfe016be42924989f262e#diff -b162dc9c35a97618a96748639ff41251R1202

1
Salman Abbas

Я думаю, что у меня может быть разумное решение без подсчета 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);
}  
0
joshua

Обращаясь к ответ @ 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));
0
Patrick Berkeley
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;
}
0
Corrupted