요소를 기준으로 마우스 위치 찾기


244

캔버스를 사용하여 작은 그림 앱을 만들고 싶습니다. 캔버스에서 마우스의 위치를 ​​찾아야합니다.


2
전체 솔루션 : acko.net/blog/…
edA-qa mort-ora-y

3
나는 얼마나 짧은 지 사랑하지만이 게시물의 모든 것을 설명합니다.
dwjohnston

이것은 정말 오래되었지만 방금 GitHub 프로젝트를 시작했습니다. 그 중에서도 무엇보다도 필요한 것을 정확하게 수행합니다. brainlessdeveloper.com/mouse-move-interaction-spot-js
Fausto NA

답변:


177

JQuery를 사용하는 사람들의 경우 :

경우에 따라 이벤트가 첨부 된 중첩 요소가있는 경우 브라우저에서 상위 요소로 인식하는 내용을 이해하기 어려울 수 있습니다. 여기서 부모를 지정할 수 있습니다.

마우스 위치를 가져 와서 부모 요소의 오프셋 위치에서 빼십시오.

var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;

스크롤 창 내 페이지에서 마우스 위치를 가져 오려는 경우 :

var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();

또는 페이지와 관련된 위치 :

var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();

다음 성능 최적화에 유의하십시오.

var offset = $('#element').offset();
// Then refer to 
var x = evt.pageX - offset.left;

이런 식으로 JQuery는 #element각 줄 을 찾을 필요가 없습니다 .

최신 정보

getBoundingClientRect ()를 지원하는 브라우저를 위해 아래 @anytimecoder의 최신 JavaScript 전용 버전이 있습니다 .


7
@ben에서 효과가 있었습니까? "정답"또는 여전히 효과가없는 것에 대한 의견에 감사드립니다. 어쩌면 내가 더 도울 수 있습니다.
sparkyspider

8
매우 느린 코드를 원하지 않는 한 이벤트 핸들러에서 $ ( 'selector')를 사용하지 마십시오. 요소를 미리 선택하고 처리기에서 미리 선택된 참조를 사용하십시오. $ (window)와 동일하게 한 번 수행하고 캐시하십시오.
오스틴 프랑스

2
위의 코드를 복사하여 복사하는 경우 다음을 수정해야 var y = (evt.pageY - $('#element').offset().left) + $(window).scrollTop();합니다.var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();
Raj Nathani

77
질문이 jQuery와 관련이 없기 때문에 어떻게 대답 할 수 있습니까?
FlorianB

2
@Black 그러나 일부 사람들은 jquery가 환경에서 호환되지 않을 수 있기 때문에 jquery 대신 javascript로 질문합니다.
dbrree

307

복사 / 붙여 넣을 수있는 jQuery가없는 답변을 찾지 못 했으므로 여기에 사용 된 솔루션이 있습니다.

function clickEvent(e) {
  // e = Mouse click event.
  var rect = e.target.getBoundingClientRect();
  var x = e.clientX - rect.left; //x position within the element.
  var y = e.clientY - rect.top;  //y position within the element.
}

전체 예제의 JSFiddle


2
이 방법으로 정수 값을 보장 하려면 경계 사각형반올림 해야합니다 .
Jake Cobb

2
새로운 편집은 (는 clientX / Y 사용) 문제 스크롤 수정해야
에릭 Koopmans

6
이 답변은 투표되어야합니다. anytimecoder와 @ErikKoopmans에게 감사합니다.
Ivan

3
PSA : @mpen의 의견은 더 이상 사용되지 않습니다. 이 방법은 스크롤이있는 경우에도 작동합니다. 자신의 바이올린의 업데이트 된 버전을 참조하십시오 jsfiddle.net/6wcsovp2
Xharlie

4
감사합니다! 한 가지 참고 사항 : e.currentTargete.target이 아닌 이 필요합니다 . 그렇지 않으면, 어린이 요소가 영향을 미칩니다
Maxim Georgievskiy

60

다음은 캔버스 요소에 대한 마우스 위치 관계를 계산합니다.

var example = document.getElementById('example'); 
example.onmousemove = function(e) { 
    var x = e.pageX - this.offsetLeft; 
    var y = e.pageY - this.offsetTop; 
}

