Reputation: 73
I've modified a page where I can drag and drop images onto a canvas. It does everything I want except for one. I've tried multiple methods (including scripts, e.g. Kinetic and Raphael, which I still think may be the route to go) but have dead ended:
Once the image is dropped, I can't drag it on the canvas to a new position.
function drag(e)
{
//store the position of the mouse relativly to the image position
e.dataTransfer.setData("mouse_position_x",e.clientX - e.target.offsetLeft );
e.dataTransfer.setData("mouse_position_y",e.clientY - e.target.offsetTop );
e.dataTransfer.setData("image_id",e.target.id);
}
function drop(e)
{
e.preventDefault();
var image = document.getElementById( e.dataTransfer.getData("image_id") );
var mouse_position_x = e.dataTransfer.getData("mouse_position_x");
var mouse_position_y = e.dataTransfer.getData("mouse_position_y");
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// the image is drawn on the canvas at the position of the mouse when we lifted the mouse button
ctx.drawImage( image , e.clientX - canvas.offsetLeft - mouse_position_x , e.clientY - canvas.offsetTop - mouse_position_y );
}
function convertCanvasToImage() {
var canvas = document.getElementById('canvas');
var image_src = canvas.toDataURL("image/png");
window.open(image_src);
}
Here is a JSFiddle that I used as my initial start point - http://fiddle.jshell.net/gael/GF96n/4/ (drag the JSFiddle logo onto the canvas and then try to move it). I've since added CSS, tabs, content, etc. to my almost working page. The function I don't want to lose is the ability to drag the single image multiple times (clone) onto the canvas.
Any ideas/examples/pointers on how to create this functionality?
Upvotes: 3
Views: 6639
Reputation: 21830
You need to do a couple of changes to your code, instead of drawing the image immediately to the canvas, you need to keep track of all images dropped. imagesOnCanvas
will be filled with all images dropped.
var imagesOnCanvas = [];
function drop(e)
{
e.preventDefault();
var image = document.getElementById( e.dataTransfer.getData("image_id") );
var mouse_position_x = e.dataTransfer.getData("mouse_position_x");
var mouse_position_y = e.dataTransfer.getData("mouse_position_y");
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
imagesOnCanvas.push({
context: ctx,
image: image,
x:e.clientX - canvas.offsetLeft - mouse_position_x,
y:e.clientY - canvas.offsetTop - mouse_position_y,
width: image.offsetWidth,
height: image.offsetHeight
});
}
You also need an animation loop, which will go through all images in imagesOnCanvas
and draw them sequentially. requestAnimationFrame
is used to achieve this.
function renderScene() {
requestAnimationFrame(renderScene);
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,
canvas.width,
canvas.height
);
for(var x = 0,len = imagesOnCanvas.length; x < len; x++) {
var obj = imagesOnCanvas[x];
obj.context.drawImage(obj.image,obj.x,obj.y);
}
}
requestAnimationFrame(renderScene);
Next you will have to monitor mousedown
events on canvas, and if the event occurs on an image the startMove
action can be called
canvas.onmousedown = function(e) {
var downX = e.offsetX,downY = e.offsetY;
// scan images on canvas to determine if event hit an object
for(var x = 0,len = imagesOnCanvas.length; x < len; x++) {
var obj = imagesOnCanvas[x];
if(!isPointInRange(downX,downY,obj)) {
continue;
}
startMove(obj,downX,downY);
break;
}
}
The isPointInRange
function returns true if the mouse event occurred on an image object
function isPointInRange(x,y,obj) {
return !(x < obj.x ||
x > obj.x + obj.width ||
y < obj.y ||
y > obj.y + obj.height);
}
Once 'move mode' is active, the x/y coordinates of the object are changed to reflect the new mouse position
function startMove(obj,downX,downY) {
var canvas = document.getElementById('canvas');
var origX = obj.x, origY = obj.y;
canvas.onmousemove = function(e) {
var moveX = e.offsetX, moveY = e.offsetY;
var diffX = moveX-downX, diffY = moveY-downY;
obj.x = origX+diffX;
obj.y = origY+diffY;
}
canvas.onmouseup = function() {
// stop moving
canvas.onmousemove = function(){};
}
}
Working example here:
Upvotes: 6
Reputation: 489
I know it's been like 2 years, but I'll give it a try... In the answer provided by @lostsource, the dataTransfer object is not supported in Opera browser, and the jsfiddle is not working. I desperately need that answer, that's what I've been looking for, but it's not working!
Upvotes: 0