Câu hỏi Xác định phần tử nào con trỏ chuột ở trên cùng trong Javascript


Tôi muốn một hàm cho tôi biết phần tử nào mà con trỏ chuột đã kết thúc.

Vì vậy, ví dụ, nếu con chuột của người dùng trên văn bản này (với id wmd-input), đang gọi window.which_element_is_the_mouse_on() sẽ có chức năng tương đương với $("#wmd-input")


76
2018-01-11 01:32


gốc




Các câu trả lời:


BẢN GIỚI THIỆU

Có một chức năng thực sự thú vị được gọi là document.elementFromPoint nó làm như thế nào

Những gì chúng ta cần là để tìm các coords x và y của chuột và sau đó gọi nó bằng cách sử dụng các giá trị đó:

var x = event.clientX, y = event.clientY,
    elementMouseIsOver = document.elementFromPoint(x, y);

document.elementFromPoint

Đối tượng sự kiện jQuery


105
2018-01-11 01:42



@TikhonJelvis: Tốt từ đây Tôi thấy nó được hỗ trợ trên IE và firefox. Nếu bạn nhận được hai bạn thường nhận được tất cả. MSDN  MDN - qwertymk
Tuyệt vời. Có cách nào để có được các coords của chuột mà không bắt một sự kiện? (Có lẽ không phải tôi giả định). Nếu điều này là không thể, thì tiếc là tôi không nghĩ phương pháp này tốt hơn event.target hay bất cứ cái gì - Tom Lehman
@ HoraceLoeb Nó không thể có được những thanh co chuột mà không đánh bắt một sự kiện. xem câu hỏi SO này để giải thích thêm - Logan Besecker
Đó là một cách kỳ lạ để làm điều đó. Nếu bạn bắt một sự kiện, tại sao không chỉ sử dụng event.target ? - pmrotule
Câu trả lời không giải thích cái gì event là, và nó như thế nào - vsync


Trong các trình duyệt mới hơn, bạn có thể thực hiện các thao tác sau:

document.querySelectorAll( ":hover" );

Điều đó sẽ cung cấp cho bạn một NodeList của các mục mà con chuột hiện đang kết thúc theo thứ tự tài liệu. Phần tử cuối cùng trong NodeList là phần tử cụ thể nhất, mỗi phần tử trước đó phải là cha, mẹ, và vân vân.


49
2018-03-07 04:36



Điều này dường như không hoạt động trong khi tôi đang kéo <li> trong khi trên đầu trang của khác <li> các yếu tố. - Seiyria
Tôi đã tạo ra một câu đố $(':hover') nhưng về cơ bản cũng giống như vậy: jsfiddle.net/pmrotule/2pks4tf6 - pmrotule
(function(){ var q = document.querySelectorAll(":hover"); return q[q.length-1]; })() - user
Tôi có một cảm giác về hiệu suất của điều này thật khủng khiếp .. gọi nó là mousemove có thể làm tổn thương hiệu suất - vsync


Mặc dù sau đây có thể không thực sự trả lời câu hỏi, vì đây là kết quả đầu tiên của googling (googler có thể không hỏi chính xác cùng một câu hỏi :), hy vọng nó sẽ cung cấp thêm một số đầu vào.

Thực tế có hai cách tiếp cận khác nhau để có được một danh sách tất cả các phần tử mà chuột hiện đang kết thúc (đối với các trình duyệt mới hơn, có lẽ):

Cách tiếp cận "cấu trúc" - Cây DOM tăng dần

Như trong câu trả lời của dherman, người ta có thể gọi

var elements = document.querySelectorAll(':hover');

Tuy nhiên, điều này giả định rằng chỉ có trẻ em sẽ che phủ tổ tiên của họ, mà thường là trường hợp, nhưng không đúng nói chung, đặc biệt là khi giao dịch với SVG nơi yếu tố trong các nhánh khác nhau của cây DOM có thể chồng lên nhau.

Cách tiếp cận "trực quan" - Dựa trên sự chồng chéo "trực quan"

Phương pháp này sử dụng document.elementFromPoint(x, y) để tìm phần tử trên cùng, tạm thời ẩn nó (vì chúng tôi khôi phục nó ngay lập tức trong cùng một ngữ cảnh, trình duyệt sẽ không thực sự hiển thị), sau đó tiếp tục tìm phần tử trên cùng thứ hai ... Trông một chút hacky, nhưng nó trả về cái gì bạn mong đợi khi có, ví dụ, anh chị em các yếu tố trong một cây occluding nhau. Vui lòng tìm bài này để biết thêm chi tiết,

function allElementsFromPoint(x, y) {
    var element, elements = [];
    var old_visibility = [];
    while (true) {
        element = document.elementFromPoint(x, y);
        if (!element || element === document.documentElement) {
            break;
        }
        elements.push(element);
        old_visibility.push(element.style.visibility);
        element.style.visibility = 'hidden'; // Temporarily hide the element (without changing the layout)
    }
    for (var k = 0; k < elements.length; k++) {
        elements[k].style.visibility = old_visibility[k];
    }
    elements.reverse();
    return elements;
}

