I'm studying jquery and html5 canvas. All I want to do is a simple html5 drawing example. When the mouse move, I draw red squares under my mouse.
My code is simple, but I have a problem getting the mouse cursor position within the canvas.
Right now, I am using x=event.offsetX; to get the mouse position. This works very well in chrome, however when it comes to firefox, it doesn't work. I changed the code to x=event.layerX. but it seems that layerX is the position of my mouse relative to the web page, not the position of the canvas. because I always see an offset.
I have two questions, first, what is the right thing to do to get the correct mouse position under firefox. second, how can i write a code that works for ie, firefox, chrome, safari and opera?
here is my code:
<!doctype html />
<html><head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(
function(){
var flip = document.getElementById('flip');
var context = flip.getContext('2d');
context.fillStyle = "rgb(255,255,255)";
context.fillRect(0, 0, 500, 500);
$("a").click(function(event){alert("Thanks for visiting!");});
$("#flip").mousemove(function(event){
var x, y;
x = event.layerX;
y = event.layerY;
//alert("mouse pos"+event.layerX );
var flip = document.getElementById('flip');
var context = flip.getContext('2d');
context.fillStyle = "rgb(255,0,0)";
context.fillRect(x, y, 5, 5);
}
);
}
);
</script>
</head> <body bgcolor="#000000"> jQuery<canvas id="flip" width="500" height="500">
This text is displayed if your browser does not support HTML5 Canvas.</canvas> </body></html>
I see plenty of question on this subject and all propose to browse DOM or use offsetX and offsetY, which are not always set right.
You should use the function: canvas.getBoundingClientRect() from the canvas API.
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y);
}, false);
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8">
<script>
Element.prototype.leftTopScreen = function () {
var x = this.offsetLeft;
var y = this.offsetTop;
var element = this.offsetParent;
while (element !== null) {
x = parseInt (x) + parseInt (element.offsetLeft);
y = parseInt (y) + parseInt (element.offsetTop);
element = element.offsetParent;
}
return new Array (x, y);
}
document.addEventListener ("DOMContentLoaded", function () {
var flip = document.getElementById ("flip");
var xy = flip.leftTopScreen ();
var context = flip.getContext ("2d");
context.fillStyle = "rgb(255,255,255)";
context.fillRect (0, 0, 500, 500);
flip.addEventListener ("mousemove", function (event) {
var x = event.clientX;
var y = event.clientY;
context.fillStyle = "rgb(255, 0, 0)";
context.fillRect (x - xy[0], y - xy[1], 5, 5);
});
});
</script>
<style>
#flip {
border: 1px solid black;
display: inline-block;
}
body {
text-align: center;
}
</style>
</head>
<body>
<canvas id = "flip" width = "500" height = "500">This text is displayed if your browser does not support HTML5 Canvas.</canvas>
</body>
</html>
You don't have to worry about compatibility, only IE (prior 9) does not support canvas natively.
You will need a custom function to work out where the element is and then work out where the mouse is within that element. Here is an example. It uses this function from quirks mode and my JavaScript library which should not be difficult to translate into jQuery.
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return [curleft, curtop];
}
}
EDIT
This will not work in IE due to it not supporting pageX. You will have to pass the event object through a function like this to correct that. But as 2x2p1p said, canvas is not supported by any Internet Explorer below version 9.
Related
I'm working on a script which is supposed to do the following. You lock your mouse to a canvas. It will show you an "artificial" cursor instead that you can also move by using your mouse. Under this cursor, you will have a circle which also moves with the mouse.
All of this worked perfectly fine with my script which was until I added another nice feature: I want to have an Arrow in the middle of the canvas which stays there, exact same size, but rotates according to your cursor movement. To give you an idea what I'm talking about, I made these example graphs (don't worry about dimensions and colour).
https://i.stack.imgur.com/poO6n.jpg
https://i.stack.imgur.com/twXhY.jpg
https://i.stack.imgur.com/RFFBe.jpg
I did some calculations to do this, implemented them, hoped for the best, but it doesn't work. I thought when it works, it will be a cool feature for everyone to have on this site. But so far I didn't see where my mistake is. If you have a clue, I'm absolutely grateful for every answer.
Many thanks!
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>ArrowSpin</title>
<style>
html, body {
margin: 0;
padding: 0;
}
html {
font-family: sans-serif;
}
canvas {
display: block;
margin: 0 auto;
border: 1px solid black;
}
.information {
width: 640px;
margin: 0 auto 50px;
}
#tracker {
position: absolute;
top: 0;
right: 10px;
background-color: white;
}
h1 {
font-size: 200%;
}
</style>
</head>
<body>
<div class="information">
<img id="mousecursor" hidden="true" width="13" height="20.5" src="mousecursor.png" alt="Cursor">
<p id="demo" style="color: black" oncl></p>
<p id="Message" style="color: black" oncl></p>
<canvas id="myCanvas" width="640" height="360">
Your browser does not support HTML5 canvas
</canvas>
<div id="tracker"></div>
</div>
<script>
try {
// helper functions
const RADIUS = 20;
// this image is you mousecursor
var img = document.getElementById("mousecursor");
// degree to radians
function degToRad(degrees) {
var result = Math.PI / 180 * degrees;
return result;
}
// generate a random number, later on, mouse cursor should start at random position, now unused
function generateRandomNumber() {
var minangle = 0;
var maxangle = 2*Math.PI;
randangle = Math.random() * (maxangle- minangle) + minangle;
return randangle;
};
//this function draws the actual arrow
function drawArrow(fromx, fromy, tox, toy, colourarrow){
//variables to be used when creating the arrow
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var headlen = 3;
var angle = Math.atan2(toy-fromy,tox-fromx);
//starting path of the arrow from the start square to the end square and drawing the stroke
ctx.beginPath();
ctx.moveTo(fromx, fromy);
ctx.lineTo(tox, toy);
ctx.strokeStyle = colourarrow;
ctx.lineWidth = 20;
ctx.stroke();
//starting a new path from the head of the arrow to one of the sides of the point
ctx.beginPath();
ctx.moveTo(tox, toy);
ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
//path from the side point of the arrow, to the other side point
ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7));
//path from the side point back to the tip of the arrow, and then again to the opposite side point
ctx.lineTo(tox, toy);
ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
//draws the paths created above
ctx.strokeStyle = colourarrow;
ctx.lineWidth = 20;
ctx.stroke();
ctx.fillStyle = colourarrow
ctx.fill();
}
// this function calculates the current angle of the cursor from the exact middle of the canvas (x0,y0) by using two simple assumptions which are a) radius=sqrt(sqr(xfrom)+sqr(y)) b) x=x0+radius*cos(alpha) <=> alpha=arccos((x-x0)/radius)
function CursorAngle() {
var currentrad=Math.sqrt([Math.pow(x-canvas.width/2)+Math.pow(y+canvas.height)]);
var currentangle=Math.acos([(x-canvas.width/2)/currentrad]);
return currentangle
}
//in this function I use the just calculated cursor angle to now calculate where my arrow shall begin and end, again I use x=x0+radius*cos(alpha) and y=y0+radius*sin(alpha). In this case I always want my arrow to have a radius of 50 and I always want it to be drawn in the center of the canvas.
function ProbeAngle(alpha) {
var x1 = canvas.width/2+50*cos(alpha)
var y1 = canvas.width/2+50*sin(alpha)
var x2 = canvas.width/2+50*cos(alpha+Math.PI)
var y2 = canvas.width/2+50*sin(alpha+Math.PI)
return [x1; y1; x2; y2]
}
// setup of the canvas
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var x = canvas.width/2;
var y = canvas.height/2;
//refresh the canvas
function canvasDraw() {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#f00";
ctx.beginPath();
ctx.arc(x, y, RADIUS, 0, degToRad(360), true);
ctx.fill();
ctx.drawImage(img, x, y);
}
canvasDraw();
// pointer lock object forking for cross browser
canvas.requestPointerLock = canvas.requestPointerLock ||
canvas.mozRequestPointerLock;
document.exitPointerLock = document.exitPointerLock ||
document.mozExitPointerLock;
canvas.onclick = function() {
canvas.requestPointerLock();
canvasDraw();
};
// pointer lock event listeners
// Hook pointer lock state change events for different browsers
document.addEventListener('pointerlockchange', lockChangeAlert, false);
document.addEventListener('mozpointerlockchange', lockChangeAlert, false);
function lockChangeAlert() {
if (document.pointerLockElement === canvas ||
document.mozPointerLockElement === canvas) {
console.log('The pointer lock status is now locked');
document.addEventListener("mousemove", updatePosition, false);
} else {
console.log('The pointer lock status is now unlocked');
document.removeEventListener("mousemove", updatePosition, false);
}
}
//tracker shows x and y coordinates of "pseudo" cursor
var tracker = document.getElementById('tracker');
//border protection for our image not to move out of the canvas
var animation;
function updatePosition(e) {
x += e.movementX;
y += e.movementY;
if (x > canvas.width) {
x = canvas.width;
}
if (y > canvas.height) {
y = canvas.height;
}
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
tracker.textContent = "X position: " + x + ", Y position: " + y;
if (!animation) {
animation = requestAnimationFrame(function() {
animation = null;
canvasDraw();
//receive the ProbeCoords by using the functions CursorAngle and ProbeAngle and draw it!
var ProbeCoord = ProbeAngle(CursorAngle());
drawArrow(ProbeCoord[0],ProbeCoord[1],ProbeCoord[2],ProbeCoord[3],'white')
});
}
}
}
catch(err) {
document.getElementById("demo").innerHTML = err.message;
}
document.getElementById("Message").innerHTML = "potential Errorcode above";
</script>
</body>
</html>
Have you tried using Fabric JS? In the linked example you can click an object and a handle appears at the top. After that you can click handle and it will follow the mouse. I'm suggesting this because most likely there is a way to change the click event to a hover event and then get the handle to follow the mouse.
I'm creating circles in a Raphael.js Canvas with a clicking action. When the canvas is drawn at the origin of the website it works fine. But when I move it to the middle some type offseting happens and only when you click on the right side of the canvas the circles are drawn at the left side of the canvas. Even though I have my listener action to the canvas and not the div that the is append to, here is the code:
<body>
<div id="container"></div>
</body>
Here is the JS:
var canvas = Raphael("container", 500, 500);
var ourCanvas = $('svg').last();
ourCanvas.attr("id", "canvas");
var canvasHandler = $("#canvas");
//We create a div with a class to append our canvas
var containerHandler = $("#container");
var circleClass = $("circle.quincy");
var justDragged = false;
canvasHandler.mouseup(function (e) {
var mouseX = e.pageX;
var mouseY = e.pageY;
makeCircle(mouseX, mouseY);
});
function makeCircle(mouseX, mouseY) {
var radius;
var fill;
var thisCirclesID = String(new Date().getTime());
var circle = canvas.circle(mouseX, mouseY, 50).attr({
fill: "hsb(.8, 1, 1)",
stroke: "none",
opacity: .5,
});
}
Here is a JSFiddle
I wonder if the way that I'm using the event position is correct. Any suggestion is more than welcome.
Thanks
M
I figured it out after realizing that the offset of the new position of svg was causing the mouse event to not recognize its real position. I found this blog post that shows how to use the offsetParent method to calculate the new position of my canvas relative its parent . Here is the code:
$(document).ready(function () {
//We create our canvas and add an ID
var canvas = Raphael("container", 500, 500);
var ourCanvas = $('svg').last();
ourCanvas.attr("id", "canvas");
var canvasHandler = $("#canvas");
//We create a div with a class to append our canvas
var containerHandler = $("#container");
var circleClass = $("circle.quincy");
var justDragged = false;
canvasHandler.mouseup(function (e) {
var mouseX = e.pageX - findPos(this)[0];
var mouseY = e.pageY - findPos(this)[1];
makeCircle(mouseX, mouseY);
findPos(this);
console.log("This is the position of the mouse in X: " + e.pageX);
console.log("This is the position of the mouse in Y: " + e.pageY);
});
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj == obj.offsetParent);
console.log(curleft);
console.log(curtop);
// return [curleft, curtop];
}
return [curleft, curtop];
}
As you can see the findPos(obj) returns and array of the new position of X and Y. So I substract that to my mouseX and mouseY to get the real position on the svg when clicking.
Update
Doing more reading and asking around. I didn't realize what type of elements the web browser returns. Instead of using e.pageX and e.pageY. offsetX offers the position of the mouse in respect to the parent giving the real coordinates. So the code will look like this:
canvasHandler.mouseup(function (e) {
var mouseX = e.offsetX;
var mouseY = e.offsetY;
makeCircle(mouseX, mouseY);
findPos(this);
});
This makes it easier since the offset takes into consideration the real position of the mouse in respect to the element.
I'm currently learning canvas touch event function,I 'm able to draw line on the canvas, now I want to get the x and y coordinates when I draw any lines and show on the screen.please help and teach me how to get the x and y values, thank You!
here is the coding
<!DOCTYPE html>
<html><head>
<style>
#contain {
width: 500px;
height: 120px;
top : 15px;
margin: 0 auto;
position: relative;
}
</style>
<script>
var canvas;
var ctx;
var lastPt=null;
var letsdraw = false;
var offX = 10, offY = 20;
function init() {
var touchzone = document.getElementById("layer1");
touchzone.addEventListener("touchmove", draw, false);
touchzone.addEventListener("touchend", end, false);
ctx = touchzone.getContext("2d");
}
function draw(e) {
e.preventDefault();
if (lastPt != null) {
ctx.beginPath();
ctx.moveTo(lastPt.x, lastPt.y);
ctx.lineTo(e.touches[0].pageX - offX,
e.touches[0].pageY - offY);
ctx.stroke();
}
lastPt = {
x: e.touches[0].pageX - offX,
y: e.touches[0].pageY - offY
};
}
function end(e) {
var touchzone = document.getElementById("layer1");
e.preventDefault();
// Terminate touch path
lastPt = null;
}
function clear_canvas_width ()
{
var s = document.getElementById ("layer1");
var w = s.width;
s.width = 10;
s.width = w;
}
</script>
</head>
<body onload="init()">
<div id="contain">
<canvas id="layer1" width="450" height="440"
style="position: absolute; left: 0; top: 0;z-index:0; border: 1px solid #ccc;"></canvas>
</div>
</body>
</html>
Still not entirely confident I understand your question.
In the code you posted, you are already obtaining coordinates using e.touches[0].pageX/Y. The main problem with that is that the pageX/Y values are relative to the page origin. You are then subtracting fixed offX/Y in your code to try and convert these to canvas-relative coordinates. Right idea, wrong values. You need to subtract off the position of the canvas element which can be obtained by summing the offsetX/Y values as you traverse the tree upward using the offsetParent reference.
Something like:
offX=0;offY=0;
node = document.getElementById ("layer1");
do {
offX += node.offsetX;
offY += node.offsetY;
node = node.offsetParent;
} while(node);
should give you a better value for offX and offY.
If you just want to locate the actual drawing at the end, it would be easiest just to track a bounding box while the user draws.
I'm trying to draw a rectangle by a user click, mouse move, and click. There are two problems with my code.
Firstly, after one rectangle is drawn it is automatically assumed that another one will be drawn. Secondly, the starting point on the second rectangle is the last click that created the first rectangle.
http://jsbin.com/uqonuw/3/edit
You were close. So, the question isn't really about the "canvas" element in HTML5, but a canvas that is really a div.
http://jsfiddle.net/d9BPz/546/
In order for me to see what your code was trying to accomplish, I had to tidy it up. What needed to happen was tracking of the square element.
We are doing one of two things everytime we click on the canvas. We are either creating a rectangle element, or finishing a rectangle element. So, when we're finished it makes sense to set 'element' (previously named 'd') to null. When creating an element, we have to assign the new DOM element to 'element'.
Everytime the mouse moves, we want to get the mouse position. If the element is in the process of creation (or "not null"), then we need to resize the element.
Then we wrap it all up in a function, and that's all there is to it:
function initDraw(canvas) {
var mouse = {
x: 0,
y: 0,
startX: 0,
startY: 0
};
function setMousePosition(e) {
var ev = e || window.event; //Moz || IE
if (ev.pageX) { //Moz
mouse.x = ev.pageX + window.pageXOffset;
mouse.y = ev.pageY + window.pageYOffset;
} else if (ev.clientX) { //IE
mouse.x = ev.clientX + document.body.scrollLeft;
mouse.y = ev.clientY + document.body.scrollTop;
}
};
var element = null;
canvas.onmousemove = function (e) {
setMousePosition(e);
if (element !== null) {
element.style.width = Math.abs(mouse.x - mouse.startX) + 'px';
element.style.height = Math.abs(mouse.y - mouse.startY) + 'px';
element.style.left = (mouse.x - mouse.startX < 0) ? mouse.x + 'px' : mouse.startX + 'px';
element.style.top = (mouse.y - mouse.startY < 0) ? mouse.y + 'px' : mouse.startY + 'px';
}
}
canvas.onclick = function (e) {
if (element !== null) {
element = null;
canvas.style.cursor = "default";
console.log("finsihed.");
} else {
console.log("begun.");
mouse.startX = mouse.x;
mouse.startY = mouse.y;
element = document.createElement('div');
element.className = 'rectangle'
element.style.left = mouse.x + 'px';
element.style.top = mouse.y + 'px';
canvas.appendChild(element)
canvas.style.cursor = "crosshair";
}
}
}
Usage: Pass the block-level element that you would like to make a rectangle canvas.
Example:
<!doctype html>
<html>
<head>
<style>
#canvas {
width:2000px;
height:2000px;
border: 10px solid transparent;
}
.rectangle {
border: 1px solid #FF0000;
position: absolute;
}
</style>
</head>
<body>
<div id="canvas"></div>
<script src="js/initDraw.js"></script>
<script>
initDraw(document.getElementById('canvas'));
</script>
</body>
</html>
Here's how to click-move-click to create a rectangle
Create these variables:
var isDrawing=false;
var startX;
var startY;
In your mousedown event handler:
If this is the starting click, set the isDrawing flag and set the startX/Y.
If this is the ending click, clear the isDrawing flage and draw the rectangle.
You might also want to change the mouse cursor so the user knows they are drawing.
if(isDrawing){
isDrawing=false;
ctx.beginPath();
ctx.rect(startX,startY,mouseX-startX,mouseY-startY);
ctx.fill();
canvas.style.cursor="default";
}else{
isDrawing=true;
startX=mouseX;
startY=mouseY;
canvas.style.cursor="crosshair";
}
Here is a Fiddle: http://jsfiddle.net/m1erickson/7uNfW/
Instead of click-move-click, how about using drag to create a rectangle?
Create these variables:
var mouseIsDown=false;
var startX;
var startY;
In your mousedown event handler, set the mouseIsDown flag and set the startX/Y.
Optionally, change the cursor so the user knows their dragging a rectangle.
mouseIsDown=true;
startX=mouseX;
startY=mouseY;
canvas.style.cursor="crosshair";
In your mouseup event handler, clear the mouseIsDown flag and draw the rect
If you changed the cursor, change it back.
mouseIsDown=false;
ctx.beginPath();
ctx.rect(startX,startY,mouseX-startX,mouseY-startY);
ctx.fill();
canvas.style.cursor="default";
For those who encountered the scrolling problem, I've found a fix.
You need to get the offset (using window.pageYOffset) and reduce it from the mouse position in any of the recommended snippets given. You should take it off from the height as well.
i was also working on a project, so here's my code
enjoy.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Selection</title>
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<style>
body {
margin: 0px;
background-color: #f1f1f1;
}
canvas {
border: none;
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="500"></canvas>
<div id="output"></div>
<script>
//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
//Mousedown
$(canvas).on('mousedown', function(e) {
last_mousex = parseInt(e.clientX-canvasx);
last_mousey = parseInt(e.clientY-canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function(e) {
mousedown = false;
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
//Mousemove
$(canvas).on('mousemove', function(e) {
mousex = parseInt(e.clientX-canvasx);
mousey = parseInt(e.clientY-canvasy);
if(mousedown) {
ctx.clearRect(0,0,canvas.width,canvas.height); //clear canvas
ctx.beginPath();
var width = mousex-last_mousex;
var height = mousey-last_mousey;
ctx.rect(last_mousex,last_mousey,width,height);
//ctx.fillStyle = "#8ED6FF";
ctx.fillStyle = 'rgba(164, 221, 249, 0.3)'
ctx.fill();
ctx.strokeStyle = '#1B9AFF';
ctx.lineWidth = 1;
ctx.fillRect(last_mousex, last_mousey, width, height)
ctx.stroke();
}
//Output
$('#output').html('current: '+mousex+', '+mousey+'<br/>last: '+last_mousex+', '+last_mousey+'<br/>mousedown: '+mousedown);
});
</script>
</body>
</html>
Below is the solution I created in React. There might be some corner cases but it is working as per my knowledge.
Solution approach.
You must have start (x,y position) and the end (x,y) position
Once the user clicks on the cell capture cell number and column number start (x,y), this will happen on the mouseDown event
Then the user starts moving the mouse, in that case capture the cell number and the row number end (x,y) respectively.
Now the div draw logic comes where the condition would highlight the cell if the below condition is true.
i = cellNumber
i >= Math.min(start,end) && i <= Math.max(start,end) && i%4 <= Math.max(startY, endY)
https://codesandbox.io/s/still-field-0q760y?file=/src/App.js
I want to implement dragging of an image within a canvas. I want simplest code for that. So far I have seen a lot of examples but they have used complex ways of implementation. I want an example that is easy to learn and implement.
It's pretty difficult. You'll first need to write a function that can detect when you click a particular element. However, before we can do that, we must define what we mean by "element". Is it the product of a single draw instruction (e.g. a rectangle or arc), or something complex? (Imagine I wanted to draw a cat and make the entire cat draggable as a unit.)
A canvas is nothing but a collection of pixels. If you want your program to have an idea of "shapes" or even "collections of shapes treated as a unit" you'll need to implement them yourself as data structures external to the canvas itself. Once you have that, you can write an onmousedown handler that takes the x/y point clicked and determine what shape (if any) the click falls inside of (and if it falls inside of multiple shapes, check which has the foremost z-index). Then add an onmousemove handler that erases and redraws the shape on the canvas based on the information in the shape data object.
This is a moderately difficult problem with very difficult prerequisite problems (creating data structures that can describe a wide range of shapes as well as collections of shapes). I highly recommend you use a canvas drawing library that has already solved these problems. I use cake.js but there are loads of options available.
If you don't have to use the HTML5 canvas, jQuery UI is a lot simpler:
HTML:
<img class="drag-me" src="http://www.google.com/images/srpr/logo3w.png">
JavaScript:
$(function() {
$('.drag-me').draggable();
});
See it in action:
http://jsfiddle.net/flackend/TQzSe/
The jQuery UI API has a lot of options too to make it act how you want:
http://jqueryui.com/demos/draggable/
Plus, if it doesn't do what you need, it's easy to implement yourself. Post here if you need help with that.
jsfiddle.net/Zevan/QZejF/5 This may help you.
<html>
<head>
<title>Test Page</title>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>
<canvas id="c" width = "500" height = "500" ></canvas>
<script type="text/javascript">
var canvas = $("#c");
var c = canvas[0].getContext("2d");
//var path = "http://wonderfl.net/images/icon/e/ec/ec3c/ec3c37ba9594a7b47f1126b2561efd35df2251bfm";
var path = "blue.jpg";
var path2 = "purple.jpg";
var image1 = new DragImage(path, 200, 100);
var image2 = new DragImage(path2, 300, 100);
var loop = setInterval(function() {
c.fillStyle = "gray";
c.fillRect(0, 0, 500, 500);
image1.update();
image2.update();
}, 30);
var mouseX = 0,
mouseY = 0;
var mousePressed = false;
var dragging = false;
canvas.mousemove(function(e) {
mouseX = e.offsetX;
mouseY = e.offsetY;
})
$(document).mousedown(function() {
mousePressed = true;
}).mouseup(function() {
mousePressed = false;
dragging = false;
});
function DragImage(src, x, y) {
var that = this;
var startX = 0,
startY = 0;
var drag = false;
this.x = x;
this.y = y;
var img = new Image();
img.src = src;
this.update = function() {
if (mousePressed ) {
var left = that.x;
var right = that.x + img.width;
var top = that.y;
var bottom = that.y + img.height;
if (!drag) {
startX = mouseX - that.x;
startY = mouseY - that.y;
}
if (mouseX < right && mouseX > left && mouseY < bottom && mouseY > top) {
if (!dragging){
dragging = true;
drag = true;
}
}
} else {
drag = false;
}
if (drag) {
that.x = mouseX - startX;
that.y = mouseY - startY;
}
c.drawImage(img, that.x, that.y);
}
}
</script>
</body>
</html>