鼠标光标与画布不匹配。

3

我有一个问题:当我在画布上画线时,鼠标位置似乎与画布位置不匹配,所以每次我画的时候,我的光标和绘图线之间会有一些距离..请帮我解决这个问题,以下是我的代码:

$(document).ready(function(){

        context = document.getElementById('canvasInAPerfectWorld').getContext("2d");


        $('#canvasInAPerfectWorld').mousedown(function(e){
          var mouseX = e.pageX - this.offsetLeft;
          var mouseY = e.pageY - this.offsetTop;

          paint = true;
          addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
          redraw();
        });

        $('#canvasInAPerfectWorld').mousemove(function(e){ 
          if(paint){
            addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
            redraw();
          }
        });


        $('#canvasInAPerfectWorld').mouseup(function(e){
          paint = false;
        });

        $('#canvasInAPerfectWorld').mouseleave(function(e){
          paint = false;
        });         

});


    var clickX = new Array();
    var clickY = new Array();
    var clickDrag = new Array();
    var paint;

    function addClick(x, y, dragging)
    {
      clickX.push(x);
      clickY.push(y);
      clickDrag.push(dragging);
    }   

    function clear_canvas(){
        //alert('masuk claear');
        context.clearRect(0,0,context.canvas.width,context.canvas.height);  

    }

    function redraw(){        

      context.strokeStyle = "#df4b26";
      context.lineJoin = "round";
      context.lineWidth = 5;

      for(var i=0; i < clickX.length; i++) {        
        context.beginPath();
        if(clickDrag[i] && i){
          context.moveTo(clickX[i-1], clickY[i-1]);
         }else{
           context.moveTo(clickX[i]-1, clickY[i]);
         }
         context.lineTo(clickX[i], clickY[i]);
         context.closePath();
         context.stroke();
      }
    } 

您能否添加一个 Fiddle 或 Plunker,以便我们可以准确快速地重现您的问题? - user1823
无法重现您的问题。链接 - Teemu
2个回答

3

在鼠标事件处理程序中,this 指的是窗口对象,而 this.offsetLeft 是未定义的。

您可以使用 getBoundingClientRect 来获取画布元素的边界:

// get a reference to your canvas element at the start of your app
var canvas=document.getElementById('canvasInAPerfectWorld');

// example mousedown handler

// get the current canvas offsets using getBoundingClientRect
var BB=canvas.getBoundingClientRect();
var offsetX=BB.left;
var offsetY=BB.top;        

// calculate the current mouse position relative to the canvas
// using e.client and the offsets calculated above
var mouseX=parseInt(e.clientX-offsetX);
var mouseY=parseInt(e.clientY-offsetY);

如果您的画布与视口不重新定位,您可以在应用程序启动时一次性获取偏移量,这样它们就不需要在鼠标处理程序内每次重新计算。

这对我有用 - 只需进行这一个修改。我将“canvas”设置为事件目标对象,如下所示:var canvas = e.target; - b0rgBart3

0

您可以按照markE的答案中提供的解决方案进行操作(也可以在这里找到)。

或者,如果您的布局允许,可以执行以下操作:

  • 将画布元素设置为相对定位
  • 使用layerXlayerY读取鼠标位置

这种方法可以使代码更简单。

两种方法都会受到填充和边框厚度的影响(如果使用任何一个,则需要减去它们)。如果您想要边框/填充,最好将画布包装在一个div中,然后样式化该div。

使用相对定位的示例

var c = document.querySelector("canvas"),
    ctx = c.getContext("2d");

ctx.font = "bold 16px sans-serif";

c.onmousemove = function(e) {
  
  var x = e.layerX,
      y = e.layerY;

  ctx.clearRect(0, 0, 300, 20);
  ctx.fillText("x: " + x + ", y: " + y, 10, 16);
};
div {padding:20px}
canvas {background:#eee; position:relative}
<div><div><canvas></canvas></div></div>

使用 getBoundingClientRect() 的示例

var c = document.querySelector("canvas"),
    ctx = c.getContext("2d");

ctx.font = "bold 16px sans-serif";

c.onmousemove = function(e) {
  
  var rect = this.getBoundingClientRect(),
      x = e.clientX - rect.left,
      y = e.clientY - rect.top;

  ctx.clearRect(0, 0, 300, 20);
  ctx.fillText("x: " + x + ", y: " + y, 10, 16);
};
div {padding:20px}
canvas {background:#eee; position:relative}
<div><div><canvas></canvas></div></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接