이 예에서 this받는 지칭 example요소와 e는 IS onmousemove이벤트.


83
어쩌면 나지만 키워드 "this"를 사용하는 두 줄의 코드가 컨텍스트가 없습니까?
Deratrius

9
확실히 부족한 상황. 'e'는 이벤트이고 'this'는 이벤트와 관련된 요소입니다. var example = document.getElementById('example'); example.onmousemove = function(e) { var X = e.pageX - this.offsetLeft; var Y = e.pageY - this.offsetTop; }
Nick Bisby

22
일부 하위 요소가 상대 또는 절대 위치를 사용하는 경우에는 작동하지 않습니다.
edA-qa mort-ora-y

12
당신은 밖으로 전환 할 수 있습니다 thise.currentTarget당신이에 이벤트 리스너를 추가 한 요소의 위치를 얻을 것이다.
Linus Unnebäck

2
이것은 위치 가 전체 요소가 아닌 요소 의 보이는 부분과 관련이있는 것으로 보입니다 . 뷰포트에서 요소의 일부를 볼 수없고 스크롤 막대 등이있는 경우이를 수용 할 수있는 방법이 있습니까?
frabjous

37

순수 자바 스크립트에는 참조 요소가 다른 위치에 중첩되어 절대 위치를 지정할 수있는 경우 상대 좌표를 반환하는 대답이 없습니다. 이 시나리오에 대한 해결책은 다음과 같습니다.

function getRelativeCoordinates (event, referenceElement) {

  const position = {
    x: event.pageX,
    y: event.pageY
  };

  const offset = {
    left: referenceElement.offsetLeft,
    top: referenceElement.offsetTop
  };

  let reference = referenceElement.offsetParent;

  while(reference){
    offset.left += reference.offsetLeft;
    offset.top += reference.offsetTop;
    reference = reference.offsetParent;
  }

  return { 
    x: position.x - offset.left,
    y: position.y - offset.top,
  }; 

}

3
나는 그것이 계정에 소요 생각하지 않는다 html요소 오프셋
apieceofbart

3
대체 : 조금 변화, 컨테이너를 스크롤과 함께 좋은 작품 while(reference !== undefined)으로 while(reference). Chrome에서는 적어도 offsetParent가로 끝나지 undefined않고 null. 그냥 여부를 확인 referencetruthy 그것이 모두 작동 보장 것이다 undefined하고 null.
blex

offsetParent다른 상황에서도 매우 유용한 것으로 판명 된 부동산 이 있다는 사실을 알려주므로 +1을 더 줄 것입니다 !
FonzTech

일반적으로, 정의되지 않은 검사는 나쁜 생각입니다.
Juan Mendes

난 당신이 뺄 필요가 있다고 생각 scrollLeft하고 scrollTop스크롤 후손을 보상 할 수 있습니다.
로버트

20

이 문제의 난이도에 대한 자세한 내용은 http://www.quirksmode.org/js/events_properties.html#position에서 확인할 수 있습니다 .

여기에 설명 된 기술을 사용하면 문서에서 마우스 위치를 찾을 수 있습니다. 그런 다음 요소의 경계 상자 안에 있는지 확인 element.getBoundingClientRect()하면 다음 속성을 가진 객체를 반환하는 을 호출 하여 찾을 수 있습니다 { bottom, height, left, right, top, width }. 거기에서 요소 내부 에서조차 발생했는지 여부를 알아내는 것은 사소한 일입니다.


1
슬프게도, 어떤 종류의 회전이 진행되면 이것이 실패합니다
Eric

17

나는이 모든 솔루션을 시도했으며 매트릭스 변환 컨테이너 (panzoom 라이브러리)를 사용한 특수 설정으로 인해 아무것도 작동하지 않았습니다. 확대 / 축소 및 이동 한 경우에도 올바른 값을 반환합니다.

mouseevent(e) {
 const x = e.offsetX,
       y = e.offsetY
}

그러나 방해 요소가없는 경우에만. CSS를 사용하여 이벤트에 '보이지 않게'만들어서 우회 할 수 있습니다.

.child {
   pointer-events: none;
}

