14

I am building a HTML5 canvas image editor. After uploading an image in to the canvas i need to Dragg and resize it over the canvas. I managed to upload an image and make it draggable on the canvas. But i need to make it resizable also along the canvas. Thanks in advance.

var Img = new Image();
Img.src = file;
Img.onload = function () {
  context.drawImage(Img, 50, 0, 200, 200); 
}
mouseMove = function (event){
if (down) 
{
 context.clearRect(0,0,800,500);
 context.translate(0, -50); 
 context.drawImage(Img, (event.clientX - offsetX),
 (event.clientY - offsetY), 200, 200);
 context.translate(0, 50);
}
}
mouseUp = function () {
  down = false;
}
mouseDown = function () {
  down = true;
}
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove',mouseMove, false);

I tried with kinetics js but it is not suitable with canvas.

0

1 Answer 1

32

Here's example code to allow you to drag and resize an image using Canvas.

Resizing

enter image description hereenter image description here

How to resize an image with 4 draggable anchors

  • Draw a draggable anchor on each corner of an image.
  • If the user mousedown’s one if the anchors, start dragging that anchor.
  • In the mousemove handler, resize the image using the dragging anchor’s position(Note below).
  • As the last act in mousemove, redraw the resized image and 4 new anchors.
  • On mouseup, stop the anchor’s drag.

Note on the math used to resize the image:

  • The resized width is the difference between the mouseX position and the opposite corner’s X.
  • The resized height is the difference between the mouseY position and the opposite corner’s Y.

Dragging

enter image description hereenter image description here

How to drag an image

  • If the user mousedown’s inside the image, save the mouses starting XY to begin dragging.
  • In the mousemove handler, move the image by the current mouseXY minus the startingXY.
  • Also in mousemove, reset the startingXY to the current mouseXY in preparation for continued dragging.
  • On mouseup, stop the image’s drag.

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/LAS8L/

<!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; padding:10px;}
    #canvas{border:1px solid red;}
</style>
    
<script>
$(function(){

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

    var canvasOffset=$("#canvas").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 img=new Image();
    img.onload=function(){
        imageWidth=img.width;
        imageHeight=img.height;
        imageRight=imageX+imageWidth;
        imageBottom=imageY+imageHeight
        draw(true,false);
    }
    img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/facesSmall.png";


    function draw(withAnchors,withBorders){

        // clear the canvas
        ctx.clearRect(0,0,canvas.width,canvas.height);

        // draw the image
        ctx.drawImage(img,0,0,img.width,img.height,imageX,imageY,imageWidth,imageHeight);

        // 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);
          
      }
      
      
    }


    $("#canvas").mousedown(function(e){handleMouseDown(e);});
    $("#canvas").mousemove(function(e){handleMouseMove(e);});
    $("#canvas").mouseup(function(e){handleMouseUp(e);});
    $("#canvas").mouseout(function(e){handleMouseOut(e);});

       
}); // end $(function(){});
</script>

</head>

<body>
    <p>Resize the image using the 4 draggable corner anchors</p>
    <p>You can also drag the image</p>
    <canvas id="canvas" width=350 height=350></canvas>
</body>
</html>
Sign up to request clarification or add additional context in comments.

11 Comments

I tried with it but not able to make it working with drawing Image using 'context.DrawImage'. Can you help me bydrawing images rather than rectangles by editing simson sarris code.
Thank you very much for your help. You are always very helpful. May god bless you.
I am curios to know how to implement rotate event also on the image.
The context will rotate your image+resizers. But when hittesting in mouse handlers, you'll have to un-rotate the mouseXY (because that XY is given in unrotated space) So...Drawing with rotation: ctx.save(); ctx.rotate(radianAngle); // draw image and resizers normally ctx.restore(); But in your mouse events, you'll have to track the image and resizers by unrotating mouseXY for the rotation: unrotatedX=centerX+mouseXMath.cos(-radianAngle)-mouseYMath.sin(-radianAngle); unrotatedY=centerY-mouseXMath.sin(-radianAngle)-mouseYMath.cos(-radianAngle);
I tried my level best to implement rotate feature also in to the above code in yours fiddle using your suggestions. But i could not succeed. It might be because of my inexperience. Can you please help me by adding the the code of rotating also to the fiddle.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.