jQuery nhận vị trí chuột trong một phần tử


165

Tôi đã hy vọng tạo ra một điều khiển trong đó người dùng có thể nhấp vào bên trong div, sau đó kéo chuột, sau đó thả chuột lên để cho biết họ muốn một cái gì đó trong bao lâu. (Cái này dành cho điều khiển lịch, vì vậy người dùng sẽ chỉ ra thời lượng của một sự kiện nhất định)

Có vẻ như cách tốt nhất để làm điều này là đăng ký một sự kiện "mousedown" trên div cha, lần lượt đăng ký một sự kiện "mousemove" trên div cho đến khi sự kiện "mouseup" được kích hoạt. Các sự kiện "mousedown" và "mouseup" sẽ xác định thời điểm bắt đầu và kết thúc của phạm vi thời gian và khi tôi theo dõi các sự kiện "mousemove", tôi có thể tự động thay đổi kích thước của phạm vi để người dùng có thể thấy những gì họ đang làm. Tôi dựa trên cơ sở này về cách các sự kiện được tạo trong lịch google.

Vấn đề tôi gặp phải là sự kiện jQuery dường như chỉ cung cấp thông tin tọa độ chuột đáng tin cậy trong toàn bộ trang. Có cách nào để phân biệt tọa độ nào trong tham chiếu đến phần tử cha không?

Biên tập:

Đây là một bức tranh về những gì tôi đang cố gắng làm: văn bản thay thế

Câu trả lời:


305

Một cách là sử dụng offsetphương thức jQuery để dịch event.pageXevent.pageYtọa độ từ sự kiện sang vị trí chuột so với cha mẹ. Đây là một ví dụ để tham khảo trong tương lai:

$("#something").click(function(e){
   var parentOffset = $(this).parent().offset(); 
   //or $(this).offset(); if you really just want the current element's offset
   var relX = e.pageX - parentOffset.left;
   var relY = e.pageY - parentOffset.top;
});

2
Có, đây là một ý tưởng tuyệt vời nếu bố cục của phần tử cha mẹ không thể / không nên thay đổi!
Mũi nhọn

2
Câu trả lời này có tính đến phần đệm / viền không?
LeeGee

10
Theo các tài liệu, phần không tính đến "các đường viền, lề hoặc phần đệm được đặt trên phần tử cơ thể". Tôi đã không gặp phải vấn đề với câu trả lời được đăng của mình đang sử dụng, nhưng có thể tốt để kiểm tra những câu trả lời được đặt.
bóng

2
Điều này không phải làm việc. offset()cũng tương đối, vì vậy nếu cha mẹ là con của yếu tố khác, điều này sẽ cho kết quả sai. Sử dụng position()thay thế.
Flash Thunder

1
@FlashThunder offset () không tương đối, ít nhất là không theo tài liệu. Ngoài ra, nó phải là thực hành tiêu chuẩn để không có bất kỳ lề hoặc đệm trên các yếu tố cơ thể.
James Watkins

18

Để có được vị trí nhấp liên quan đến yếu tố được nhấp hiện tại
Sử dụng mã này

$("#specialElement").click(function(e){
    var x = e.pageX - this.offsetLeft;
    var y = e.pageY - this.offsetTop;
}); 

2
Câu trả lời của bạn đã giúp tôi BTW, câu trả lời được chấp nhận là không. Cảm ơn :) Những gì tôi thực sự sử dụng là thế này, thay vào đó: var y = e.pageY - $(this).offset().top;Nhưng câu trả lời của bạn đã đưa tôi đi đúng hướng.
Solomon Closson

11

Tôi sử dụng đoạn mã này, nó khá hay :)

    <script language="javascript" src="http://code.jquery.com/jquery-1.4.1.js" type="text/javascript"></script>
<script language="javascript">
$(document).ready(function(){
    $(".div_container").mousemove(function(e){
        var parentOffset = $(this).parent().offset();
        var relativeXPosition = (e.pageX - parentOffset.left); //offset -> method allows you to retrieve the current position of an element 'relative' to the document
        var relativeYPosition = (e.pageY - parentOffset.top);
        $("#header2").html("<p><strong>X-Position: </strong>"+relativeXPosition+" | <strong>Y-Position: </strong>"+relativeYPosition+"</p>")
    }).mouseout(function(){
        $("#header2").html("<p><strong>X-Position: </strong>"+relativeXPosition+" | <strong>Y-Position: </strong>"+relativeYPosition+"</p>")
    });
});
</script>

9

Câu trả lời @AbdulRahim gần như đúng. Nhưng tôi đề nghị chức năng dưới đây thay thế (để tham khảo thêm):

function getXY(evt, element) {
                var rect = element.getBoundingClientRect();
                var scrollTop = document.documentElement.scrollTop?
                                document.documentElement.scrollTop:document.body.scrollTop;
                var scrollLeft = document.documentElement.scrollLeft?                   
                                document.documentElement.scrollLeft:document.body.scrollLeft;
                var elementLeft = rect.left+scrollLeft;  
                var elementTop = rect.top+scrollTop;

                x = evt.pageX-elementLeft;
                y = evt.pageY-elementTop;

                return {x:x, y:y};
            }




            $('#main-canvas').mousemove(function(e){
                var m=getXY(e, this);
                console.log(m.x, m.y);
            });

1
Cải thiện rực rỡ, tiết kiệm trong ngày của tôi.
Bud Damyanov

