Development Tip

캔버스에서 실제 마우스 위치

yourdevel 2020. 10. 15. 21:52
반응형

캔버스에서 실제 마우스 위치


이 질문에 이미 답변이 있습니다.

HTML5 캔버스 위에 마우스로 그리려고하는데 어떤 이유로 캔버스 위치를 변경하면 캔버스가 0,0 (왼쪽 위 모서리) 위치에있는 것뿐입니다. 당연히 그려지지 않습니다. 다음은 내 코드입니다.

 function createImageOnCanvas(imageId){
    document.getElementById("imgCanvas").style.display = "block";
    document.getElementById("images").style.overflowY= "hidden";
    var canvas = document.getElementById("imgCanvas");
    var context = canvas.getContext("2d");
    var img = new Image(300,300);
    img.src = document.getElementById(imageId).src;
    context.drawImage(img, (0),(0));
}

function draw(e){
    var canvas = document.getElementById("imgCanvas");
    var context = canvas.getContext("2d");
    posx = e.clientX;
    posy = e.clientY;
    context.fillStyle = "#000000";
    context.fillRect (posx, posy, 4, 4);
}

HTML 부분

 <body>
 <div id="images">
 </div>
 <canvas onmousemove="draw(event)" style="margin:0;padding:0;" id="imgCanvas"
          class="canvasView" width="250" height="250"></canvas> 

올바른 위치를 얻기 위해 JavaScript에서 간단한 함수를 만드는 방법이 있다는 것을 읽었지만 그 방법에 대해 전혀 모릅니다.


간단한 1 : 1 시나리오

캔버스 요소가 비트 맵 크기에 비해 1 : 1 인 상황의 경우 다음 스 니펫을 사용하여 마우스 위치를 가져올 수 있습니다.

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
}

이벤트와 캔버스를 인수로 사용하여 이벤트에서 호출하십시오. 마우스 위치에 대해 x 및 y가있는 개체를 반환합니다.

마우스 위치가 클라이언트 창에 상대적이므로 캔버스 요소의 위치를 ​​빼서 요소 자체를 기준으로 변환해야합니다.

코드 통합의 예 :

//put this outside the event loop..
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");

function draw(evt) {
    var pos = getMousePos(canvas, evt);

    context.fillStyle = "#000000";
    context.fillRect (pos.x, pos.y, 4, 4);
}

수정 된 바이올린

참고 : 테두리와 패딩은 캔버스 요소에 직접 적용되는 경우 위치에 영향을 미치므로이를 통해 고려 getComputedStyle()하거나 해당 스타일을 부모 div에 대신 적용해야합니다.

요소와 비트 맵의 ​​크기가 다른 경우

예를 들어, 요소가 비트 맵 자체와 다른 크기에있는 상황이있는 경우, 예를 들어 요소가 CSS를 사용하여 크기가 조정되거나 픽셀 종횡비 등이있는 경우이 문제를 해결해야합니다.

예:

function  getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect(), // abs. size of element
      scaleX = canvas.width / rect.width,    // relationship bitmap vs. element for X
      scaleY = canvas.height / rect.height;  // relationship bitmap vs. element for Y

  return {
    x: (evt.clientX - rect.left) * scaleX,   // scale mouse coordinates after they have
    y: (evt.clientY - rect.top) * scaleY     // been adjusted to be relative to element
  }
}

스케일을 사용하여 바이올린

컨텍스트에 적용된 변형 (크기 조정, 회전 등)

그런 다음 회전, 기울이기 / 전단, 크기 조정, 변환 등과 같은 변환을 컨텍스트에 적용한 더 복잡한 경우가 있습니다.이를 처리하기 위해 현재 행렬의 역행렬을 계산할 수 있습니다.

최신 브라우저에서는 currentTransform속성을 통해 현재 행렬을 읽을 수 있으며 Firefox (현재 알파)는 mozCurrentTransformInverted. 그러나 파이어 폭스는를 통해 mozCurrentTransform배열을 반환 하지만 DOMMatrix원래 는 반환하지 않습니다 . 실험 플래그를 통해 활성화되면 나도 크롬,하는 반환하지 않습니다 DOMMatrix하지만를 SVGMatrix.

그러나 대부분의 경우 완전한 지원을받을 때까지 자신 만의 맞춤형 매트릭스 솔루션 (예 : 여기에있는 내 솔루션 -무료 / MIT 프로젝트) 을 구현해야합니다 .

행렬을 얻기 위해 선택한 경로에 관계없이 결국 행렬을 얻은 경우이를 반전하여 마우스 좌표에 적용해야합니다. 좌표는 캔버스로 전달되어 매트릭스를 사용하여 현재 위치로 다시 변환됩니다.

