source

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

gigabyte 2023. 1. 22. 22:27
반응형

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

캔버스를 이용한 작은 그림 앱을 만들고 싶습니다.그래서 캔버스에서 마우스 위치를 찾아야 해요.

복사/붙여넣을 수 있는 jQuery 프리 답변을 찾을 수 없었기 때문에 사용한 솔루션은 다음과 같습니다.

document.getElementById('clickme').onclick = 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.
      console.log("Left? : " + x + " ; Top? : " + y + ".");
    }
#clickme {
  margin-top: 20px;
  margin-left: 100px;
  border: 1px solid black;
  cursor: pointer;
}
<div id="clickme">Click Me -<br>
(this box has margin-left: 100px; margin-top: 20px;)</div>

완전한 예의 JSFiddle

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각 회선마다.

갱신하다

@anytimecoder의 응답에는 새로운 JavaScript 전용 버전이 있습니다.getBoundingClientRect()에 대한 브라우저 지원도 참조하십시오.

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

const example = document.getElementById('example');

example.onmousemove = function(e) { 
    const x = e.pageX - e.currentTarget.offsetLeft; 
    const y = e.pageY - e.currentTarget.offsetTop; 
}

순수 javascript에서는 참조 요소가 다른 요소 안에 중첩되어 있을 때 상대 좌표를 반환하는 답변이 없습니다.다음은 이 시나리오에 대한 해결책입니다.

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,
  }; 

}

저는 이 모든 솔루션을 시도해 보았지만 매트릭스 변환 컨테이너(판줌 라이브러리)를 사용한 특별한 설정 때문에 효과가 없었습니다.이렇게 하면 확대/축소 및 상하좌우로 이동하더라도 올바른 값이 반환됩니다.

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

하지만 방해가 되는 요소가 없는 경우에만요.이는 CSS를 사용하여 이벤트에 대해 '보이지 않음'으로 함으로써 회피할 수 있습니다.

.child {
   pointer-events: none;
}

이 문제의 문제의 상세한 것에 대하여는, http://www.quirksmode.org/js/events_properties.html#position 를 참조해 주세요.

여기에 설명된 기술을 사용하여 문서에서 마우스 위치를 찾을 수 있습니다. 자신이 안에 .element.getBoundingClientRect()과 같은 가진 를 반환합니다.{ bottom, height, left, right, top, width }여기서부터 요소 내부에서 발생했는지 여부를 파악하는 것은 매우 간단합니다.

이을 하게 만, ( DOM 오버를 사용하여)내에 적합하게 , 「DOM」을을 알았습니다.offsetX ★★★★★★★★★★★★★★★★★」offsetY드래그오버 이벤트 때.

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

1개의 요소에 관련된 레이어X 및 레이어Y를 취득하는 경우는, 다음과 같이 시험할 수 있습니다.

let bbox_rect = document.getElementById("dom-ID").getBoundingClientRect()
let layerX = e.clientX-bbox_rect.left
let layerY = e.clientY-bbox_rect.top

나는 마크 반 와이크의 대답이 나를 올바른 방향으로 이끌었기 때문에 +1'이라고 대답했지만, 나는 그것을 잘 해결하지 못했다.나는 다른 요소 안에 포함된 요소들에 대한 회화에 대한 오프셋이 여전히 있었다.

폴로잉으로 해결했습니다.

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

즉, 중첩된 모든 요소의 모든 오프셋을 쌓기만 하면 됩니다.

모바일 디바이스용 일반 웹사이트 또는 터치스크린을 탑재한 노트북/모니터용 PWA(Progressive Web Apps)를 개발하시는 분들은 마우스 이벤트에 익숙하고 터치 이벤트의 고통스러운 경험을 처음 접하는 분입니다.야호!

규칙은 3가지뿐입니다.

  1. 때는 적게 .mousemove ★★★★★★★★★★★★★★★★★」touchmove벤트입입니니다
  2. 수 한 해 주세요.mousedown ★★★★★★★★★★★★★★★★★」touchstart벤트입입니니다
  3. 전파를 취소하고 터치 이벤트의 기본값을 방지하여 하이브리드 디바이스에서도 마우스 이벤트가 실행되지 않도록 합니다.

