Як дістати положення миші без подій (без переміщення миші)?


286

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


61
Нічого поганого в події руху миші. Просто в деяких випадках користувачі не рухають мишкою. Дякую за вашу відповідь.
Норберт Тамас

2
Норберт Тамас, відповідь @ SuperNova (яка не була додана до цього року) показує, що мишінтер працює на це добре, оскільки він спрацьовує при завантаженні сторінки (якщо миша знаходиться у вікні перегляду). Чи не вийшло так у 2010 році, чи просто ніхто не думав це спробувати?
Пітер Хансен

@CrescentFresh У деяких випадках (як, наприклад, сценарії користувачів) ви не хочете сповільнювати браузер, додаючи багато mousemoveподій.
Томаш Зато - Відновіть Моніку

Можливо у FF за допомогою миші, але це не в IE та Chrome.
Елад

Або в грі ваша камера рухається по ігровому світу, і персонаж дивиться на мишку (типовий стиль стрільця зверху вниз), але якщо користувач не рухає мишкою, він орієнтується на неправильну точку, коли ви рухаєтесь навколо, якщо ти покладаєшся лише на рушій миші. Однак це не велика справа, ми просто зберігаємо "світові" координати вказівника і даємо людям це запитувати.
kamranicus

Відповіді:


336

Справжня відповідь: Ні, це неможливо.

Гаразд, я тільки що придумав спосіб. Перекрийте свою сторінку подільником, який охоплює весь документ. Усередині цього створіть (скажімо) 2000 х 2000 <a>елементів (щоб :hoverпсевдоклас працював у IE 6, див.), Розміром 1 піксель. Створіть :hoverправило CSS для тих <a>елементів, які змінюють властивість (скажімо font-family). У своєму вантажному навантажувачі перегляньте кожен з 4-х мільйонів <a>елементів, перевіряючи currentStyle/ getComputedStyle()доки не знайдете той із шрифтом наведення. Екстраполюйте назад з цього елемента, щоб отримати координати в документі.

NB НЕ РОБИТИ ЦЕ .


92
ха-ха - у якийсь момент вам слід погукати і подивитися, чи зможете ви зрозуміти, скільки людей насправді реалізували це
Pointy

6
Насправді він реалізований без великого завантаження процесора (я думаю. Я його не тестував). На dom готовий створити <a> елементи за допомогою JavaScript, займіть позицію миші та видаліть усі елементи <a>. У миші у вас повинна бути інша функція, щоб зайняти положення миші. У всякому разі, це було весело.
машинобудівний вирок

21
Можливо, це можна зробити практичним за допомогою двійкового пошуку? Петля робить пару <a>елементів, що охоплюють задані прямокутники ( <img>я думаю, використовуючи абсолютне розміщення елементів розміру ), щоразу стискаючи прямокутники. Так, це смішно, але так неможливо отримати цю інформацію перед першим рухом миші.
Дарій Бекон

29
stackoverflow.com/a/8543879/27024 говорить, що вказівник не стріляє, поки миша не рухатиметься вперше. Це перетворює цю схему.
Дарій Бекон

4
@DariusBacon: Ця пов'язана відповідь здається невірною : jsbin.com/utocax/3 . Так так, такий підхід може бути практичним для деяких ситуацій.
Тім Даун

121

Редагувати 2020: Це вже не працює. Схоже, що продавці браузера виправили це. Оскільки більшість браузерів покладаються на хром, це може бути в його основі.

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

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. Таким чином, ви можете перевірити, чи користувач перебуває на вашій сторінці за допомогою курсору.


11
Здається, це єдина справді корисна відповідь, яка здається дивною. Дійсно (в останніх Firefox, Chrome та IE11) мишоцентр спрацьовує під час завантаження сторінки та забезпечує правильні координати. Чи змінилася поведінка браузера в цій галузі за останні кілька років?
Пітер Хансен

3
Насправді "мишоцентр", схоже, не додає жодної цінності. Я перевірив наступну jsfiddle в Chrome і IE, і вони не показують кординати, поки ви не покладете мишу на внутрішній документ (панель результатів): jsfiddle.net/xkpd784o/1
Mariano Desanze

1
@Proton: Перемістіть курсор миші на панелі результатів до області панелі результатів, перш ніж сторінка повністю завантажена, і не рухатись, ніж. Після завантаження сторінки негайно знає положення миші. Рух миші не потрібен. Отже, мишіцентр також звільняється, коли сторінка завантажується, а миша знаходиться в зоні документа. Тобто те, чого спочатку хотіла ОП. Ніхто інший не дає такої відповіді.
SuperNova

1
Потенційно корисним доповненням є додавання функції для mouseleaveподії, яка встановлюється xта yповертається до nullабо'undefined'
rtpax

2
chrome 68, використовуючи вищевказаний jsfiddel, сповіщення виникає при першому русі миші, а не при завантаженні, навіть якщо миша переміщена до наданої області перед завантаженням сторінки.
юнвар

84

Що ви можете зробити, це створити змінні для 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);
}

Попередній код оновлюється раз на секунду повідомленням про те, де знаходиться ваш курсор. Я сподіваюся, що це допомагає.


18
Ви читали тему цього допису? ОП запитує, як отримати координати миші без використання події. І все ж ваш пост пропонує використовувати подію onmousemove.
Джейк