hầu như, thêm lề vào khung vẽ và bạn tắt bằng lề
Benn

Đây là một số mã tuyệt vời, cảm ơn bạn rất nhiều!
Stefan

7

Giải pháp này hỗ trợ tất cả các trình duyệt chính bao gồm IE. Nó cũng chăm sóc cuộn. Đầu tiên, nó lấy vị trí của phần tử so với trang một cách hiệu quả và không sử dụng hàm đệ quy. Sau đó, nó nhận được x và y của nhấp chuột liên quan đến trang và thực hiện phép trừ để có câu trả lời là vị trí liên quan đến phần tử (ví dụ phần tử có thể là hình ảnh hoặc div):

function getXY(evt) {
    var element = document.getElementById('elementId');  //replace elementId with your element's Id.
    var rect = element.getBoundingClientRect();
    var scrollTop = document.documentElement.scrollTop?
                    document.documentElement.scrollTop:document.body.scrollTop;
    var scrollLeft = document.documentElement.scrollLeft?                   
                    document.documentElement.scrollLeft:document.body.scrollLeft;
    var elementLeft = rect.left+scrollLeft;  
    var elementTop = rect.top+scrollTop;

        if (document.all){ //detects using IE   
            x = event.clientX+scrollLeft-elementLeft; //event not evt because of IE
            y = event.clientY+scrollTop-elementTop;
        }
        else{
            x = evt.pageX-elementLeft;
            y = evt.pageY-elementTop;
    }

3

Nếu bạn đặt phần tử cha của mình là "vị trí: tương đối", thì đó sẽ là "phần tử bù" cho nội dung bạn đang theo dõi các sự kiện chuột. Do đó, "vị trí ()" của jQuery sẽ liên quan đến điều đó.


Hey Pointy, cảm ơn phản hồi của bạn. Dựa trên cách diễn đạt của bạn, có vẻ như những gì bạn đang đề xuất khác với những gì jball gợi ý, nhưng tôi không hiểu làm thế nào, bạn có thể giải thích không? Cảm ơn một lần nữa
Chris Dutrow

@DutrowLLC, Pointy đang đề nghị thay đổi phong cách của phần tử cha cần có "position:relative". Vị trí jQuery sau đó sẽ báo cáo các vị trí của nó liên quan đến phần tử cha, không phải trang. Từ ngữ trong câu trả lời của tôi rất kém, nó ngụ ý rằng nó liên quan trực tiếp đến giải pháp của Pointy, nhưng đó là cách tính toán bù khi bạn không thể hoặc không muốn phụ thuộc vào thuộc tính kiểu của phần tử cha.
bóng

Vì vậy, nếu tôi đặt "vị trí: tương đối", jQuery sẽ báo cáo vị trí thay thế chính xác trong tất cả các trình duyệt? Lý do tôi hỏi là vì tài liệu jQuery dường như ngụ ý rằng vị trí chuột đáng tin cậy duy nhất trong tất cả các trình duyệt là vị trí liên quan đến chính cửa sổ trình duyệt.
Chris Dutrow

Một hộp có "vị trí: tương đối" sẽ đặt cài đặt "trên cùng" và "bên trái" (v.v.) cho các hộp con tương đối với hình chữ nhật nội dung của hộp cha mẹ tương đối.
Mũi nhọn

Tôi có thể đang làm gì đó sai, nhưng điều này dường như không hoạt động trong firefox. Tôi có "vị trí: tương đối;" được đặt trong phần cha mẹ, firefox báo cáo event.pageX và event.clientX (tương ứng với phần trên cùng, bên trái của trang) và báo cáo event.offsetX là không xác định
Chris Dutrow

2

Đây là một trong đó cũng cung cấp cho bạn vị trí phần trăm của điểm trong trường hợp bạn cần nó. https://jsfiddle.net/Themezly/2etbhw01/

function ThzhotspotPosition(evt, el, hotspotsize, percent) {
  var left = el.offset().left;
  var top = el.offset().top;
  var hotspot = hotspotsize ? hotspotsize : 0;
  if (percent) {
    x = (evt.pageX - left - (hotspot / 2)) / el.outerWidth() * 100 + '%';
    y = (evt.pageY - top - (hotspot / 2)) / el.outerHeight() * 100 + '%';
  } else {
    x = (evt.pageX - left - (hotspot / 2));
    y = (evt.pageY - top - (hotspot / 2));
  }

  return {
    x: x,
    y: y
  };
}



$(function() {

  $('.box').click(function(e) {

    var hp = ThzhotspotPosition(e, $(this), 20, true); // true = percent | false or no attr = px

    var hotspot = $('<div class="hotspot">').css({
      left: hp.x,
      top: hp.y,
    });
    $(this).append(hotspot);
    $("span").text("X: " + hp.x + ", Y: " + hp.y);
  });


});
.box {
  width: 400px;
  height: 400px;
  background: #efefef;
  margin: 20px;
  padding: 20px;
  position: relative;
  top: 20px;
  left: 20px;
}

.hotspot {
  position: absolute;
  left: 0;
  top: 0;
  height: 20px;
  width: 20px;
  background: green;
  border-radius: 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
  <p>Hotspot position is at: <span></span></p>
</div>


-1

Tôi muốn đề nghị điều này:

e.pageX - this.getBoundingClientRect().left
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.