Bagaimana cara mendapatkan posisi mouse tanpa kejadian (tanpa menggerakkan mouse)?

286

Apakah mungkin untuk mendapatkan posisi mouse dengan JavaScript setelah halaman dimuat tanpa aktivitas pergerakan mouse (tanpa menggerakkan mouse)?

Norbert Tamas
sumber
61
Tidak ada yang salah dengan acara mousemove. Hanya dalam beberapa kasus pengguna tidak menggerakkan mouse. Terima kasih atas jawaban anda.
Norbert Tamas
2
Norbert Tamas, jawaban @ SuperNova (yang belum ditambahkan hingga tahun ini) menunjukkan bahwa mouseenter berfungsi dengan baik untuk ini karena ia menyala saat memuat halaman (jika mouse ada di viewport). Apakah tidak bekerja seperti itu pada tahun 2010, atau hanya tidak ada yang berpikir untuk mencobanya?
Peter Hansen
@CrescentFresh Dalam beberapa kasus (seperti skrip pengguna) Anda tidak ingin memperlambat browser dengan menambahkan banyak mousemoveacara.
Tomáš Zato - Reinstate Monica
Mungkin di FF dengan mouseover, tetapi tidak di IE dan Chrome.
Elad
Atau, dalam sebuah game, kamera Anda bergerak di sekitar dunia game dan karakter sedang melihat mouse (gaya top-down shooter) tetapi jika pengguna tidak menggerakkan mouse, itu berpusat di sekitar titik yang salah saat Anda bergerak di sekitar jika Anda hanya mengandalkan mouse. Namun, ini bukan masalah besar, kami hanya menyimpan koordinat "dunia" dari pointer dan membiarkan orang-orang menanyakannya.
kamranicus

Jawaban:

336

Jawaban sebenarnya: Tidak, itu tidak mungkin.

OK, saya baru saja memikirkan cara. Overlay halaman Anda dengan div yang mencakup seluruh dokumen. Di dalamnya, buat (katakanlah) 2.000 x 2.000 <a>elemen (sehingga :hoverpseudo-class akan bekerja di IE 6, lihat), masing-masing berukuran 1 pixel. Buat :hoveraturan CSS untuk <a>elemen - elemen yang mengubah properti (katakanlah font-family). Di penangan beban Anda, siklus melalui masing-masing 4 juta <a>elemen, memeriksa currentStyle/ getComputedStyle()sampai Anda menemukan satu dengan font hover. Ekstrapolasi kembali dari elemen ini untuk mendapatkan koordinat dalam dokumen.

NB JANGAN LAKUKAN INI .

Tim Down
sumber
92
ha ha - pada titik tertentu Anda harus berkeliling dan melihat apakah Anda dapat mengetahui berapa banyak orang yang benar-benar menerapkan ini
Pointy
6
Sebenarnya, ini dapat diterapkan tanpa harus banyak memuat CPU (saya pikir. Saya belum mengujinya). Saat siap, bangun elemen <a> dengan javascript, ambil posisi mouse dan kemudian hapus semua elemen <a>. Pada mouse Anda harus memiliki fungsi lain untuk mengambil posisi mouse. Bagaimanapun, ini lucu.
machineaddict
21
Mungkin ini bisa dibuat praktis dengan pencarian biner? Lingkaran membuat sepasang <a>elemen yang menutupi persegi panjang yang diberikan (menggunakan posisi absolut dari <img>elemen berukuran , saya kira), mengecilkan persegi panjang setiap kali. Ya, ini konyol, tetapi tidak dapat memperoleh info ini sebelum mousemove pertama.
Darius Bacon
29
stackoverflow.com/a/8543879/27024 mengatakan hover tidak akan menyala hingga mouse bergerak untuk pertama kalinya. Ini menggagalkan skema ini.
Darius Bacon
4
@DariusBacon: Jawaban tertaut itu sepertinya tidak benar: jsbin.com/utocax/3 . Jadi ya, pendekatan ini mungkin praktis untuk beberapa situasi.
Tim Down
121