53
@jake Незважаючи на те, що ОП спеціально попросила метод без подій, ця відповідь приносить користь іншим, хто прийшов сюди, шукаючи відповіді та, можливо, подолання. Крім того, я би розглядав цю відповідь частково в межах теми, оскільки, наскільки я знаю, це найкращий метод отримати положення курсору в будь-який момент часу без необхідності використовувати події безпосередньо. З цього приводу, відповідь можна було б сформулювати більше так, як констатувати факт і запропонувати шлях, щоб уникнути заїдання коментарів.
jpeltoniemi

2
@Pichan Мені це не принесло користі, бо я шукав спосіб заповнити цю cursorX/Yзмінну до того, як відбудеться якась подія.
polkovnikov.ph

дуже мало користувачів не
повели

1
Уважно, утримати слухача мишею миші може бути дорого. Я б запропонував відтворити слухача в інтервалі та знищити слухача після отримання координат.
KRB

10

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

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


9

Відповідь @Tim Down не є ефективною, якщо ви надаєте 2000 x 2000 <a>елементів:

Гаразд, я тільки що придумав спосіб. Перекрийте свою сторінку подільником, який охоплює весь документ. Усередині цього створіть (скажімо) 2 000 х 2000 елементів (щоб псевдоклас: наведіть курсор в IE 6, див.), Розміром 1 піксель. Створіть правило CSS: наведіть курсор на ті елементи, які змінюють властивість (скажімо, сімейство шрифтів). У вашому оброблювачем навантажень перегляньте кожен з 4-х мільйонів елементів, перевіривши currentStyle / getComputedStyle (), поки не знайдете той із шрифтом наведення. Екстраполюйте назад з цього елемента, щоб отримати координати в документі.

NB НЕ РОБИТИ ЦЕ.

Але вам не доведеться одночасно виводити 4 мільйони елементів, замість цього використовуйте двійковий пошук. Просто використовуйте 4 <a>елементи замість цього:

  • Крок 1. Розгляньте весь екран як початкову область пошуку
  • Крок 2: Розбийте область пошуку на 2 х 2 = 4 <a>елемента прямокутника
  • Крок 3: Використовуючи getComputedStyle()функцію, визначте, в якому прямокутнику наводиться миша
  • Крок 4: Зменшіть область пошуку до цього прямокутника і повторіть з кроку 2.

Таким чином, вам потрібно буде повторити ці дії максимум 11 разів, враховуючи, що ваш екран не ширший 2048 пікселів.

Так ви генеруєте максимум 11 х 4 = 44 <a>елементи.

Якщо вам не потрібно визначати положення миші точно до пікселя, але скажіть, що точність 10 пікселів у порядку. Ви б повторили кроки не більше 8 разів, тому вам потрібно було б намалювати максимум 8 х 4 = 32 <a>елементи.

Також генерування та знищення <a>елементів не виконується, оскільки DOM, як правило, повільно. Замість цього, ви можете просто повторно використовувати початкові 4 <a>елементів і просто налаштувати їх top, left, widthі heightяк вам прохідне кроків.

Тепер, створення 4, також <a>є надлишком. Натомість ви можете повторно використовувати той самий один <a>елемент для тестування getComputedStyle()у кожному прямокутнику. Таким чином, замість того , щоб розщепленню область пошуку в 2 х 2 <a>елементів просто повторно використовувати один <a>елемент, переміщаючи його topі leftвластивості стилю.

Отже, все, що вам потрібно, це один <a>елемент змінити його widthі heightмаксимум 11 разів, а змінити його topі leftмакс 44 рази, і ви матимете точне положення миші.


3

Найпростіше рішення, але не на 100% точне

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

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


Для мене вона повертається undefinedнезалежно. Чи можете ви пояснити, як це використовувати?
tresf

Він повернеться, undefinedколи курсор не завис жодного елемента (або коли браузер втратив фокус). Можливо, вам знадобиться встановити часовий інтервал, якщо ви тестуєте з консолі ..
StefansArya

Дякую. setTimeoutпрацювали. Я використовував jsfiddle, і ви маєте рацію, він ніколи не потрапляв на подію наведення курсора, оскільки він перемальовує DOM кожен раз, коли ви натискаєте кнопку відтворення. Я рекомендую додати цю підказку для інших.
tresf

Я не хочу точної позиції миші, але я просто хочу знати, що миша - крайній правий або крайній лівий на функцію без об'єкта події, тому ваше рішення працює в моєму випадку ... дякую вам
Swap-IOS-Android

2

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

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

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

Це не допоможе користувачам, які переходять на цю сторінку іншими способами, ніж ваша батьківська сторінка.


1

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

jsfiddle.net/5XzeE/4/


Мабуть, ці хитрощі вже не працюють, якщо користувач не має явного руху миші. :(
trusktr

1

Вам не потрібно рухати мишкою, щоб отримати місцезнаходження курсору. Місцезнаходження також повідомляється про інші події, ніж миші . Ось приклад кліку як приклад:

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

1

Опираючись на відповідь @ 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));


1

Ось моє рішення. Експорт властивостей 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


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

14
Це все ще не вимагає від користувача переміщення миші?
Пол Хіемстра

0

Я думаю, що у мене може бути розумне рішення з підрахунку дівок та пікселів

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

По суті, ми відслідковуємо фіктивний дів у будь-який час із рухом миші.

// 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);
}  
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.