[javascript] 캔버스 요소에서 마우스 클릭의 좌표를 얻으려면 어떻게해야합니까?

클릭 이벤트 핸들러를 캔버스 요소에 추가하여 클릭의 x 및 y 좌표를 반환하는 가장 간단한 방법은 무엇입니까 (캔버스 요소 기준)?

레거시 브라우저 호환성이 필요하지 않으며 Safari, Opera 및 Firefox가 지원합니다.



답변

2018 편집 : 이 답변은 꽤 오래되었으며 더 이상 필요하지 않은 이전 브라우저에 대한 검사를 사용합니다. clientXclientY현재 속성은 모든 현재 브라우저에서 작동합니다. 더 간단하고 최신 솔루션에 대해서는 Patriques Answer 를 확인하십시오 .

원래 답변 :
이전에 찾은 기사에 설명되어 있지만 더 이상 존재하지 않는 항목 :

var x;
var y;
if (e.pageX || e.pageY) { 
  x = e.pageX;
  y = e.pageY;
}
else { 
  x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
  y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 
} 
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;

나를 위해 완벽하게 일했습니다.


답변

단순성을 좋아하지만 여전히 브라우저 간 기능을 원한다면이 솔루션이 가장 효과적이라는 것을 알았습니다. 이것은 @Aldekein 솔루션의 단순화이지만 jQuery는 없습니다 .

function getCursorPosition(canvas, event) {
    const rect = canvas.getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top
    console.log("x: " + x + " y: " + y)
}

const canvas = document.querySelector('canvas')
canvas.addEventListener('mousedown', function(e) {
    getCursorPosition(canvas, e)
})


답변

업데이트 (5/5/16) : 더 간단하고 신뢰할 수 있기 때문에 patriques의 답변 을 대신 사용해야합니다.


캔버스는 항상 전체 페이지를 기준으로 스타일이 지정 canvas.offsetLeft/Top되지 않으므로 필요한 것을 항상 반환하지는 않습니다. 스타일이 적용된 div캔버스를 포함 하는 요소 와 같은 offsetParent 요소를 기준으로 오프셋 된 픽셀 수를 반환합니다 position: relative. 이를 설명하려면 offsetParentcanvas 요소 자체부터 시작 하여 체인을 반복해야 합니다. 이 코드는 Firefox 및 Safari에서 테스트되었지만 완벽하게 작동하지만 모두 작동합니다.

function relMouseCoords(event){
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do{
        totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
        totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
    }
    while(currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;

마지막 줄은 캔버스 요소를 기준으로 마우스 좌표를 얻는 데 편리합니다. 유용한 좌표를 얻기 위해 필요한 것은

coords = canvas.relMouseCoords(event);
canvasX = coords.x;
canvasY = coords.y;


답변

최신 브라우저가 이제이를 처리합니다. Chrome, IE9 및 Firefox는 이와 같은 오프셋 X / Y를 지원하여 클릭 핸들러에서 이벤트를 전달합니다.

function getRelativeCoords(event) {
    return { x: event.offsetX, y: event.offsetY };
}

대부분의 최신 브라우저는 layerX / Y도 지원하지만 Chrome과 IE는 마진, 패딩 등 페이지 클릭의 절대 오프셋에 layerX / Y를 사용합니다. Firefox에서는 layerX / Y와 offsetX / Y는 동일하지만 오프셋은 이전에는 존재하지 않았습니다. 따라서 약간 오래된 브라우저와의 호환성을 위해 다음을 사용할 수 있습니다.

function getRelativeCoords(event) {
    return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}


답변

신선한에 따르면 쿼크 모드clientXclientY방법은 모든 주요 브라우저에서 지원됩니다. 스크롤 바가있는 페이지의 스크롤 div에서 작동하는 좋은 작동 코드는 다음과 같습니다.

function getCursorPosition(canvas, event) {
var x, y;

canoffset = $(canvas).offset();
x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft - Math.floor(canoffset.left);
y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop - Math.floor(canoffset.top) + 1;

return [x,y];
}

또한에 대한 jQuery 가 필요 합니다 $(canvas).offset().


답변

이 문제에 대한 솔루션의 전체 소스 코드를 사용하여 모든 브라우저에서 작동하는 완전한 데모를 만들었습니다. 마우스 좌표에서 Javascript로 캔버스를 클릭하십시오 . 데모를 시도하려면 코드를 복사하여 텍스트 편집기에 붙여 넣으십시오. 그런 다음 example.html로 저장 한 다음 브라우저에서 파일을여십시오.


답변

너비 (%)가 가변 인 캔버스에 대한 Ryan Artecona의 답변 을 약간 수정했습니다 .

 HTMLCanvasElement.prototype.relMouseCoords = function (event) {
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do {
        totalOffsetX += currentElement.offsetLeft;
        totalOffsetY += currentElement.offsetTop;
    }
    while (currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    // Fix for variable canvas width
    canvasX = Math.round( canvasX * (this.width / this.offsetWidth) );
    canvasY = Math.round( canvasY * (this.height / this.offsetHeight) );

    return {x:canvasX, y:canvasY}
}