jQuery รับตำแหน่งเมาส์ภายในองค์ประกอบ


165

ฉันหวังที่จะสร้างตัวควบคุมที่ผู้ใช้สามารถคลิกภายใน div จากนั้นลากเมาส์แล้วปล่อยให้เมาส์เพื่อระบุระยะเวลาที่พวกเขาต้องการบางสิ่งบางอย่าง (นี่คือการควบคุมปฏิทินดังนั้นผู้ใช้จะแสดงความยาวในเวลาของเหตุการณ์บางอย่าง)

ดูเหมือนว่าวิธีที่ดีที่สุดในการทำเช่นนี้ก็คือการลงทะเบียนเหตุการณ์ "mousedown" ใน div parent ซึ่งจะลงทะเบียนเหตุการณ์ "mousemove" บน div จนกระทั่งเหตุการณ์ "mouseup" ถูกเรียกใช้ เหตุการณ์ "mousedown" และ "mouseup" จะกำหนดการเริ่มต้นและสิ้นสุดของช่วงเวลาและเมื่อฉันติดตามเหตุการณ์ "mousemove" ฉันสามารถเปลี่ยนขนาดของช่วงแบบไดนามิกเพื่อให้ผู้ใช้สามารถเห็นสิ่งที่พวกเขากำลังทำอยู่ ฉันใช้วิธีนี้ในการสร้างกิจกรรมใน Google ปฏิทิน

ปัญหาที่ฉันมีคือเหตุการณ์ jQuery ดูเหมือนว่าจะให้ข้อมูลพิกัดเมาส์ที่เชื่อถือได้เท่านั้นโดยอ้างอิงกับทั้งหน้า มีวิธีใดที่จะมองเห็นว่าพิกัดอ้างอิงกับองค์ประกอบหลักหรือไม่?

แก้ไข:

นี่คือภาพสิ่งที่ฉันพยายามทำ: ข้อความแสดงแทน

คำตอบ:


305

วิธีหนึ่งคือการใช้offsetวิธีการjQuery เพื่อแปลevent.pageXและevent.pageYพิกัดจากเหตุการณ์ไปยังตำแหน่งเมาส์ที่สัมพันธ์กับผู้ปกครอง นี่คือตัวอย่างสำหรับการอ้างอิงในอนาคต:

$("#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
ใช่นี่เป็นความคิดที่ดีถ้าเลย์เอาต์ขององค์ประกอบหลักไม่สามารถ / ไม่ควรเปลี่ยน!
แหลม

2
คำตอบนี้คำนึงถึงช่องว่างภายใน / ขอบหรือไม่?
LeeGee

10
ตามเอกสารนั้นการชดเชยไม่มีบัญชี "สำหรับขอบระยะขอบหรือช่องว่างภายในที่ตั้งไว้ในองค์ประกอบของร่างกาย" ฉันไม่ได้พบปัญหากับคำตอบที่โพสต์ไว้ แต่อาจจะดีสำหรับการตรวจสอบการตั้งค่าเหล่านั้น
jball

2
สิ่งนี้ไม่ต้องทำงาน offset()สัมพันธ์กันดังนั้นหากผู้ปกครองเป็นลูกขององค์ประกอบอื่น ๆ สิ่งนี้จะให้ผลลัพธ์ที่ผิด ใช้position()แทน
Flash Thunder

1
@FlashThunder offset () ไม่สัมพันธ์กันอย่างน้อยไม่เป็นไปตามเอกสาร นอกจากนี้ควรเป็นวิธีปฏิบัติมาตรฐานที่จะไม่มีขอบหรือช่องว่างภายในองค์ประกอบของร่างกาย
James Watkins

18

ในการรับตำแหน่งของการคลิกที่สัมพันธ์กับองค์ประกอบที่ถูกคลิกในปัจจุบัน
ใช้รหัสนี้

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

2
คำตอบของคุณช่วยฉัน BTW คำตอบที่ยอมรับไม่ได้ ขอบคุณ :) สิ่งที่ฉันใช้จริงคือแทน: var y = e.pageY - $(this).offset().top;แต่คำตอบของคุณทำให้ฉันในเส้นทางที่ถูกต้อง
โซโลมอน Closson

11

ฉันใช้รหัสนี้มันค่อนข้างดี :)

    <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

@AbdulRahim คำตอบนั้นถูกต้องเกือบ แต่ฉันขอแนะนำฟังก์ชั่นด้านล่างแทน (สำหรับการอ้างอิงเพิ่มเติม):

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
การปรับปรุงที่ยอดเยี่ยมบันทึกวันของฉัน
Bud Damyanov

เกือบจะเพิ่มระยะขอบให้กับผืนผ้าใบและคุณถูกปิดโดยขอบ
Benn

นี่เป็นโค้ดที่ยอดเยี่ยมมากขอบคุณมาก!
สเตฟาน

7

โซลูชันนี้รองรับเบราว์เซอร์หลักทั้งหมดรวมถึง IE นอกจากนี้ยังดูแลการเลื่อน ก่อนอื่นจะดึงตำแหน่งขององค์ประกอบที่สัมพันธ์กับหน้าอย่างมีประสิทธิภาพและไม่ต้องใช้ฟังก์ชันเรียกซ้ำ จากนั้นจะได้รับ x และ y ของการคลิกเมาส์สัมพันธ์กับหน้าและทำการลบเพื่อรับคำตอบซึ่งเป็นตำแหน่งที่สัมพันธ์กับองค์ประกอบ (องค์ประกอบสามารถเป็นภาพหรือ 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

หากคุณทำให้องค์ประกอบหลักของคุณเป็น "ตำแหน่ง: สัมพัทธ์" ก็จะเป็น "ผู้ปกครองชดเชย" สำหรับสิ่งที่คุณติดตามกิจกรรมเมาส์ ดังนั้น jQuery "position ()" จะสัมพันธ์กับสิ่งนั้น


สวัสดี Pointy ขอบคุณสำหรับคำตอบของคุณ จากคำพูดของคุณดูเหมือนว่าสิ่งที่คุณกำลังแนะนำนั้นแตกต่างจากสิ่งที่ jball แนะนำ แต่ฉันไม่เข้าใจว่าคุณสามารถอธิบายรายละเอียดได้อย่างไร ขอขอบคุณอีกครั้ง
Chris Dutrow

@DutrowLLC "position:relative"ปลายแหลมจะแนะนำการเปลี่ยนแปลงรูปแบบขององค์ประกอบหลักที่จะมี จากนั้นตำแหน่ง jQuery จะรายงานตำแหน่งที่สัมพันธ์กับองค์ประกอบหลักไม่ใช่หน้าเว็บ ถ้อยคำในคำตอบของฉันไม่ดีมันก็หมายความว่ามันเกี่ยวข้องโดยตรงกับวิธีการแก้ปัญหาของ Pointy แต่มันเป็นวิธีการคำนวณออฟเซ็ตเมื่อคุณไม่สามารถหรือไม่ต้องการที่จะขึ้นอยู่กับสไตล์ขององค์ประกอบหลัก
jball

ดังนั้นถ้าฉันตั้ง "ตำแหน่ง: ญาติ" jQuery จะรายงานตำแหน่งความสัมพันธ์อย่างถูกต้องในเบราว์เซอร์ทั้งหมด? เหตุผลที่ฉันถามก็เพราะเอกสาร jQuery ดูเหมือนจะบ่งบอกว่าตำแหน่งเมาส์ที่เชื่อถือได้เพียงอย่างเดียวในเบราว์เซอร์ทั้งหมดเป็นสิ่งที่เกี่ยวข้องกับหน้าต่างเบราว์เซอร์เอง
Chris Dutrow

กล่องที่มี "ตำแหน่ง: สัมพัทธ์" จะทำให้การตั้งค่า "ด้านบน" และ "ซ้าย" (ฯลฯ ) สำหรับกล่องลูกโดยสัมพันธ์กับสี่เหลี่ยมผืนผ้าเนื้อหาของกล่องหลัก
Pointy

ฉันอาจจะทำสิ่งผิดปกติ แต่สิ่งนี้ดูเหมือนจะไม่ทำงานใน firefox ฉันมี "ตำแหน่ง: ญาติ;" ตั้งค่าในพาเรนต์, firefox รายงาน event.pageX และ event.clientX เหมือนกัน (เทียบกับด้านบน, ด้านซ้ายของหน้า) และรายงาน event.offsetX ตามที่ไม่ได้กำหนด
Chris Dutrow

2

นี่คือสิ่งที่ให้ตำแหน่งเปอร์เซ็นต์ของจุดในกรณีที่คุณต้องการ 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>


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.