3
2019 년에는이 방법이 꼭 필요한 방법입니다. 다른 답변에는 모두 오래된 크루 프티 수하물이 들어 있습니다.
Colin D

1
@ColinD 감사합니다! IE11에서도 작동한다는 것을 추가하는 것을 잊었습니다.
Fabian von Ellerts

이것은 나를 위해 일했습니다. 그러나 나는 1) 소수의 투표율이 2) 높은 등급의 답변이 더 복잡하고 3) 단점이 설명되어 있지 않은 것으로 의심됩니다. 누구 든지이 접근법을 사용하는 것에 대해 알고 있습니까?
Mark E

1
@MarkE 의심스러운 것은 없습니다. StackOverflow의 많은 결함 중 하나입니다. 이 답변이 몇 년 전에 게시되어 맨 위에 표시되는 답변은 엄청나게 많은 투표 모멘텀을 얻었습니다. 답이이 모멘텀을 얻었을 때,이기는 것은 매우 어렵고 아주 드 rare니다.
잭 지핀

9

나는이 질문을 보았지만 내 경우 (DOM 요소 (내 경우에는 캔버스가 아님) 에서 드래그 를 사용 offsetX하여) offsetY에서 작동하도록하기 위해 드래그 마우스 이벤트 에서만 사용해야한다는 것을 알았습니다. .

onDragOver(event){
 var x = event.offsetX;
 var y = event.offsetY;
}

2
이것은 나를 위해 잘 작동했습니다. 왜 아무도 이것을지지하지 않았습니까? 함정이 있는지 궁금합니다. 내가 발견하면 다시보고합니다!
seabass

7
event.offsetX는 마우스 오버 포인터가 연결된 요소가 아니라 마우스 포인터가 현재있는 요소와 관련이 있습니다. 중첩 된 요소 구조가 없으면 괜찮지 만 그렇게하면 작동하지 않습니다.
opsb

7

나는 올바른 방향으로 나를 얻었지만 Mark van Wyk의 대답을 +1하지만 나를 위해 그것을 해결하지 못했습니다. 나는 여전히 다른 요소에 포함 된 요소의 그림에 오프셋을 가졌습니다.

다음은 나를 위해 해결했습니다.

        x = e.pageX - this.offsetLeft - $(elem).offset().left;
        y = e.pageY - this.offsetTop - $(elem).offset().top;

다시 말해서, 나는 단순히 중첩 된 모든 요소의 모든 오프셋을 쌓았습니다.


당신을 위해 +1! 이것이 내가 찾은 대답입니다. 두 개의 캔버스가 서로 쌓여 있고 다른 div로 인해 좌표가 모두 잘못되었습니다. 나는 이것이 문제라는 것을 알았지 만 그것을 보상 할 논리 / 방정식을 알지 못했습니다. 당신도 내 문제를 해결했습니다! = D 감사합니다!
Partack

5

위의 답변 중 어느 것도 만족스러운 IMO가 아니므로 여기에 내가 사용하는 것이 있습니다.

// Cross-browser AddEventListener
function ael(e, n, h){
    if( e.addEventListener ){
        e.addEventListener(n, h, true);
    }else{
        e.attachEvent('on'+n, h);
    }
}

var touch = 'ontouchstart' in document.documentElement; // true if touch device
var mx, my; // always has current mouse position IN WINDOW

if(touch){
    ael(document, 'touchmove', function(e){var ori=e;mx=ori.changedTouches[0].pageX;my=ori.changedTouches[0].pageY} );
}else{
    ael(document, 'mousemove', function(e){mx=e.clientX;my=e.clientY} );
}

// local mouse X,Y position in element
function showLocalPos(e){
    document.title = (mx - e.getBoundingClientRect().left)
        + 'x'
        + Math.round(my - e.getBoundingClientRect().top);
}

그리고 페이지의 현재 Y 스크롤 위치를 알아야하는 경우 :

var yscroll = window.pageYOffset
        || (document.documentElement && document.documentElement.scrollTop)
        || document.body.scrollTop; // scroll Y position in page

4

