Zach
Zach

Reputation: 5113

HTML5 Canvas distortion

I am trying to include a canvas element over a dynamically sized video that will load asynchronously. On the canvas, the user will be able to drag and resize a rectangle selection box.

In my JS file, I have a listener watching the window and resizing the canvas via the canvas element's .width and .height properties to be the exact width and height of the video.

For the JS rectangular select code, I am following the fiddle from the first answer to this StackOverflow question: drawing a rectangle with mouse click and drag - javascript, however, for some reason, when the user is scrolled down on the page drawing on the canvas is completely distorted, and rectangles start being drawn pretty far away from the mouse. When the user is at the top of the page, however, the rectangle draws at the correct position. Why would this happen?

Below is some of the JS code I am using:

  
// Happens on mousedown event
  downCanvas: function(e) {
    $('.label-grid-canvas').css('cursor','crosshair');
    this.isDrawing = true
    this.startX = parseInt(e.clientX - this.offsetX);
    this.startY = parseInt(e.clientY - this.offsetY);
  },
  
// Happens on mouseup event
  upCanvas: function(e) {
    this.isDrawing = false;
    $('.label-grid-canvas').css('cursor','default');
  },
  // Happens on mousemove event
  moveCanvas: function(e) {
    if (this.isDrawing) {
      var mouseX = parseInt(e.clientX - this.offsetX);
      var mouseY = parseInt(e.clientY - this.offsetY);

      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      this.ctx.beginPath();
      this.ctx.rect(this.startX, this.startY, mouseX - this.startX, mouseY - this.startY);
      this.ctx.stroke();
    }
  },

  resizeCanvas: function() {
    this.canvas.width = $('#video-canvas')[0].offsetWidth;
    this.canvas.height = $('#video-canvas')[0].offsetHeight;

    this.canvasOffset = $('.label-grid-canvas').offset();
    this.offsetX = this.canvasOffset.left;
    this.offsetY = this.canvasOffset.top;

    this.redraw();
  },

  redraw: function() {
    this.ctx.strokeStyle = 'blue';
    this.ctx.lineWidth = '2';
    this.ctx.strokeRect(0, 0, $('#video-canvas')[0].offsetWidth,
        $('#video-canvas')[0].offsetHeight);
  },

// Happens after page-load
  initialize: function(options) {
    this.canvas = document.getElementById('label-grid-canvas');
    this.isDrawing = false;
    this.ctx = this.canvas.getContext('2d');
    this.startX;
    this.startY;
    this.canvasOffset = $('.label-grid-canvas').offset();
    this.offsetX = this.canvasOffset.left;
    this.offsetY = this.canvasOffset.top;
    $(window).on('resize', _.bind(this.resizeCanvas, this));
 ....
}

Please disregard the inefficiencies, I am just first trying to hack a working thing together before cleaning it up.

Upvotes: 0

Views: 2533

Answers (1)

markE
markE

Reputation: 105035

Here's skeleton showing how to account for resizing and scrolling when calculating mouse position.

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }

var isDown=false;
var startX,startY,mouseX,mouseY;

var $mouse=$('#mouse');
$("#canvas").mousemove(function(e){handleMouseMove(e);});

function handleMouseMove(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  // calc the current mouse position
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  // report the mouse position
  $mouse.text('Mouse position: '+mouseX+' / '+mouseY);
}
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 id=mouse>Move the mouse around the canvas.</h4>
<canvas id="canvas" width=300 height=300></canvas>

Upvotes: 2

Related Questions