jQuery는 요소 내에서 마우스 위치를 얻는다


165

사용자가 div 내부를 클릭 한 다음 마우스를 끈 다음 마우스를 올려 놓아 원하는 시간을 표시 할 수있는 컨트롤을 만들고 싶었습니다. (이것은 달력 제어를위한 것이므로 사용자는 특정 이벤트의 시간을 시간 단위로 표시합니다)

이를 수행하는 가장 좋은 방법은 상위 div에 "mousedown"이벤트를 등록하고 "mouseup"이벤트가 트리거 될 때까지 div에 "mousemove"이벤트를 등록하는 것입니다. "mousedown"및 "mouseup"이벤트는 시간 범위의 시작과 끝을 정의하며 "mousemove"이벤트를 수행함에 따라 사용자가 수행중인 작업을 볼 수 있도록 범위의 크기를 동적으로 변경할 수 있습니다. Google 캘린더에서 이벤트가 생성되는 방식을 기반으로했습니다.

내가 겪고있는 문제는 jQuery 이벤트가 전체 페이지와 관련하여 신뢰할 수있는 마우스 좌표 정보 만 제공하는 것 같습니다. 부모 요소와 관련하여 좌표가 무엇인지 식별하는 방법이 있습니까?

편집하다:

내가하려는 일의 그림은 다음과 같습니다. 대체 텍스트

답변:


305

한 가지 방법은 jQuery를 사용하는 것입니다 offset변환하는 방법 event.pageXevent.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
그렇습니다. 부모 요소의 레이아웃을 변경할 수 없거나 변경해서는 안됩니다.
Pointy

2
이 답변은 패딩 / 테두리를 고려합니까?
LeeGee

10
문서에 따르면 오프셋 은 "본문 요소에 설정된 테두리, 여백 또는 패딩"을 고려하지 않습니다. 게시 된 답변에 문제가 발생하지 않았지만 설정된 답변을 확인하는 것이 좋습니다.
jball 2016 년

2
작동하지 않아도됩니다. offset()부모도 다른 요소의 자식 인 경우 잘못된 결과를 얻을 수 있습니다. position()대신 사용하십시오 .
Flash Thunder

1
@FlashThunder offset ()은 적어도 문서에 따르면 상대적이지 않습니다. 또한 body 요소에 여백이나 패딩이없는 것이 표준 관행이어야합니다.
제임스 왓킨스

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;그러나 당신의 대답은 나를 올바른 길로 인도했습니다.
Solomon 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

이것은 훌륭한 코드입니다. 대단히 감사합니다!
Stefan

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

부모 요소를 "position : relative"로 설정하면 마우스 이벤트를 추적하는 항목에 대한 "offset parent"가됩니다. 따라서 jQuery "position ()"은 이에 상대적입니다.


Pointy, 답변 해 주셔서 감사합니다. 당신의 말을 바탕으로, 당신이 제안하는 것이 jball이 제안한 것과 다른 것처럼 들리지만 어떻게 이해할 수 있습니까? 다시 한번 감사드립니다
Chris Dutrow

@DutrowLLC, Pointy는 부모 요소의 스타일을 변경하도록 제안합니다 "position:relative". 그런 다음 jQuery 위치는 페이지가 아닌 상위 요소와 관련된 위치를보고합니다. 내 대답에 대한 표현이 좋지 않습니다 .Pointy의 솔루션과 직접 관련이 있음을 의미하지만 부모 요소의 스타일 속성에 의존 할 수 없거나 원하지 않는 경우 오프셋을 계산하는 방법입니다.
jball

"position : relative"를 설정하면 jQuery가 모든 브라우저에서 관련 위치를 올바르게보고합니까? 내가 묻는 이유는 jQuery 문서가 모든 브라우저에서 신뢰할 수있는 마우스 위치가 브라우저 창 자체와 관련된 것임을 암시하는 것처럼 보였기 때문입니다.
Chris Dutrow

"position : relative"가있는 상자는 상대 부모 상자의 내용 사각형을 기준으로 하위 상자의 "상단"및 "왼쪽"(등) 설정을 만듭니다.
Pointy

뭔가 잘못하고 있지만 파이어 폭스에서는 작동하지 않는 것 같습니다. 나는 "position : relative;" 부모에서 설정 한 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>


-1

나는 이것을 제안 할 것이다 :

e.pageX - this.getBoundingClientRect().left
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.