터치 스크린이있는 모바일 장치 및 / 또는 랩톱 / 모니터 용 일반 웹 사이트 또는 PWA (Progressive Web Apps)를 개발하는 사용자는 마우스 이벤트에 익숙 할 수 있고 때때로 고통스러운 Touch 경험에 익숙하지 않기 때문에 여기에 착륙했습니다. 이벤트 ... 예!

3 가지 규칙이 있습니다.

  1. mousemove또는 touchmove행사 중에 가능한 한 적게하십시오 .
  2. mousedown또는 touchstart행사 중에 가능한 한 많이하십시오 .
  3. 전파 이벤트를 취소하고 터치 이벤트의 기본값을 방지하여 하이브리드 이벤트에서 마우스 이벤트가 발생하지 않도록하십시오.

말할 것도없이, touch이벤트 는 이벤트 가 더 복잡 할 수 있습니다. 하나 이상이있을 수 있고 마우스 이벤트보다 더 유연하고 복잡하기 때문입니다. 여기서는 한 번의 터치 만 다룰 것입니다. 예, 게으르고 있지만 가장 일반적인 유형의 터치입니다.

var posTop;
var posLeft;
function handleMouseDown(evt) {
  var e = evt || window.event; // Because Firefox, etc.
  posTop = e.target.offsetTop;
  posLeft = e.target.offsetLeft;
  e.target.style.background = "red";
  // The statement above would be better handled by CSS
  // but it's just an example of a generic visible indicator.
}
function handleMouseMove(evt) {
  var e = evt || window.event;
  var x = e.offsetX; // Wonderfully
  var y = e.offsetY; // Simple!
  e.target.innerHTML = "Mouse: " + x + ", " + y;
  if (posTop)
    e.target.innerHTML += "<br>" + (x + posLeft) + ", " + (y + posTop);
}
function handleMouseOut(evt) {
  var e = evt || window.event;
  e.target.innerHTML = "";
}
function handleMouseUp(evt) {
  var e = evt || window.event;
  e.target.style.background = "yellow";
}
function handleTouchStart(evt) {
  var e = evt || window.event;
  var rect = e.target.getBoundingClientRect();
  posTop = rect.top;
  posLeft = rect.left;
  e.target.style.background = "green";
  e.preventDefault(); // Unnecessary if using Vue.js
  e.stopPropagation(); // Same deal here
}
function handleTouchMove(evt) {
  var e = evt || window.event;
  var pageX = e.touches[0].clientX; // Touches are page-relative
  var pageY = e.touches[0].clientY; // not target-relative
  var x = pageX - posLeft;
  var y = pageY - posTop;
  e.target.innerHTML = "Touch: " + x + ", " + y;
  e.target.innerHTML += "<br>" + pageX + ", " + pageY;
  e.preventDefault();
  e.stopPropagation();
}
function handleTouchEnd(evt) {
  var e = evt || window.event;
  e.target.style.background = "yellow";
  // Yes, I'm being lazy and doing the same as mouseout here
  // but obviously you could do something different if needed.
  e.preventDefault();
  e.stopPropagation();
}
div {
  background: yellow;
  height: 100px;
  left: 50px;
  position: absolute;
  top: 80px;
  user-select: none; /* Disable text selection */
  -ms-user-select: none;
  width: 100px;
}
<div 
  onmousedown="handleMouseDown()" 
  onmousemove="handleMouseMove()"
  onmouseout="handleMouseOut()"
  onmouseup="handleMouseUp()" 
  ontouchstart="handleTouchStart()" 
  ontouchmove="handleTouchMove()" 
  ontouchend="handleTouchEnd()">
</div>
Move over box for coordinates relative to top left of box.<br>
Hold mouse down or touch to change color.<br>
Drag to turn on coordinates relative to top left of page.

Vue.js선호 하십니까? 나는한다! 그런 다음 HTML은 다음과 같습니다.

<div @mousedown="handleMouseDown"
     @mousemove="handleMouseMove"
     @mouseup="handleMouseUp"
     @touchstart.stop.prevent="handleTouchStart"
     @touchmove.stop.prevent="handleTouchMove"
     @touchend.stop.prevent="handleTouchEnd">

3

당신은 그것을 얻을 수 있습니다

var element = document.getElementById(canvasId);
element.onmousemove = function(e) {
    var xCoor = e.clientX;
    var yCoor = e.clientY;
}

