HTML5 Canvas 笔划不跟随鼠标 Y 点

HTML5 Canvas stroke not following mouse Y point

我正在 HTML5 Canvas 中编写绘图应用程序,其中包括用鼠标徒手绘制。

我有一个问题,即移动鼠标以绘制笔画时不在十字准线光标下。 X 坐标很好,但是 Y 坐标随着鼠标指针的移动而偏移了不同的量(越靠近页面顶部,越靠近底部越远)。

跟上面的'header bar'div有关系

这是代码。

<style>
#divContainer {
    width: 100%;
    height: 100%;
}
#divHeader {
    position: absolute;
    left: 0px;
    top: 0px;
    right: 0px;
    height: 28px;
    background-color: #333;
}
#divContentArea {
    position: absolute;
    left: 0px;
    top: 29px;
    right: 0px;
    bottom: 5px;
}
#divContentCenter {
    position: absolute;
    top: 0px;
    left: 0px;
    bottom: 0px;
    right:0px;
}

.canvascontainer {
  position: relative;
  overflow: auto;
  width:100%;
  height:100%;
}

.canvas {
   cursor: crosshair;
   width: 100%;
   height: 100%;
   position:absolute;
   left:0px;
   top:0px;
   z-index: 2;
}

.maincanvas {
   cursor: crosshair;
   width: 100%;
   height: 100%;
   position:absolute;
   left:0px;
   top:0px;
   z-index: 1;
}
</style>

<div id="divContainer">

   <div id="divHeader">
    The Header
   </div>

   <div id="divContentArea">
      <div id="divContentCenter">

         <div id='canvascontainer'  class='canvascontainer' >
            <canvas id="canvas" class='canvas'>
            Sorry, your browser does not support a canvas object.
            </canvas>
            <canvas id="maincanvas" class='maincanvas'>
            Sorry, your browser does not support a canvas object.
            </canvas>
         </div>

      </div>
   </div>

</div>

<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

const canrect = canvas.getBoundingClientRect();

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

var maincanvas = document.getElementById('maincanvas');
var maincontext = maincanvas.getContext('2d');

maincanvas.width = window.innerWidth;
maincanvas.height = window.innerHeight;

var lastPoint;
var startPoint;


var isDrawing = false;

context.lineWidth = 3;
context.lineJoin = context.lineCap = 'round';
context.setLineDash([0, 0]);
context.globalAlpha = 1.0;

function drawGuideLines() {
   
   for ( i = 0; i < canvas.height; i += 20 ) {
      context.beginPath(); 
      context.setLineDash([2, 2]);
      context.lineWidth = 1;
      if ( i % 60 == 0 ) {
         context.lineWidth = 2;
      }
      context.strokeStyle = '#ccc';
      context.moveTo(0,i);
      context.lineTo(canvas.width,i);
      context.stroke();
   }
   for ( i = 0; i < canvas.width; i += 20 ) {
      context.beginPath(); 
      context.setLineDash([2, 2]);
      context.lineWidth = 1;
      if ( i % 60 == 0 ) {
         context.lineWidth = 2;
      }
      context.strokeStyle = '#ccc';
      context.moveTo(i,0);
      context.lineTo(i, canvas.height);
      context.stroke();
   }

}

function getMousePos(e) {
    return {
      x: e.offsetX - canrect.left,
      y: e.offsetY + canrect.top
    };
}

function clearPage() {
   context.clearRect(0, 0, canvas.width, canvas.height);
}

function copyToMain () {

   maincontext.drawImage(canvas, 0, 0);
   clearPage();

}

canvas.onmousedown = function(e) {

   isDrawing = true;   
   canvas.addEventListener("mousemove", drawDirectPath, false);

   lastPoint = { x: e.clientX, y: e.clientY };
   lastPoint = { x: e.offsetX, y: e.offsetY };
//   lastPoint = { x: e.offsetX, y: e.PageY };
   lastPoint = getMousePos(e);
      
};

function drawDirectPath(e) {

   if (!isDrawing) return;

   context.beginPath();
   context.setLineDash([0, 0]);
   context.lineWidth = 3;
   context.strokeStyle = 'red';
   context.fillStyle = 'red';

   //show_mouse_info(e, 'GetMousePos:' + getMousePos(e).x + ', ' + getMousePos(e).y);
   //show_mouse_info(e, 'boundrect:' + canrect.x + ', ' + canrect.y);

   //mx = e.clientX;
   //my = e.clientY;
   mx = e.offsetX;
   my = e.offsetY;

   context.moveTo(lastPoint.x, lastPoint.y);
   context.lineTo(mx, my);
   context.stroke();
   lastPoint = { x: mx, y: my };

}


canvas.onmouseup = function() {
   isDrawing = false;
   copyToMain ();
};

canvas.onmouseleave = function() {
   isDrawing = false;
   copyToMain ();
};

drawGuideLines();

</script>

我已经尝试使用 OffsetX/Y、PageX/Y、clinetX/Y 来查看这些是否有所作为,但我无法解决问题。

测试,鼠标点击右上角或左上角drag/draw斜向下到对面底角看效果

不要使用 CSS 为 canvas 设置 100% 的宽度和高度。

.canvas {
   cursor: crosshair;
   position:absolute;
   left:0px;
   top:0px;
   z-index: 2;
}

结合您可能要考虑的其他事项

始终声明变量for (let i =...

不要将 getBoundingClientRect() 设为常量。这样做的原因是,如果您需要添加一个调整大小的函数,您将无法更改边界,因为该变量保留了原始边界。

您一遍又一遍地分配 lastPoint。不太确定这是关于什么的。

   lastPoint = { x: e.clientX, y: e.clientY };
   lastPoint = { x: e.offsetX, y: e.offsetY };
//   lastPoint = { x: e.offsetX, y: e.PageY };
   lastPoint = getMousePos(e);