4



I want to draw rectangle on canvas. Below code is working fine except when i draw rectangle it does't show path when mouse is moving. When i left the mouse then rectangle is visible on canvas.

Please help,

Thanks

var canvas, ctx, flag = false,
        prevX = 0,
        currX = 0,
        prevY = 0,
        currY = 0,
        currShape = 'rectangle',
        mouseIsDown = 0,
        startX, endX, startY, endY,
        dot_flag = false;

    var x = "white",
        y = 2;
   
    function init() {
        canvas = document.getElementById('can');
        ctx = canvas.getContext("2d");
        var imageObj = new Image(); //Canvas image Obj

        imageObj.onload = function() {
            ctx.drawImage(imageObj, 69, 50);    //Load Image on canvas
        };
        imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'; //Load Image 

        w = canvas.width;   // Canvas Width
        h = canvas.height;  // Canvas Height
        //Check Shape to be draw
        eventListener();

    }
    function eventListener(){
        if(currShape=='rectangle'){
            canvas.addEventListener("mousedown",function (e) { 
                mouseDown(e);
            }, false);
            canvas.addEventListener("mousemove",function (e){
                mouseXY(e);
            }, false);
            canvas.addEventListener("mouseup", function (e){ 
                mouseUp(e);
            }, false);
        }
    }

function mouseUp(eve) {
    if (mouseIsDown !== 0) {
        mouseIsDown = 0;
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;
        if(currShape=='rectangle')
        {
            drawSquare(); //update on mouse-up
        }
    }
}

function mouseDown(eve) {
    mouseIsDown = 1;
    var pos = getMousePos(canvas, eve);
    startX = endX = pos.x;
    startY = endY = pos.y;
    if(currShape=='rectangle')
    {
        drawSquare(); //update on mouse-up
    }
}

function mouseXY(eve) {
    if (mouseIsDown !== 0) {
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;
        //drawSquare();
    }
}

function drawSquare() {
    // creating a square
    var w = endX - startX;
    var h = endY - startY;
    var offsetX = (w < 0) ? w : 0;
    var offsetY = (h < 0) ? h : 0;
    var width = Math.abs(w);
    var height = Math.abs(h);

               
    ctx.beginPath();
    ctx.globalAlpha=0.7;
    ctx.rect(startX + offsetX, startY + offsetY, width, height);
    ctx.fillStyle = x;
    ctx.fill();
    ctx.lineWidth = y;
    ctx.strokeStyle = x;
    ctx.stroke();
}

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    };
}
.colortool div {
        width: 15px;
        height: 15px;
        float: left;
        margin-left: 2px;
    }
    .clear {
      clear: both;
    }
<!DOCTYPE HTML>
<html>
    <body onload="init()">
     <div class="canvasbody">
     <canvas id="can" width="400" height="400" style="border:1px dotted #eee;"></canvas>
     </div>
    </body>
    </html>
Ajay Thakur
  • 1,066
  • 7
  • 23

4 Answers4

0

In some way, you would need to keep track on the changes you make to a shape you draw on the canvas. In your case, you would start by creating a very small rectangle and then scale it according to your mouse position during your dragmove.

Currently, you only have a function which draws an entirely new rectangle but does not take any previous "state" into consideration.

I found this blogpost which could be helpful. It doesn't explain scaling in particular but it could help with the basic concepts behind so I think this would be a good way for you to find a suitable solution.

glutengo
  • 388
  • 3
  • 13
0

Since we are finding the canvas tag in the DOM using it’s id and then setting the drawing context of the canvas to 2D. Two things is importent here is store the information as we draw the recatangle and a bolean to check user is drawing the rectangleor not. You can reffer these links:Drawing a rectangle using click, mouse move, and click Draw on HTML5 Canvas using a mouse Check the js fiddle in the given link. Hope this will help you..

Community
  • 1
  • 1
rajiv
  • 64
  • 1
  • 6
0

Here is you new JavaScript

var canvas, cnvHid, cnvRender, ctx, flag = false,
        prevX = 0,
        currX = 0,
        prevY = 0,
        currY = 0,
        currShape = 'rectangle',
        mouseIsDown = 0,
        startX, endX, startY, endY,
        dot_flag = false;

    var x = "white",
        y = 2;

    function init() {
        canvas = document.getElementById('can');
        cnvHid = document.getElementById( "canHid" );
        cnvRender = document.getElementById( "canRend" );
        ctx = canvas.getContext("2d");
        var imageObj = new Image(); //Canvas image Obj

        imageObj.onload = function() {
            ctx.drawImage(imageObj, 69, 50);    //Load Image on canvas
            renderAllCanvas();
        };
        imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'; //Load Image 

        w = canvas.width;   // Canvas Width
        h = canvas.height;  // Canvas Height
        //Check Shape to be draw
        eventListener();
    }
    function eventListener(){
        if(currShape=='rectangle'){
            cnvRender.addEventListener("mousedown",function (e) { 
                mouseDown(e);
                renderAllCanvas();
            }, false);
            cnvRender.addEventListener("mousemove",function (e){
                mouseXY(e);
                renderAllCanvas();
            }, false);
            cnvRender.addEventListener("mouseup", function (e){ 
                mouseUp(e);
                renderAllCanvas();
            }, false);
        }
    }
    function mouseUp(eve) {
    if (mouseIsDown !== 0) {
        mouseIsDown = 0;
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;
        if(currShape=='rectangle')
        {
            drawSquare( canvas ); //update on mouse-up
            cnvHid.getContext( "2d" ).clearRect( 0, 0, cnvHid.width, cnvHid.height );
        }
    }
}

function mouseDown(eve) {
    mouseIsDown = 1;
    var pos = getMousePos(canvas, eve);
    startX = endX = pos.x;
    startY = endY = pos.y;
    if(currShape=='rectangle')
    {
        drawSquare( canvas ); //update on mouse-up
    }
}

function mouseXY(eve) {
    if (mouseIsDown !== 0) {
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;
        drawSquare( cnvHid, true );
    }
}

function drawSquare( cnv, clear ) {
    var ctx = cnv.getContext( "2d" );
    if( clear && clear === true ){
        ctx.clearRect( 0, 0, cnv.width, cnv.height );
    }
    // creating a square
    var w = endX - startX;
    var h = endY - startY;
    var offsetX = (w < 0) ? w : 0;
    var offsetY = (h < 0) ? h : 0;
    var width = Math.abs(w);
    var height = Math.abs(h);

    ctx.beginPath();
    ctx.globalAlpha=0.7;
    ctx.rect(startX + offsetX, startY + offsetY, width, height);
    ctx.fillStyle = x;
    ctx.fill();
    ctx.lineWidth = y;
    ctx.strokeStyle = x;
    ctx.stroke();
    ctx.closePath();
}

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    };
}

function renderAllCanvas(){
    var cnxRender = cnvRender.getContext( "2d" );
    cnxRender.drawImage(
        canvas
        ,0,0
        ,cnvRender.width,cnvRender.height
    );
    cnxRender.drawImage(
        cnvHid
        ,0,0
        ,cnvRender.width,cnvRender.height
    );
}

And here is you new HTML

<!DOCTYPE HTML>
<html>
    <body onload="init()">
        <div class="canvasbody">
        <canvas id="can" width="400" height="400" style="display: none;"></canvas>
        <canvas id="canHid" width="400" height="400" style="display: none;"></canvas>
        <canvas id="canRend" width="400" height="400" style="border:1px dotted #eee;"></canvas>
        </div>
    </body>
</html>
Zakawa
  • 132
  • 1
  • 5
  • 1
    Mouse events fire up to 200+ times a second. Screen updates 60 times a second. The vast majority of `drawSquare` calls will never be seen. This is a waste of device power, client's resources, and will cause shearing when dragging. For any type of browser based animation (including UI interaction) you should use `requestAnimationFrame` to minimise resource usage and unwanted animation artifacts. See http://stackoverflow.com/a/40126873/3877726 for example of how to animate UI interaction. – Blindman67 Oct 26 '16 at 12:45
0

Your current code has the redraw commented out on the mouse move, which would be required to update the canvas. However your code is also destroying the image the way the rectangle is being drawn. If you retain the image as shown below and redraw it on each frame before drawing the rectangle, it might have the desired effect.

var canvas, ctx, flag = false,
        prevX = 0,
        currX = 0,
        prevY = 0,
        currY = 0,
        currShape = 'rectangle',
        mouseIsDown = 0,
        startX, endX, startY, endY,
        dot_flag = false;
        var x = "white",
        y = 2, 
        image = null;

   
    function init() {
        canvas = document.getElementById('can');
        ctx = canvas.getContext("2d");
        var imageObj = new Image(); //Canvas image Obj

        imageObj.onload = function() {
            image = imageObj;
            ctx.drawImage(image, 69, 50);    //Load Image on canvas
        };
        imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg'; //Load Image 

        w = canvas.width;   // Canvas Width
        h = canvas.height;  // Canvas Height
        //Check Shape to be draw
        eventListener();

    }
    function eventListener(){
        if(currShape=='rectangle'){
            canvas.addEventListener("mousedown",function (e) { 
                mouseDown(e);
            }, false);
            canvas.addEventListener("mousemove",function (e){
                mouseXY(e);
            }, false);
            canvas.addEventListener("mouseup", function (e){ 
                mouseUp(e);
            }, false);
        }
    }

function mouseUp(eve) {
    if (mouseIsDown !== 0) {
        mouseIsDown = 0;
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;
        if(currShape=='rectangle')
        {
            drawSquare(); //update on mouse-up
        }
    }
}

function mouseDown(eve) {
    mouseIsDown = 1;
    var pos = getMousePos(canvas, eve);
    startX = endX = pos.x;
    startY = endY = pos.y;
    if(currShape=='rectangle')
    {
        drawSquare(); //update on mouse-up
    }
}

function mouseXY(eve) {
    if (mouseIsDown !== 0) {
        var pos = getMousePos(canvas, eve);
        endX = pos.x;
        endY = pos.y;
        drawSquare();
    }
}

function drawSquare() {

    // draw background image
    if(image) {
        ctx.drawImage(image, 69, 50);
    }

    // creating a square
    var w = endX - startX;
    var h = endY - startY;
    var offsetX = (w < 0) ? w : 0;
    var offsetY = (h < 0) ? h : 0;
    var width = Math.abs(w);
    var height = Math.abs(h);
              
    ctx.beginPath();
    ctx.globalAlpha=0.7;
    ctx.rect(startX + offsetX, startY + offsetY, width, height);
    ctx.fillStyle = x;
    ctx.fill();
    ctx.lineWidth = y;
    ctx.strokeStyle = x;
    ctx.stroke();
}

function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: evt.clientX - rect.left,
        y: evt.clientY - rect.top
    };
}
.colortool div {
        width: 15px;
        height: 15px;
        float: left;
        margin-left: 2px;
    }
    .clear {
      clear: both;
    }
<!DOCTYPE HTML>
<html>
    <body onload="init()">
     <div class="canvasbody">
     <canvas id="can" width="400" height="400" style="border:1px dotted #eee;"></canvas>
     </div>
    </body>
    </html>
Michael A. McCloskey
  • 2,391
  • 16
  • 19