Edit 2020: Ini tidak berfungsi lagi. Tampaknya begitu, bahwa vendor browser menambal ini. Karena sebagian besar browser bergantung pada kromium, itu mungkin pada intinya.

Jawaban lama: Anda juga dapat mengaitkan mouseenter (acara ini diaktifkan setelah pemuatan ulang halaman, saat kursor berada di dalam halaman). Memperluas kode yang rusak harus melakukan trik:

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

Anda juga dapat mengatur x dan y ke nol pada mouseleave-event. Jadi Anda dapat memeriksa apakah pengguna ada di halaman Anda dengan kursornya.

SuperNova
sumber
11
Ini tampaknya menjadi satu-satunya jawaban yang benar-benar berguna di sini, yang tampaknya aneh. Memang (di Firefox terbaru, Chrome dan IE11) mouseenter menyala di halaman memuat dan memberikan koordinat yang benar. Apakah perilaku peramban di area ini berubah dalam beberapa tahun terakhir?
Peter Hansen
3
Sebenarnya "mouseenter" tampaknya tidak menambah nilai apa pun. Saya menguji dengan jsfiddle berikut di Chrome dan IE, dan mereka tidak menunjukkan kordinat sampai Anda meletakkan mouse pada dokumen bagian dalam (panel hasil): jsfiddle.net/xkpd784o/1
Mariano Desanze
1
@ Proton: Gerakkan mouse Anda ke panel hasil ke area panel hasil SEBELUM halaman telah penuh dan tidak bergerak. Setelah memuat halaman segera tahu posisi mouse. Tidak diperlukan gerakan mouse. Jadi mouseenter juga dipecat, ketika halaman telah dimuat dan mouse berada di dalam area dokumen. Itulah yang diinginkan OP. Tidak ada orang lain yang memberikan jawaban ini.
SuperNova
1
Tambahan yang berpotensi bermanfaat adalah menambahkan fungsi untuk mouseleaveacara yang mengatur xdan ykembali ke nullatau'undefined'
rtpax
2
chrome 68, menggunakan jsfiddel di atas, peringatan terjadi pada gerakan mouse pertama dan tidak pada beban, bahkan jika mouse dipindahkan ke wilayah yang diberikan sebelum halaman selesai memuat.
junvar
84

Yang dapat Anda lakukan adalah membuat variabel untuk xdan ykoordinat kursor Anda, memperbaruinya setiap kali mouse bergerak dan memanggil fungsi pada interval untuk melakukan apa yang Anda butuhkan dengan posisi yang disimpan.

Kelemahan dari ini tentu saja adalah bahwa setidaknya satu gerakan awal dari mouse diperlukan untuk membuatnya bekerja. Selama kursor memperbarui posisinya setidaknya satu kali, kami dapat menemukan posisinya terlepas dari apakah ia bergerak lagi.

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

Kode sebelumnya memperbarui satu detik sekali dengan pesan di mana kursor Anda berada. Saya harap ini membantu.

JHarding
sumber
18
Apakah Anda membaca subjek posting ini? OP bertanya bagaimana cara mendapatkan koordinat mouse tanpa menggunakan acara. Namun posting Anda menyarankan menggunakan acara onmousemove.
jake
53
@ jake Meskipun OP secara khusus meminta metode non-peristiwa, jawaban ini bermanfaat bagi orang lain yang datang ke sini mencari jawaban dan mungkin solusinya. Juga, saya akan mempertimbangkan jawaban ini sebagian dalam topik karena sejauh yang saya tahu, ini adalah metode terbaik untuk mendapatkan posisi kursor pada waktu tertentu tanpa harus menggunakan acara secara langsung. Yang mengatakan, jawabannya bisa saja kata-kata sepanjang menyatakan fakta dan menawarkan jalan sekitar untuk menghindari nitpicking dalam komentar.
jpeltoniemi
2
@Pichan Itu tidak menguntungkan saya, karena saya telah mencari cara untuk mengisi cursorX/Yvariabel - variabel itu sebelum peristiwa apa pun terjadi.
polkovnikov.ph
sangat sedikit pengguna yang tidak akan menyalakan acara mouse
SuperUberDuper
1
Hati-hati, itu bisa mahal untuk menjaga pendengar ibu di sekitar. Saya menyarankan untuk menciptakan kembali pendengar dalam interval dan menghancurkan pendengar setelah Anda mendapatkan koordinat.
KRB
10

