简体   繁体   中英

Mouse position within HTML 5 responsive Canvas

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?

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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM