HTML5响应式画布中的鼠标位置

5

我已经搜索了其他的问题,但没有一个符合我的情况。

我有一个画布元素:

<canvas id="linear-synoptic-map" width="1053px" height="1000px" ng-click="linearSynopticCtrl.canvasClicked($event)" ng-mousemove="linearSynopticCtrl.mouseMovedOverCanvas($event)">
</canvas>

我正在使用这个函数获取位置:

linearSynopticCtrl.getPositionFromEvent = function (event) {
  var rect = linearSynopticCtrl.canvas.getBoundingClientRect();
  var x = event.x - rect.left;
  var y = event.y - rect.top;
  return new Point(x,y);
};

问题在于画布需要具有响应性,因此我添加了以下CSS规则:
canvas#linear-synoptic-map {
  width: 100%;
}

当画布的尺寸缩小或放大超过定义值(1053x1000),就会发生调整大小。此时,正确的鼠标位置与函数返回的位置之间会出现间隙。
我还尝试使用以下方法获取位置:
linearSynopticCtrl.getPositionFromEvent = function (event) {
  var x = event.x - linearSynopticCtrl.canvas.offsetLeft;
  var y = event.y - linearSynopticCtrl.canvas.offsetTop;
  return new Point(x,y);
};

但我的结果要差得多。

有人知道如何解决这个问题吗?


3
尝试在窗口调整大小时将画布的实际宽度和高度调整为适合屏幕尺寸,而不是使用CSS缩放,然后使用drawImage将图像拉伸到相应大小。当然,您必须追踪手动缩放并相应地调整鼠标位置。 - Frank
1个回答

5

鼠标坐标永远不会被缩放。

因此,您必须缩放鼠标坐标,以反映缩放后的画布。

下面是一种使您的画布具有响应性并获得缩放鼠标坐标的方法:

// handle responsively resizing the canvas   
var scale=1.00;
var originalWindowWidth=window.innerWidth;
var originalCanvasWidth=document.getElementById('canvas').width;
function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};
var resizeCanvas = debounce(function() {
  scale=window.innerWidth/originalWindowWidth;
  $('#canvas').css('width',originalCanvasWidth*scale);
}, 250);
window.addEventListener('resize', resizeCanvas);

// now, do normal app stuff

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

$("#canvas").mousemove(function(e){handleMouseMove(e);});

ctx.fillRect(50,50,100,100);
ctx.fillText('Rect drawn at [50,50]',50,35);

function handleMouseMove(e){

  var rect = canvas.getBoundingClientRect();
  var x = parseInt((event.x - rect.left)/scale);
  var y = parseInt((event.y - rect.top)/scale);

  $('#mouse').text(x+'/'+y);

}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Mouse will report rect corner at<br>[50,50] even after resizing window</h4>
<h4 id=mouse>mouse</h4>
<canvas id="canvas" width=300 height=300></canvas>


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