Hãy thử cả hai, và kiểm tra lợi nhuận khác nhau của họ.


32
2018-01-11 06:40



Điều này đã giúp tôi rất nhiều. Cảm ơn @ herrlich10. Đáng ngạc nhiên, mã của bạn xử lý trường hợp với các phần tử con lồng nhau. - Vikram Deshmukh
Bạn đang chào đón @ VikramDeshmukh ~ Rất vui khi biết điều đó :) - herrlich10
Cách tiếp cận trực quan thực sự tuyệt vời! Cảm ơn! - Mikhail
Điều này cực kỳ hữu ích. Chính xác những gì tôi đang tìm kiếm. Như bạn đã nói, querySelectorAll không hoạt động trong mọi trường hợp. - noobsharp
@ herrlich10 Điều này có vẻ giống như một polyfill phong nha cho developer.mozilla.org/en-US/docs/Web/API/Document/…. Nếu API đó tồn tại trong trình duyệt được hỗ trợ của bạn, tôi nghĩ bạn có thể sử dụng nó. - dherman


Sự kiện di chuột qua bong bóng, vì vậy bạn có thể đặt một người nghe duy nhất trên cơ thể và chờ họ bong bóng lên, sau đó lấy event.target hoặc là event.srcElement:

function getTarget(event) {
    var el = event.target || event.srcElement;
    return el.nodeType == 1? el : el.parentNode;
}

<body onmouseover="doSomething(getTarget(event));">

5
2018-01-11 02:37



Trong khi bản thân tôi sử dụng các trình xử lý sự kiện phổ quát thì đây sẽ là nguồn tài nguyên đắt tiền hơn document.elementFromPoint(x, y). - John


<!-- One simple solution to your problem could be like this: -->

<div>
<input type="text" id="fname" onmousemove="javascript: alert(this.id);" />
<!-- OR -->
<input type="text" id="fname" onclick="javascript: alert(this.id);" />
</div>
<!-- Both mousemove over the field & click on the field displays "fname"-->
<!-- Works fantastic in IE, FireFox, Chrome, Opera. -->
<!-- I didn't test it for Safari. -->

4
2017-08-28 03:42



Tôi xin lỗi vì người nghèo mà bạn đã được đối xử với câu hỏi của bạn (giờ đã bị xóa). Cá nhân tôi muốn câu hỏi được phục hồi. Trong khi nó đang trên đường đóng cửa (không công bằng, theo quan điểm của tôi), tôi đã có kế hoạch bỏ phiếu để mở lại nó. Tuy nhiên, với số lượng downvotes, tôi hiểu nếu bạn chọn giữ nó. - halfer


Đoạn mã sau sẽ giúp bạn lấy phần tử của con trỏ chuột. Các phần tử kết quả sẽ hiển thị trong bảng điều khiển.

document.addEventListener('mousemove', function(e) {
    console.log(document.elementFromPoint(e.pageX, e.pageY)); 
})

4
2017-08-19 15:48



Điều này đòi hỏi con trỏ di chuyển. Gần như nó có thể được, nó không phải là những gì đang được yêu cầu ở đây. - Carles Alcolea
Không hoạt động nếu trang được cuộn. Sử dụng e.clientX và e.clientY thay vào đó (được thử nghiệm trên Firefox 59). - youen


Bạn có thể nhìn vào mục tiêu của mouseover sự kiện trên một số tổ tiên phù hợp:

var currentElement = null;

document.addEventListener('mouseover', function (e) {
    currentElement = e.target;
});

Đây là bản trình diễn.


3
2018-01-11 01:36





elementFromPoint() lấy phần tử đầu tiên trong cây DOM. Điều này chủ yếu là không đủ cho các nhà phát triển cần. Do đó có chức năng tốt đẹp này:

Document.elementsFromPoint()

Điều này trả về một mảng các đối tượng phần tử theo các điểm đã cho.

Tính năng thử nghiệm hiện tại không được tất cả các trình duyệt hỗ trợ, vì vậy bạn có thể sử dụng câu trả lời này như dự phòng

| Chrome | Firefox | IE   | Opera | Safari
| 43.0   | 46.0    | 10.0 | ?     | No support

Thông tin thêm và khả năng tương thích trình duyệt hiện tại tại đây: https://developer.mozilla.org/en-US/docs/Web/API/document/elementsFromPoint


2
2017-08-04 09:45





Mục tiêu của mousemove Sự kiện DOM là phần tử DOM cao nhất bên dưới con trỏ khi con chuột di chuyển:

(function(){
    //Don't fire multiple times in a row for the same element
    var prevTarget=null;
    document.addEventListener('mousemove', function(e) {
        //This will be the top-most DOM element under cursor
        var target=e.target;
        if(target!==prevTarget){
            console.log(target);
            prevTarget=target;
        }
    });
})();

Điều này tương tự như giải pháp @Philip Walton, nhưng không yêu cầu jQuery hoặc một setInterval.


1
2018-01-15 14:32