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 library because I need make the ships draggable over another canvas interface (the battleship board), which I could not figure out how to do with the Kinetic library. I feel like I am close, but I cannot figure out the last bit. The ships should be smoothly dragged but they seem to snap to the location of the mouse when clicked...
Here is my clode:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Canvas Drag and Drop Test</title>
</head>
<body>
<section>
<div align=center>
<canvas id="canvas" width="550" height="550">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
</div>
<script type="text/javascript">
var canvas;
var ctx;
var x = 75;
var y = 50;
var WIDTH = 550;
var HEIGHT = 550;
var dragok = false;
var ships = [];
var ship;
var shipFill = "#FF0000";
//Definitions
//Draggable Carrier
var caRectX = 100;
var caRectY = 50;
var caRectHeight = 50;
var caRectWidth = 5 * 50;
var carrier = {
x : caRectX,
y : caRectY,
width : caRectWidth,
height : caRectHeight,
fill : shipFill,
dragging : false,
offsetX : 0,
offsetY : 0,
};
ships.push(carrier);
//Draggable Battleship
var bsRectX = 100;
var bsRectY = 150;
var bsRectHeight = 50;
var bsRectWidth = 4 * 50;
var battleship = {
x : bsRectX,
y : bsRectY,
width : bsRectWidth,
height : bsRectHeight,
fill : shipFill,
dragging : false,
offsetX : 0,
offsetY : 0,
};
ships.push(battleship);
//Draggable Patrolboat
var pbRectX = 100;
var pbRectY = 250;
var pbRectHeight = 50;
var pbRectWidth = 2 * 50;
var patrolboat = {
x : pbRectX,
y : pbRectY,
width : pbRectWidth,
height : pbRectHeight,
fill : shipFill,
dragging : false,
offsetX : 0,
offsetY : 0,
};
ships.push(patrolboat);
//Draggable Submarine
var suRectX = 100;
var suRectY = 350;
var suRectHeight = 50;
var suRectWidth = 3 * 50;
var submarine = {
x : suRectX,
y : suRectY,
width : suRectWidth,
height : suRectHeight,
fill : shipFill,
dragging : false,
offsetX : 0,
offsetY : 0,
};
ships.push(submarine);
//Draggable destroyer
var deRectX = 100;
var deRectY = 450;
var deRectHeight = 50;
var deRectWidth = 3 * 50;
var destroyer = {
x : deRectX,
y : deRectY,
width : deRectWidth,
height : deRectHeight,
dragging : false,
fill : shipFill
};
ships.push(destroyer)
function rect(x, y, w, h) {
ctx.beginPath();
ctx.rect(x, y, w, h);
ctx.closePath();
ctx.fill();
}
function clear() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
return setInterval(draw, 10);
}
function draw() {
clear();
ctx.fillStyle = "#FAF7F8";
rect(0, 0, WIDTH, HEIGHT);
ctx.fillStyle = "#444444";
for (var i = 0; i < ships.length; i++) {
rect(ships[i].x, ships[i].y, ships[i].width, ships[i].height);
}
}
function myMove(e) {
if (ship.dragging) {
ship.x = e.pageX - canvas.offsetLeft;
ship.y = e.pageY - canvas.offsetTop;
draw()
}
}
function myDown(e) {
ship = getClickedShip(e.pageX,e.pageY);
if (ship!=null) {
ship.x = e.pageX - canvas.offsetLeft;
ship.y = e.pageY - canvas.offsetTop;
ship.dragging = true;
canvas.onmousemove = myMove();
}
}
function myUp() {
ship.dragging = false;
canvas.onmousemove = null;
}
function getClickedShip(sx,sy){
for (var i = 0; i < ships.length; i++){
if(sx > (ships[i].x )+ canvas.offsetLeft && sx < (ships[i].x+ships[i].width+ canvas.offsetLeft) && sy > (ships[i].y + canvas.offsetTop) && sy < (ships[i].y+ships[i].height))
return ships[i];
}
}
init();
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
</script>
</section>
</body>
</html>
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:
MouseUp handler code:
MouseMove handler code:
This code illustrates using
context.isPointInPath
to hit-test an html canvas pathThe 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
Note about enhancing performance:
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/sEBAC/