것도 없이, 은 더 복잡합니다만, 더 합니다.touch이벤트에는 여러 개의 이벤트가 있을 수 있고 마우스 이벤트보다 유연성이 높기 때문입니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★에, 거기 ,, 게, 게, 게, 게, 게, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes, yes.

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">

위의 답변 중 어느 것도 만족스러운 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

튜토리얼에서 인용하여 톱 코멘트를 수정했습니다.

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 );
} );
canvas.onmousedown = function(e) {
    pos_left = e.pageX - e.currentTarget.offsetLeft;
    pos_top = e.pageY - e.currentTarget.offsetTop;
    console.log(pos_left, pos_top)
}

HT Mlement. offset 왼쪽

HTMLElement.offsetLeft은 현재 전용으로 합니다.HTMLElement.offsetParentdiscloss.discloss.

요소에 대해서는, 「」를 참조해 주세요.offsetTop,offsetLeft,offsetWidth , , , , 입니다.offsetHeight describe describe describe describe describe describe 、 describe 、 describe 、 describe describe 。offsetParent.

요소( 「」등)의 는, 다음과 같습니다.span에서 다음을 할 수 것, > > > > > > > > > > > > > > > > > > > > > > > > > 。offsetTop ★★★★★★★★★★★★★★★★★」offsetLeft첫 번째 테두리 상자의 위치를 설명합니다(사용).Element.getClientRects()폭과 높이를 얻기 위해)를 선택합니다.offsetWidth ★★★★★★★★★★★★★★★★★」offsetHeight테두리 상자의 치수를 설명합니다(용도).Element.getBoundingClientRect()그 지위를 획득하기 위해서).왼쪽,, 가 라, 쪽, 비, 이, 이, 이, 이의 입니다.offsetLeft,offsetTop,offsetWidth ★★★★★★★★★★★★★★★★★」offsetHeight는 줄바꿈된 텍스트가 있는 범위의 경계 상자가 되지 않습니다.

HTLelement.오프셋정상

HTMLElement.offsetTop는 현재 할 때 " 전용"의 을 기준으로 합니다.offsetParentdiscloss.discloss.

MouseEvent.pageX

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

MouseEvent. 페이지y

MouseEvent.pageY읽기 전용 속성은 전체 문서를 기준으로 이벤트의 픽셀 단위로 Y(수직) 좌표를 반환합니다.이 속성은 페이지의 수직 스크롤을 고려합니다.

상세한 것에 대하여는, Mozilla Developer Network 를 참조해 주세요.

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


const findMousePositionRelativeToElement = (e) => {
    const xClick = e.clientX - e.currentTarget.offsetLeft;
    const yClick = e.clientY - e.currentTarget.offsetTop;
    console.log(`x: ${xClick}`);
    console.log(`y: ${yClick}`);

    // or
    const rect = e.currentTarget.getBoundingClientRect();
    const xClick2 = e.clientX - rect.left;
    const yClick2 = e.clientY - rect.top;
    console.log(`x2: ${xClick2}`);
    console.log(`y2: ${yClick2}`);
}

조금 늦은 건 알지만, PURE javascript와 연동됩니다.또한 요소가 뷰포트보다 크고 사용자가 스크롤한 경우 요소 내의 포인터의 좌표를 알 수 있습니다.

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그런 다음 이 숫자를 사용하여 요소와 컨텐츠 영역의 왼쪽 사이의 거리를 계산합니다.★★★★★★★★★★★★★★★★ element_offset_x = element.getBoundingClientRect().left......;

컨텐츠 영역으로부터 요소의 거리를 확인합니다. event.clientX는 뷰포트에서 포인터의 거리를 나타냅니다.뷰포트와 내용 영역은 서로 다른 두 개의 엔티티이며 페이지가 스크롤되면 뷰포트가 이동할 수 있음을 이해하는 것이 중요합니다.따라서 clientX는 페이지가 스크롤되어도 같은 번호를 반환합니다.

이를 보완하려면 포인터의 x 위치(뷰포트를 기준으로 함)를 뷰포트의 x 위치(콘텐츠 영역을 기준으로 함)에 추가해야 합니다.의 X 다. window.pageXOffset.

@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;
}