이것은 IE에서 작동합니까, 아니면 IE가 이벤트를 리스너의 첫 번째 인수로 전달하는 대신 여전히 window.event를 사용합니까? 편집-IE 버전 9까지 어쨌든 canvas 요소가 없다고 생각하지만, 이것은 아마도 excanvas와 같은 것들 때문에 IE를 지원해야합니다 ....
Dagg Nabbit

21
이렇게하면 브라우저 창을 기준으로 좌표가 표시되지만 element.getBoundingClientRect ()를 사용하여 요소에 있는지 확인해야합니다.
David W. Keith

getBoundingClientRect !!!에 대해 알려 주셔서 감사합니다! 나는 그런 것이 있다는 것을 결코 깨닫지 못했습니다!
Gershom

@ DavidW.Keith 의견은 실제로 정답으로 간주되어야합니다!
울릭. S

3

이 튜토리얼 에서 가져온 주석은 다음과 같이 수정되었습니다.

function getMousePos( canvas, evt ) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: Math.floor( ( evt.clientX - rect.left ) / ( rect.right - rect.left ) * canvas.width ),
        y: Math.floor( ( evt.clientY - rect.top ) / ( rect.bottom - rect.top ) * canvas.height )
    };
}

다음과 같이 캔버스에서 사용하십시오.

var canvas = document.getElementById( 'myCanvas' );
canvas.addEventListener( 'mousemove', function( evt ) {
    var mousePos = getMousePos( canvas, evt );
} );

3

나는 조금 늦었다는 것을 알고 있지만 이것은 PURE 자바 스크립트와 함께 작동하며 요소가 뷰포트보다 크고 사용자가 스크롤 한 경우 요소 내의 포인터 좌표를 제공합니다.

var element_offset_x ; // The distance from the left side of the element to the left of the content area


....// some code here (function declaration or element lookup )



element_offset_x = element.getBoundingClientRect().left  -  document.getElementsByTagName("html")[0].getBoundingClientRect().left  ;

....// code here 




function mouseMoveEvent(event) 
{
   var pointer_location = (event.clientX + window.pageXOffset) - element_offset_x ; 
}

작동 방식

가장 먼저 할 일은 현재 뷰포트를 기준으로 HTML 요소 (컨텐츠 영역)의 위치를 ​​얻는 것입니다. 페이지에 스크롤 막대가 있고 스크롤 된 getBoundingClientRect().left경우 html 태그 에 대해 반환 된 숫자는 음수입니다. 그런 다음이 숫자를 사용하여 요소와 컨텐츠 영역의 왼쪽 사이의 거리를 계산합니다. 와element_offset_x = element.getBoundingClientRect().left......;

컨텐츠 영역에서 요소의 거리를 알고 있습니다. event.clientX뷰포트에서 포인터의 거리를 알려줍니다. 뷰포트와 컨텐츠 영역이 서로 다른 두 엔티티라는 것을 이해하는 것이 중요합니다. 페이지가 스크롤되면 뷰포트가 이동할 수 있습니다. 따라서 clientX는 페이지가 스크롤 되더라도 동일한 번호를 반환합니다.

이를 보완하기 위해 포인터의 x 위치 (뷰포트 기준)를 뷰포트의 x 위치 (컨텐츠 영역 기준)에 추가해야합니다. 뷰포트의 X 위치는 window.pageXOffset.


1
스크롤에 대해 생각할 수있는 유일한 응답자입니다. y 축도 추가하려면 답을 변경하십시오.
frabjous

3

@Spider의 솔루션을 기반으로 내 JQuery가 아닌 버전은 다음과 같습니다.

// Get the container element's bounding box
var sides = document.getElementById("container").getBoundingClientRect();

// Apply the mouse event listener
document.getElementById("canvas").onmousemove = (e) => {
  // Here 'self' is simply the current window's context
  var x = (e.clientX - sides.left) + self.pageXOffset;
  var y = (e.clientY - sides.top) + self.pageYOffset;
}

이것은 스크롤과 줌 모두에서 작동합니다 (이 경우 때로는 수레를 반환합니다).


