I am making a website to allow users to resize and drag their different sketches to make a final sketch. I've seen this excellent example to enable both of these functionalities, but it works only for a single image, and I couldn't understand how to integrate it for multiple images. Most of the examples I could find were only for single images, I couldn't find any for doing this for multiple images. I tried to do the following:
var canvas = document.getElementById("paint");
var ctx = canvas.getContext("2d");
var canvasOffset=$("#paint").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var startX;
var startY;
var isDown=false;
var pi2=Math.PI*2;
var resizerRadius=8;
var rr=resizerRadius*resizerRadius;
var draggingResizer={x:0,y:0};
var imageX=50;
var imageY=50;
var imageWidth,imageHeight,imageRight,imageBottom;
var draggingImage=false;
var startX;
var startY;
var tx,ty,tw,th,img;
async function loadImages(data, targetX, targetY, targetWidth, targetHeight) {
data = data.replace(/'/g, '"');
targetX = targetX.replace(/'/g, '"');
targetY = targetY.replace(/'/g, '"');
targetWidth = targetWidth.replace(/'/g, '"');
targetHeight = targetHeight.replace(/'/g, '"');
data = JSON.parse(data);
targetX = JSON.parse(targetX);
targetY = JSON.parse(targetY);
targetWidth = JSON.parse(targetWidth);
targetHeight = JSON.parse(targetHeight);
for (var i = 0; i < data.length; i++) {
tx = parseInt(targetX[i]);
ty = parseInt(targetY[i]);
tw = parseInt(targetWidth[i]);
th = parseInt(targetHeight[i]);
img = await loadImage(data[i]);
imageWidth=img.width;
imageHeight=img.height;
imageRight=imageX+imageWidth;
imageBottom=imageY+imageHeight
draw(true,false);
}
}
function loadImage(src){
return new Promise(done=>{
img = new Image();
img.src = src;
img.onload = function() {
done(img);
};
});
}
function draw(withAnchors,withBorders){
// draw the image
ctx.drawImage(img,0,0,img.width,img.height,tx,ty,tw,th);
// optionally draw the draggable anchors
if(withAnchors){
drawDragAnchor(imageX,imageY);
drawDragAnchor(imageRight,imageY);
drawDragAnchor(imageRight,imageBottom);
drawDragAnchor(imageX,imageBottom);
}
// optionally draw the connecting anchor lines
if(withBorders){
ctx.beginPath();
ctx.moveTo(imageX,imageY);
ctx.lineTo(imageRight,imageY);
ctx.lineTo(imageRight,imageBottom);
ctx.lineTo(imageX,imageBottom);
ctx.closePath();
ctx.stroke();
}
}
function drawDragAnchor(x,y){
ctx.beginPath();
ctx.arc(x,y,resizerRadius,0,pi2,false);
ctx.closePath();
ctx.fill();
}
function anchorHitTest(x,y){
var dx,dy;
// top-left
dx=x-imageX;
dy=y-imageY;
if(dx*dx+dy*dy<=rr){ return(0); }
// top-right
dx=x-imageRight;
dy=y-imageY;
if(dx*dx+dy*dy<=rr){ return(1); }
// bottom-right
dx=x-imageRight;
dy=y-imageBottom;
if(dx*dx+dy*dy<=rr){ return(2); }
// bottom-left
dx=x-imageX;
dy=y-imageBottom;
if(dx*dx+dy*dy<=rr){ return(3); }
return(-1);
}
function hitImage(x,y){
return(x>imageX && x<imageX+imageWidth && y>imageY && y<imageY+imageHeight);
}
function handleMouseDown(e){
startX=parseInt(e.clientX-offsetX);
startY=parseInt(e.clientY-offsetY);
draggingResizer=anchorHitTest(startX,startY);
draggingImage= draggingResizer<0 && hitImage(startX,startY);
}
function handleMouseUp(e){
draggingResizer=-1;
draggingImage=false;
draw(true,false);
}
function handleMouseOut(e){
handleMouseUp(e);
}
function handleMouseMove(e){
if(draggingResizer>-1){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// resize the image
switch(draggingResizer){
case 0: //top-left
imageX=mouseX;
imageWidth=imageRight-mouseX;
imageY=mouseY;
imageHeight=imageBottom-mouseY;
break;
case 1: //top-right
imageY=mouseY;
imageWidth=mouseX-imageX;
imageHeight=imageBottom-mouseY;
break;
case 2: //bottom-right
imageWidth=mouseX-imageX;
imageHeight=mouseY-imageY;
break;
case 3: //bottom-left
imageX=mouseX;
imageWidth=imageRight-mouseX;
imageHeight=mouseY-imageY;
break;
}
// enforce minimum dimensions of 25x25
if(imageWidth<25){imageWidth=25;}
if(imageHeight<25){imageHeight=25;}
// set the image right and bottom
imageRight=imageX+imageWidth;
imageBottom=imageY+imageHeight;
// redraw the image with resizing anchors
draw(true,true);
}else if(draggingImage){
imageClick=false;
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// move the image by the amount of the latest drag
var dx=mouseX-startX;
var dy=mouseY-startY;
imageX+=dx;
imageY+=dy;
imageRight+=dx;
imageBottom+=dy;
// reset the startXY for next time
startX=mouseX;
startY=mouseY;
// redraw the image with border
draw(false,true);
}
}
$("#paint").mousedown(function(e){handleMouseDown(e);});
$("#paint").mousemove(function(e){handleMouseMove(e);});
$("#paint").mouseup(function(e){handleMouseUp(e);});
$("#paint").mouseout(function(e){handleMouseOut(e);});
This resulted in the following output:
As you can see, it has only 2 anchors (when there should be 8 for two images ideally) I figured this must be because of the img variable being used by the other functions and also being present in the for loop for loading the images, but I can't figure out how to resolve this and make anchors for all the images in the loop.