이렇게하면 포인트가 마우스를 기준으로 올바른 위치에있게됩니다. 또한 여기서 역행렬을 적용하기 전에 요소를 기준으로 좌표를 조정해야합니다.

행렬 단계를 보여주는 예

function draw(evt) {
    var pos = getMousePos(canvas, evt);        // get adjusted coordinates as above
    var imatrix = matrix.inverse();            // get inverted matrix somehow
    pos = imatrix.applyToPoint(pos.x, pos.y);  // apply to adjusted coordinate

    context.fillStyle = "#000000";
    context.fillRect(pos.x-1, pos.y-1, 2, 2);
}

위에 링크 된 솔루션을 사용한 예 (더 광범위하게 지원되는 경우 기본 브라우저 솔루션으로 대체)

currentTransform구현시 사용의 예 는 다음과 같습니다.

    var pos = getMousePos(canvas, e);          // get adjusted coordinates as above
    var matrix = ctx.currentTransform;         // W3C (future)
    var imatrix = matrix.invertSelf();         // invert

    // apply to point:
    var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e;
    var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f;

업데이트 저는이 모든 단계를 여기 에서 찾을 수있는 사용하기 쉬운 단일 개체에 포함하는 무료 솔루션 (MIT)을 만들었습니다 .


다음 스 니펫을 사용하여 마우스 위치를 가져올 수 있습니다.

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

이 코드는 캔버스 공간에 대한 좌표 변경 ( evt.clientX - rect.left)과 캔버스 논리적 크기가 스타일 크기와 다를 때 크기 조정을 모두 고려합니다 ( HTML5의 캔버스 너비 및 높이/ (rect.right - rect.left) * canvas.width 참조 ).

예 : http://jsfiddle.net/sierawski/4xezb7nL/

출처 : http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/의 jerryj 댓글


캔버스를 기준으로 마우스 위치 를 가져와야합니다.

이를 위해서는 페이지에서 캔버스의 X / Y 위치를 알아야합니다.

이를 캔버스의 "오프셋"이라고하며 오프셋을 얻는 방법은 다음과 같습니다. (브라우저 간 호환성을 단순화하기 위해 jQuery를 사용하고 있지만 원시 자바 스크립트를 사용하려는 경우 빠른 Google도 얻을 수 있습니다).

    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

그런 다음 마우스 핸들러에서 다음과 같이 마우스 X / Y를 얻을 수 있습니다.

  function handleMouseDown(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
}

다음은 캔버스에서 마우스 이벤트를 성공적으로 추적하는 방법을 보여주는 코드와 바이올린입니다.

http://jsfiddle.net/m1erickson/WB7Zu/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var canvasOffset=$("#canvas").offset();
    var offsetX=canvasOffset.left;
    var offsetY=canvasOffset.top;

    function handleMouseDown(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      $("#downlog").html("Down: "+ mouseX + " / " + mouseY);

      // Put your mousedown stuff here

    }

    function handleMouseUp(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      $("#uplog").html("Up: "+ mouseX + " / " + mouseY);

      // Put your mouseup stuff here
    }

    function handleMouseOut(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      $("#outlog").html("Out: "+ mouseX + " / " + mouseY);

      // Put your mouseOut stuff here
    }

    function handleMouseMove(e){
      mouseX=parseInt(e.clientX-offsetX);
      mouseY=parseInt(e.clientY-offsetY);
      $("#movelog").html("Move: "+ mouseX + " / " + mouseY);

      // Put your mousemove stuff here

    }

    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    $("#canvas").mouseout(function(e){handleMouseOut(e);});

}); // end $(function(){});
</script>

</head>

<body>
    <p>Move, press and release the mouse</p>
    <p id="downlog">Down</p>
    <p id="movelog">Move</p>
    <p id="uplog">Up</p>
    <p id="outlog">Out</p>
    <canvas id="canvas" width=300 height=300></canvas>

</body>
</html>

이 질문을 참조하십시오 : 내가 얻는 mouseEvent.offsetX는 실제 캔버스 크기보다 훨씬 큽니다 . 귀하의 상황에 정확히 맞는 함수를 제공했습니다.


캔버스 이벤트에서 올바른 마우스 클릭 또는 마우스 이동 위치를 계산하는 가장 쉬운 방법은 다음과 같은 작은 방정식을 사용하는 것입니다.

canvas.addEventListener('click', event =>
{
    let bound = canvas.getBoundingClientRect();

    let x = event.clientX - bound.left - canvas.clientLeft;
    let y = event.clientY - bound.top - canvas.clientTop;

    context.fillRect(x, y, 16, 16);
});

If the canvas has padding-left or padding-top, subtract x and y via:

x -= parseFloat(style['padding-left'].replace('px'));
y -= parseFloat(style['padding-top'].replace('px'));

참고URL : https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas

반응형