나는 공언을했지만 페이지 오프셋에 대한 빼기 부호가 아니어야합니까? 아니면 두 번째 부분의 괄호입니까?
Chris Sunami는 Monica

1

캔버스 내부의 마우스 좌표는 event.offsetX 및 event.offsetY 덕분에 얻을 수 있습니다. 내 요점을 증명하는 약간의 스 니펫이 있습니다.

c=document.getElementById("c");
ctx=c.getContext("2d");
ctx.fillStyle="black";
ctx.fillRect(0,0,100,100);
c.addEventListener("mousemove",function(mouseEvt){
  // the mouse's coordinates on the canvas are just below
  x=mouseEvt.offsetX;
  y=mouseEvt.offsetY;
  // the following lines draw a red square around the mouse to prove it
  ctx.fillStyle="black";
  ctx.fillRect(0,0,100,100);
  ctx.fillStyle="red";
  ctx.fillRect(x-5,y-5,10,10);
});
  
body {
  background-color: blue;
}

canvas {
  position: absolute;
  top: 50px;
  left: 100px;
}
<canvas id="c" width="100" height="100"></canvas>
    


@opsb가 말한 것처럼 다른 div가 캔버스를 오버레이하면 작동하지 않습니다.
David Peicho

1
canvas.onmousedown = function(e) {
    pos_left = e.pageX - e.currentTarget.offsetLeft;
    pos_top = e.pageY - e.currentTarget.offsetTop;
    console.log(pos_left, pos_top)
}

HTMLElement.offsetLeft

HTMLElement.offsetLeft판독 전용 속성 복귀 현재 요소의 상부 좌측 코너 내의 왼쪽으로 오프셋되는 화소의 수 HTMLElement.offsetParent의 노드.

블록 레벨의 요소, offsetTop, offsetLeft, offsetWidth, 및 offsetHeight받는 소자 상대의 경계 박스를 설명 offsetParent.

그러나, (예컨대 인라인 레벨 요소에 대한 span하나의 행에서 다음으로 바꿈 수) offsetTopoffsetLeft(처음 사용할 경계 박스의 위치를 설명 Element.getClientRects()의 폭과 높이를 얻기 위해) 동안 offsetWidthoffsetHeight경계 경계 박스의 크기를 설명하는 ( Element.getBoundingClientRect()위치를 파악 하는 데 사용 ). 따라서, 왼쪽, 위쪽, 폭과 높이를 가진 박스 offsetLeft, offsetTop, offsetWidthoffsetHeight래핑 된 텍스트와 범위에 대한 경계 박스 없습니다.

HTMLElement.offsetTop

HTMLElement.offsetTop읽기 전용 속성의 상단에 현재 요소의 상대적 거리를 반환 offsetParent노드를.

MouseEvent.pageX

pageX읽기 전용 속성은 X (수평) 문서 전체를 기준으로하는, 이벤트의 상대 좌표를 픽셀 단위로 반환합니다. 이 속성은 페이지의 가로 스크롤을 고려합니다.

MouseEvent.pageY

MouseEvent.pageY판독 전용 속성 복귀 Y (세로)는 전체 문서 이벤트의 상대 좌표를 픽셀 단위. 이 속성은 페이지의 세로 스크롤을 고려합니다.

자세한 설명은 Mozilla 개발자 네트워크를 참조하십시오.

https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageX https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/pageY https : // developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop


이 코드 스 니펫은 문제를 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 코드 제안의 이유를 모를 수도 있습니다.
패트릭 훈트

앞으로 독자들에게 이것을 계산하는 JS API가 있기를 바랍니다. ;-) 아마도 가장 단순하고 완전하며 독립적 인 답변 일 것입니다. 자체 설명 코드를 주석 처리하는 것은 낭비를 산만하게합니다.
lama12345

@PatrickHund의 설명 요청에 이어 두 번째입니다. 나는 CSS / JS 전문가가 아니에요, 그리고 예를 들어, 사이의 관계에 대한 자세한 내용을 알고, page그리고 offset나에게 매우 도움이 될 것입니다. 이 요청을 고려해 주셔서 감사합니다!
cxw

