Mouse position within HTML 5 responsive Canvas

随声附和 提交于 2021-02-07 13:47:01

问题


I've searched through other questions but none of them fit my case.

I have a canvas element:

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

And I'm getting the position with this function:

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);
};

The problem is that the canvas needs to be responsive so I've added the following css rule:

canvas#linear-synoptic-map {
  width: 100%;
}

When the resizing happens (when the canvas dimension is shrinked over definition or enlarged over definition: 1053x1000) a gap starts to show between the correct mouse position and the returned position by the function.

I have also tried obtaining the position with this approach:

linearSynopticCtrl.getPositionFromEvent = function (event) {
  var x = event.x - linearSynopticCtrl.canvas.offsetLeft;
  var y = event.y - linearSynopticCtrl.canvas.offsetTop;
  return new Point(x,y);
};

But I get much worse results.

Does anyone know how to fix this problem?


回答1:


Mouse coordinates are never scaled.

Therefore, you must scale the mouse coordinates for them to reflect the scaled canvas.

Here's one way to make your canvas responsive and get scaled mouse coordinates:

// 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>


来源:https://stackoverflow.com/questions/28628964/mouse-position-within-html-5-responsive-canvas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!