How to drag an image inside HTML5 Canvas

The HTML

<h1>Click Image then Drag</h1>
<canvas id="canvas" 
width="500"
height="500"
style="border: 1px solid black">
<canvas>

The <canvas> was made to have 500px by 500px to be wide enough to drag the image. Since the web page is white and the <canvas> defaults to white, I added a thin black border around the canvas for effective testing.

Setup after the window loads

The window must finish loading before anything else happens. If the window hasn’t loaded yet, chances are the HTML tags wouldn’t have been created yet. Meaning they can’t be accessed by, for example, getElementById().

window.onload = function() {
canvas = document.getElementById(“canvas”);
context = canvas.getContext(“2d”);
 currentX = canvas.width/2;
currentY = canvas.height/2;
 star_img.src = “star.png”;
star_img.onload = function() {
_Go();
};
};

After the window loads, setup the canvas instance and the context of the canvas. The global variables currentX and currentY are set to the center of the canvas. In turn, the image is drawn at the center of the canvas. This is also the right time to load the pictures to be drawn on the canvas. Once the star image has been loaded, a method _Go() is called.

The _Go() method

The _Go() method gets things going. Since the window has finished loading, the canvas instance has been set and the image has been loaded, the mouse events must be configured as well as drawing the image.

function _Go() {
_MouseEvents();

setInterval(function() {
_DrawImage();
}, 1000/30);
}

The other important thing about this method is the setInterval(). To be able to drag an image, setInterval() is necessary to draw the image on its new x and y location inside the <canvas>.

Drawing the image

function _DrawImage() {
context.drawImage(star_img, currentX-(star_img.width/2), currentY-(star_img.height/2));
}

Changes in the currentX and currentY determines the new location of the image inside the canvas. currentX and currentY are changed via dragging.

Reset the canvas

But as we drag the image within the canvas, many star images are still drawn with their previous currentX and currentY.

Dragging an image in HTML5 Canvas

This might be ideal for visual effects but it’s not ideal when we just want a clean dragging of the image in the canvas. So we need to reset the canvas every time before we draw the image.

setInterval(function() {
_ResetCanvas()
_DrawImage();
}, 1000/30);

And the _ResetCanvas() looks like this:

function _ResetCanvas() {
context.fillStyle = '#fff';
context.fillRect(0,0, canvas.width, canvas.height);
}

In a sense, we are wiping white color to the entire canvas covering previous colors and drawn objects. This way, we won’t see stars still being drawn in the canvas with their previous positions.

The Mouse Events!

In this example, the only time a user can drag the image in the canvas is when the user left clicked the image. We detect if the mouse’ x and y positions are somewhere along the image’s position. If the mouse’ x and y positions are somewhere along the image’s position then the image is drag-able. To do this, onmousedown event is used.

onmousedown

canvas.onmousedown = function(e) {
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;


if (mouseX >= (currentX - star_img.width/2) &&
mouseX <= (currentX + star_img.width/2) &&
mouseY >= (currentY - star_img.height/2) &&
mouseY <= (currentY + star_img.height/2)) {
isDraggable = true;
}
};

onmouseup

The only time the image is not drag-able is when the user has essentially let go of the image by not holding down the left click of the mouse anymore.

canvas.onmouseup = function(e) {
isDraggable = false;
};

onmouseout

The other time is when the mouse’ location is not in the canvas anymore.

canvas.onmouseout = function(e) {
isDraggable = false;
};

onmousemove

Dragging changes the currentX and currentY. They are set when the mouse is moving in the canvas and when isDraggable is true.

canvas.onmousemove = function(e) {
if (isDraggable) {
currentX = e.pageX - this.offsetLeft;
currentY = e.pageY - this.offsetTop;
}
};

Enjoy.

— This article can also be found at junerockwell.com