@cxw Ok, 당신은 두 번째 downvote입니다 (1 개의 upvote가 있습니다). 나는 지금 긴 설명을 추가했습니다. 코드의 4 줄만큼 10 배입니다. 천만에요, 재미있게 읽습니다. 귀하의 요청을 고려했습니다! : p
lama12345

1
@cxw 나는 절대 위치 요소를 추가하고 캔버스 요소 자체를 화면 외부로 강제로 밀어서 엉망으로 만들었습니다. 그래서 왼쪽 / 상단 2000px 오프 스크린과 같이 스크롤해야했습니다. 이 코드를 깨뜨리지 못했습니다.
lama12345

1

나는 매우 간단하다고 생각되는 다른 솔루션을 구현했기 때문에 여러분과 공유 할 것이라고 생각했습니다.

따라서 문제는 드래그 한 div가 마우스 커서에 대해 0,0 으로 점프한다는 것 입니다. 그래서 div의 새 위치를 조정하기 위해 div에서 마우스 위치를 캡처해야했습니다.

나는 div의 X 페이지와 페이지 Y를 읽고 상단을 설정하고 그에 따라 다음 값이 나는 onDragStart 리스너를 사용 사업부의 초기 위치에 커서를 유지하기 위해 좌표를 조정 얻고 저장하는 왼쪽 e.nativeEvent를 초기 트리거에서만 드래그 가능한 div 내에서 마우스 위치를 제공하는 .layerXe.nativeEvent.layerY

예제 코드 :

 onDrag={(e) => {
          let newCoords;
          newCoords = { x: e.pageX - this.state.correctionX, y: e.pageY - this.state.correctionY };
          this.props.onDrag(newCoords, e, item.id);
        }}
        onDragStart={
          (e) => {
            this.setState({
              correctionX: e.nativeEvent.layerX,
              correctionY: e.nativeEvent.layerY,
            });
          }

나는 이것이 내가 겪었던 것과 같은 문제를 겪은 누군가를 도울 수 있기를 바랍니다. :)


1
function myFunction(e) {
    var x =  e.clientX - e.currentTarget.offsetLeft ; 
    var y = e.clientY - e.currentTarget.offsetTop ;
}

이 작동합니다!


0

캔버스가 div의 자식이고 다른 div의 자식 인 경우 이야기가 더 복잡해지기 때문에 페이지의 구조를 알아야합니다. 2 단계의 div 안에있는 캔버스에 대한 내 코드는 다음과 같습니다.

canvas.addEventListener("click", function(event) {
var x = event.pageX - (this.offsetLeft + this.parentElement.offsetLeft);
var y = event.pageY - (this.offsetTop + this.parentElement.offsetTop);
console.log("relative x=" + x, "relative y" + y);

});


0

원래 답변은 iframe에 넣었다고 말했습니다. 더 좋은 해결책은 패딩이 0px로 설정된 캔버스에서 이벤트 offsetX 및 offsetY를 사용하는 것입니다.

<html>
<body>
<script>

var main=document.createElement('canvas');
main.width="200";
main.height="300";
main.style="padding:0px;margin:30px;border:thick dashed red";
document.body.appendChild(main);

// adding event listener

main.addEventListener('mousemove',function(e){
    var ctx=e.target.getContext('2d');
    var c=Math.floor(Math.random()*0xFFFFFF);
    c=c.toString(16); for(;c.length<6;) c='0'+c;
    ctx.strokeStyle='#'+c;
    ctx.beginPath();
    ctx.arc(e.offsetX,e.offsetY,3,0,2*Math.PI);
    ctx.stroke();
    e.target.title=e.offsetX+' '+e.offsetY;
    });

// it worked! move mouse over window

</script>
</body>
</html>

0

여기 내가 가진 것입니다.

    $(".some-class").click(function(e) {

    var posx = 0;
    var posy = 0;

    posx = e.pageX;
    posy = e.pageY;

    alert(posx);
    alert(posy);
});

0

당신은 사용할 수 getBoudingClientRect()relative부모입니다.

document.addEventListener("mousemove", (e) => {
  let xCoord = e.clientX - e.target.getBoundingClientRect().left + e.offsetX
  let yCoord = e.clientY - e.target.getBoundingClientRect().top + e.offsetY
  console.log("xCoord", xCoord, "yCoord", yCoord)
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.