Anda dapat mencoba sesuatu yang mirip dengan yang disarankan Tim Down - tetapi alih-alih memiliki elemen untuk setiap piksel di layar, buat hanya 2-4 elemen (kotak), dan ubah lokasi, lebar, tinggi secara dinamis untuk membagi lokasi yang mungkin ada di layar dengan 2-4 secara rekursif, sehingga menemukan lokasi sebenarnya mouse dengan cepat.

Misalnya - elemen pertama mengambil setengah bagian kanan dan kiri layar, kemudian bagian atas dan bawah. Sekarang kita sudah tahu di mana seperempat layar mouse berada, dapat mengulangi - temukan seperempat ruang ini ...

AlexTR
sumber
9

Jawaban @Tim Down tidak berkinerja jika Anda merender 2.000 x 2.000 <a>elemen:

OK, saya baru saja memikirkan cara. Overlay halaman Anda dengan div yang mencakup seluruh dokumen. Di dalamnya, buat (katakanlah) elemen 2.000 x 2.000 (sehingga: kelas hover pseudo akan bekerja di IE 6, lihat), masing-masing berukuran 1 piksel. Buat CSS: aturan hover untuk elemen-elemen yang mengubah properti (katakanlah font-family). Di penangan beban Anda, siklus melalui masing-masing dari 4 juta elemen, memeriksa currentStyle / getComputedStyle () sampai Anda menemukan satu dengan font hover. Ekstrapolasi kembali dari elemen ini untuk mendapatkan koordinat dalam dokumen.

NB JANGAN LAKUKAN INI.

Tetapi Anda tidak harus membuat 4 juta elemen sekaligus, alih-alih gunakan pencarian biner. Cukup gunakan 4 <a>elemen saja:

  • Langkah 1: Pertimbangkan seluruh layar sebagai area pencarian awal
  • Langkah 2: Membagi area pencarian menjadi 2 x 2 = 4 persegi panjang <a> elemen
  • Langkah 3: Menggunakan getComputedStyle()fungsi menentukan di mana mouse persegi panjang melayang
  • Langkah 4: Kurangi area pencarian ke kotak itu dan ulangi dari langkah 2.

Dengan cara ini Anda perlu mengulangi langkah-langkah ini maks 11 kali, mengingat layar Anda tidak lebih lebar dari 2048 piksel.

Jadi, Anda akan menghasilkan maks 11 x 4 = 44 <a>elemen.

Jika Anda tidak perlu menentukan posisi mouse dengan tepat untuk piksel, tetapi katakanlah presisi 10px tidak apa-apa. Anda akan mengulangi langkah-langkah paling banyak 8 kali, jadi Anda harus menggambar maksimal 8 x 4 = 32 <a>elemen.

Juga menghasilkan dan kemudian menghancurkan <a>elemen tidak berfungsi karena DOM umumnya lambat. Sebaliknya, Anda hanya dapat menggunakan kembali awal 4 <a>elemen dan hanya menyesuaikan mereka top, left, widthdanheight seperti yang Anda loop melalui langkah-langkah.

Sekarang, membuat 4 <a>adalah kerja keras juga. Sebagai gantinya, Anda bisa menggunakan kembali <a>elemen yang sama untuk saat menguji getComputedStyle()di setiap persegi panjang. Jadi, bukannya membelah area pencarian menjadi 2 x 2 <a>elemen hanya menggunakan kembali satu <a>elemen dengan bergerak dengan topdan leftsifat gaya.

Jadi, yang Anda butuhkan adalah <a>perubahan elemen tunggal widthdan heightmaks 11 kali, dan ubah topdan leftmaks 44 kali dan Anda akan memiliki posisi mouse yang tepat.

Alex Peterson
sumber
3

Solusi paling sederhana tetapi tidak 100% akurat

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

