I just started learning html5 and I am trying to create a battleship interface with draggable ships. I need help making my dragging methods work. I am purposely not using a libr
This is the procedure for making an html shape draggable
Note that this has been answered before on SO (many times!)
But this answer illustrates the new context.isPointInPath method to hit-test whether a point is inside an html canvas path.
Hopefully, this new hit-testing method will be new & useful to the OP and others :)
Here's the general procedure for dragging shapes in html canvas:
On mouseDown:
On mouseUp
On mouseMove
MouseDown handler code:
function handleMouseDown(e){
// get the current mouse position relative to the canvas
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// save this last mouseX/mouseY
lastX=mouseX;
lastY=mouseY;
// set the mouseIsDown flag
mouseIsDown=true;
}
MouseUp handler code:
function handleMouseUp(e){
// clear the mouseIsDown flag
mouseIsDown=false;
}
MouseMove handler code:
This code illustrates using context.isPointInPath
to hit-test an html canvas path
The procedure to do that is:
context.isPointInPath(x,y)
to test if x,y are inside the path defined above.Here's the mouseMove handler using context.isPointInPath
function handleMouseMove(e){
// if the mouseIsDown flag is’nt set, no work to do
if(!mouseIsDown){ return; }
// get mouseX/mouseY
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// for each ship in the ships array
// use context.isPointInPath to test if it’s being dragged
for(var i=0;i<ships.length;i++){
var ship=ships[i];
drawShip(ship);
if(ctx.isPointInPath(lastX,lastY)){
// if this ship’s being dragged,
// move it by the change in mouse position from lastXY to currentXY
ship.x+=(mouseX-lastX);
ship.y+=(mouseY-lastY);
ship.right=ship.x+ship.width;
ship.bottom=ship.y+ship.height;
}
}
// update the lastXY to the current mouse position
lastX=mouseX;
lastY=mouseY;
// draw all ships in their new positions
drawAllShips();
}
Note about enhancing performance:
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/sEBAC/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.strokeStyle="lightgray";
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var mouseIsDown=false;
var lastX=0;
var lastY=0;
var ships=[];
// make some ship
makeShip(20,30,50,25,"skyblue");
makeShip(20,100,30,25,"skyblue");
makeShip(20,170,50,25,"salmon");
makeShip(20,240,30,25,"salmon");
function makeShip(x,y,width,height,fill){
var ship={
x:x,
y:y,
width:width,
height:height,
right:x+width,
bottom:y+height,
fill:fill
}
ships.push(ship);
return(ship);
}
drawAllShips();
function drawAllShips(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<ships.length;i++){
var ship=ships[i]
drawShip(ship);
ctx.fillStyle=ship.fill;
ctx.fill();
ctx.stroke();
}
}
function drawShip(ship){
ctx.beginPath();
ctx.moveTo(ship.x,ship.y);
ctx.lineTo(ship.right,ship.y);
ctx.lineTo(ship.right+10,ship.y+ship.height/2);
ctx.lineTo(ship.right,ship.bottom);
ctx.lineTo(ship.x,ship.bottom);
ctx.closePath();
}
function handleMouseDown(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// mousedown stuff here
lastX=mouseX;
lastY=mouseY;
mouseIsDown=true;
}
function handleMouseUp(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// mouseup stuff here
mouseIsDown=false;
}
function handleMouseMove(e){
if(!mouseIsDown){ return; }
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// mousemove stuff here
for(var i=0;i<ships.length;i++){
var ship=ships[i];
drawShip(ship);
if(ctx.isPointInPath(lastX,lastY)){
ship.x+=(mouseX-lastX);
ship.y+=(mouseY-lastY);
ship.right=ship.x+ship.width;
ship.bottom=ship.y+ship.height;
}
}
lastX=mouseX;
lastY=mouseY;
drawAllShips();
}
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>