I want to create a Canvas in which there will be two areas (Left and right), Left panel will contain some shapes which will be draggable(static as well) and on the right side I would be able to drop them, but I am facing following problem,

  1. I am not able to make the shapes which i draw on the left side, draggable, because there is no id associated with them.
  2. I do not know how to make some particular area droppable.

Here is code to visualize what I am trying to achieve-

<body>
<canvas id="myCanvas" width="800" height="600" style="border:1px solid #000000;">
</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.moveTo(250,0);
ctx.lineTo(250,600);
ctx.stroke();

ctx.fillStyle = "#FF0000";
ctx.fillRect(50,50,160,25);
ctx.fillStyle = "#0000FF";
ctx.font = "15px";
ctx.strokeText("Draggable Elements here",57,67);

ctx.fillStyle = "#FF0000";
ctx.fillRect(500,50,130,25);
ctx.font = "15px";
ctx.strokeText("Droppable area Here",510,67);    
</script>

</body>

Here is the JS fiddle for the same - http://jsfiddle.net/akki166786/4tfyy4o5/

so if anybody can shed some light on how can I achieve this, it will be a great help.

Thanks in Advance

3

There are 3 best solutions below

4
On BEST ANSWER

Drag and drop in specifik area

UPDATE: Copy of box remains at original position while it's being moved.

First you need to be able to detect your rectangles. You do this by making then into objects in your code:

function box(x,y,w,h,rgb) {
    this.x = x,
    this.y = y;
    this.xS = x; //saving x
    this.yS = y; //saving y
    this.w = w;
    this.h = h;
    this.rgb = rgb;

    //to determine if the box is being draged
    this.draging = false;
}

No you need to add an event listener to determine if someone is clicking, you also need to determine if the person clicked in one of your boxes.

c.addEventListener("mousedown",down);
c.addEventListener("mousemove",move);
c.addEventListener("mouseup",up);

So events have been made to detect when the mouse button is pressed down, released back up and if the mouse moves within the canvas. To these events we have functions, down(), move() and up(), ready to be executed.

All functions will be visible in the example below.

When we're happily draging our boxes and releasing our mouse button, we need to check if the box was dropped in the dropable area. We do this in the up()-function. If the drop was OK, the box can stay, otherwise we send it back to where it came from.

Working example

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

c.width = 600;
c.height = 300;

//My mouse coordinates
var x,y;
c.addEventListener("mousedown",down);
c.addEventListener("mousemove",move);
c.addEventListener("mouseup",up);

//I'll save my boxes in this array
var myBoxes = new Array();

//This function describes what a box is.
//Each created box gets its own values
function box(x,y,w,h,rgb) {
    this.x = x,
    this.y = y;
    this.xS = x; //saving x
    this.yS = y; //saving y
    this.w = w;
    this.h = h;
    this.rgb = rgb;
    
    //to determine if the box is being draged
    this.draging = false;
}

//Let's make some boxes!!
myBoxes[0] = new box(10,10,50,100,"green");
myBoxes[1] = new box(80,50,100,75,"blue");
myBoxes[2] = new box(40,150,20,70,"yellow");


//here we draw everything
function draw() {
    ctx.clearRect(0,0,c.width,c.height);
    //Dropable area
    ctx.fillStyle="red";
    ctx.fillRect(c.width/2,0,c.width,c.height);
    
    //Boxes!
    for (var i = 0; i<myBoxes.length; i++) {
        var b = myBoxes[i];

        //NEW CODE FOR UPDATE
        if (b.draging) { //box on the move
            //Also draw it on the original spot
            ctx.fillStyle="grey"; //I chose a different color to make it appear more as a shadow of the box that's being moved.
            ctx.fillRect(b.xS,b.yS,b.w,b.h);
            ctx.strokeRect(b.xS,b.yS,b.w,b.h);
        }
        //End of new code for update

        ctx.fillStyle=b.rgb;
        ctx.fillRect(b.x,b.y,b.w,b.h);
        ctx.strokeRect(b.x,b.y,b.w,b.h);
    }
    
    //Let's keep re-drawing this
    requestAnimationFrame(draw);
}


function down(event) {
    event = event || window.event;
    x = event.pageX - c.offsetLeft,
    y = event.pageY - c.offsetTop;
    
    for (var i = 0; i<myBoxes.length; i++) {
        var b = myBoxes[i];
        if (x>b.x && x<b.x+b.w && y>b.y && y<b.y+b.h) {
            b.draging = true;
        }
    }
}

function move(event) {
    event = event || window.event;
    x = event.pageX - c.offsetLeft,
    y = event.pageY - c.offsetTop;
    
    for (var i = 0; i<myBoxes.length; i++) {
        var b = myBoxes[i];
        if (b.draging) {
            b.x = x;
            b.y = y;
        }
    }
}
function up(event) {
    event = event || window.event;
    x = event.pageX - c.offsetLeft,
    y = event.pageY - c.offsetTop;
    
    for (var i = 0; i<myBoxes.length; i++) {
        var b = myBoxes[i];
        if (b.draging) {
            //Let's see if the rectangle is inside the dropable area
            if (b.x>c.width/2) {
                //Yes is it!
                b.x = x;
                b.y = y;
                b.draging = false;
            }
            else {
                //No it's not, sending it back to its ordiginal spot   
                b.x = b.xS;
                b.y = b.yS;
                b.draging = false;                
            }

        }
    }
}


draw();
canvas {
  border: 1px solid black;
  }
<canvas id="canvas"></canvas>

2
On

You're using just one canvas, maybe it would be better if you use two separate canvas, one for each element you want to handle on page. so you'll have one element ID for each one. plus. if your drawing is simple, consider using a div for it instead a canvas

0
On

Once drawn to the canvas, shapes(or lines, images, everything) are no longer accessible.

What you will need to do is store each shape in an object in your code. For example:

var rectangle = {
    width: 100,
    height: 100,
    x: 50,
    y: 50
}

Then when you drag rectangle, you will need to update it's x and y properties on mouseup (or while it's being dragged if you want a drag preview).