Hasil: {top: 148, left: 62.5}
Hasilnya tergantung pada ukuran elemen terdekat dan kembali undefinedketika pengguna mengganti tab

StefansArya
sumber
Bagi saya, itu kembali undefinedterlepas. Bisakah Anda menguraikan cara menggunakannya?
tresf
Itu akan kembali undefinedketika kursor tidak melayang elemen apa pun (atau ketika browser kehilangan fokus). Anda mungkin perlu mengatur interval waktu jika Anda menguji dari konsol ..
StefansArya
Terima kasih. setTimeoutbekerja. Saya menggunakan jsfiddle dan Anda benar, itu tidak pernah mengenai hover event karena menggambar ulang DOM setiap kali Anda mengklik play. Saya akan merekomendasikan menambahkan petunjuk ini untuk orang lain.
tresf
Saya tidak ingin posisi mouse akurat, tetapi saya hanya ingin tahu bahwa mouse benar-benar ekstrem atau kiri ke fungsi tanpa objek acara sehingga solusi Anda bekerja dalam kasus saya .. terima kasih
Swap-IOS-Android
2

Saya membayangkan bahwa mungkin Anda memiliki halaman induk dengan timer dan setelah sejumlah waktu atau tugas selesai, Anda meneruskan pengguna ke halaman baru. Sekarang Anda menginginkan posisi kursor, dan karena mereka menunggu, mereka tidak perlu menyentuh mouse. Jadi lacak tetikus pada halaman induk menggunakan peristiwa standar dan berikan nilai terakhir ke halaman baru dalam variabel get atau post.

Anda dapat menggunakan kode JHarding pada halaman induk Anda sehingga posisi terbaru selalu tersedia dalam variabel global:

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

Ini tidak akan membantu pengguna yang menavigasi ke halaman ini dengan cara lain selain halaman induk Anda.


sumber
1

Saya menerapkan pencarian horizontal / vertikal, (pertama membuat div penuh dengan tautan garis vertikal yang diatur secara horizontal, kemudian membuat div penuh dengan tautan garis horizontal yang disusun secara vertikal, dan cukup melihat yang mana yang memiliki status hover) seperti ide Tim Down di atas, dan ini bekerja sangat cepat. Sayangnya, tidak berfungsi di Chrome 32 di KDE.

jsfiddle.net/5XzeE/4/

pengguna2958613
sumber
ternyata trik ini tidak lagi berfungsi kecuali ada gerakan mouse yang eksplisit oleh pengguna. :(
trusktr
1

Anda tidak perlu menggerakkan mouse untuk mendapatkan lokasi kursor. Lokasi ini juga dilaporkan pada acara lain selain mousemove . Inilah acara klik sebagai contoh:

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

Mengaitkan jawaban @ SuperNova , inilah pendekatan menggunakan kelas ES6 yang menjaga konteks agar tetap thisbenar dalam panggilan balik Anda:

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

Patrick Berkeley
sumber
1

Inilah solusi saya. Hal ekspor window.currentMouseX dan window.currentMouseY sifat Anda dapat menggunakan di mana saja. Ia menggunakan posisi elemen melayang (jika ada) pada awalnya dan sesudahnya mendengarkan gerakan mouse untuk mengatur nilai yang benar.

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

Sumber CMS Composr : https://github.com/ocproducts/composr/commit/a851c19f925be20bc16bfe016be42924989f262e#diff-b162dc9c35a97618a9674864ff511251R1202

Salman von Abbas
sumber
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;
}
Rusak
sumber
14
Bukankah ini masih mengharuskan pengguna untuk memindahkan mouse?
Paul Hiemstra
0

Saya pikir saya mungkin punya solusi yang masuk akal tanpa menghitung divs dan piksel..lol

Cukup gunakan bingkai animasi atau interval waktu suatu fungsi. Anda masih akan memerlukan acara mouse satu kali meskipun hanya untuk memulai, tetapi secara teknis Anda memposisikan ini di mana pun Anda suka.

Pada dasarnya kami melacak div boneka setiap saat tanpa gerakan mouse.

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

Di bawah ini adalah logika ..

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);
}  
Joshua
sumber