이 기능은 스크롤과 줌 모두에서 작동합니다(이 경우 플로트가 반환되는 경우도 있습니다).

하시면 됩니다.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)
})

당신은 그것을 얻을 수 있다

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

캔버스 내의 마우스 좌표는 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>
    

저는 매우 간단한 다른 솔루션을 구현했습니다. 그래서 여러분과 공유하려고 합니다.

그래서 문제는 마우스 커서가 드래그된 div가 0.0으로 점프한다는 것이었습니다.그래서 나는 divs의 새로운 위치를 조정하기 위해 div의 마우스 위치를 캡처해야 했다.

나는 PageX와 PageY를 읽고 이에 따라 의 상단과 좌측을 설정한 다음, div의 초기 위치에 커서를 유지하기 위한 좌표를 조정하기 위한 값을 얻기 위해 onDragStart 청취자를 사용하여 초기 트리거에만 제공되는 e.nativeEvent.layerX와 e.nativeEventlayerYmhouse 내에 저장합니다.e 드래그 가능한 div.

코드 예:

 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,
            });
          }

제가 겪었던 것과 같은 문제를 겪은 사람에게 도움이 되었으면 합니다.

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

이거 잘 돼!

jQuery의 event.pageX 및 event.pageY를 jQuery의 메서드오프셋()과 함께 사용하면 요소에 상대적인 마우스 위치를 얻을 수 있습니다.

  $(document).ready(function() {
    $("#myDiv").mousemove(function(event){            
      var X = event.pageX - $(this).offset().left;
      var Y = event.pageY - $(this).offset().top;
      $(".cordn").text("(" + X + "," + Y + ")");
    });
  });

예를 다음에 나타냅니다.요소를 기준으로 마우스 위치를 찾는 방법

마우스 위치를 빠르게 가져오려면 다음 방법을 사용합니다.

Object.defineProperty(MouseEvent.prototype, "mouseX", {
   get() {
      return this.clientX - this.currentTarget.getBoundingClientRect().left;
   }
});
Object.defineProperty(MouseEvent.prototype, "mouseY", {
   get() {
      return this.clientY - this.currentTarget.getBoundingClientRect().top;
   }
});

예:

document.body.onmousemove=function(e){console.log(e.mouseX,e.mouseY)}

페이지 구조를 알아야 합니다. 캔버스가 디바의 자식이고 다른 디바의 자식이라면...그러면 이야기가 더 복잡해져요.2레벨의 divs 안에 있는 캔버스의 코드는 다음과 같습니다.

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);

});

원래 답은 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>

@Patrick Boos 솔루션을 기반으로 하지만 중간 스크롤바의 잠재적인 문제를 해결합니다.

export function getRelativeCoordinates(event: MouseEvent, referenceElement: HTMLElement) {
  const position = {
    x: event.pageX,
    y: event.pageY,
  };

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

  let reference = referenceElement.offsetParent as HTMLElement;

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

  const scrolls = {
    left: 0,
    top: 0,
  };

  reference = event.target as HTMLElement;
  while (reference) {
    scrolls.left += reference.scrollLeft;
    scrolls.top += reference.scrollTop;
    reference = reference.parentElement as HTMLElement;
  }

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

스크롤바가 있는 넓은 칸막이 안에서 커서 위치를 잡아야 했어요.목적은 요소를 div의 임의의 위치로 드래그하는 것이었습니다.

스크롤 깊숙한 곳에서 마우스 위치를 먼 곳에 둡니다.

$('.canvas').on('mousemove', function(e){
    $(dragElement).parent().css('top', e.currentTarget.scrollTop + e.originalEvent.clientY );
    $(dragElement).parent().css('left', e.currentTarget.scrollLeft + e.originalEvent.clientX )
});

예를 들어 선택사항이 있는 부모 요소에 추가한다면 얻을 수 있는 해결책을 찾지 못했기 때문입니다.

제가 한 일은 다음과 같습니다.

let positions = {
  x: event.pageX,
  y: event.pageY - event.currentTarget.getBoundingClientRect().top + event.currentTarget.offsetTop
}

여기 내가 얻은 게 있다.

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

    var posx = 0;
    var posy = 0;

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

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

언급URL : https://stackoverflow.com/questions/3234256/find-mouse-position-relative-to-element

반응형