LP13
LP13

Reputation: 34109

Drawing multiple rectangles on canvas without clearing the back image

I am trying to draw multiple rectangles on canvas. I am able to do it except its not clearing rectangles as the mouse moves. And when i try to clear rectangle using clearRect then the back image on canvas is also gets cleared. So I have commented out //ctx.clearRect(0, 0, canvas.width, canvas.height); in the code below

I have gone through several SO posts with similar questions but doesn't seems work

$(function(){
				var canvas = document.getElementById('myCanvas');
        if (canvas.getContext){
          var ctx = canvas.getContext('2d');
          ctx.fillText("Sample String", 20, 50);
        }
        
        var ctx = canvas.getContext('2d');
    //Variables
    var canvasx = $(canvas).offset().left;
    var canvasy = $(canvas).offset().top;
    var last_mousex = last_mousey = 0;
    var mousex = mousey = 0;
    var mousedown = false;

    //Mousedown
    $(canvas).on('mousedown', function (e) {
        last_mousex = parseInt(e.clientX - canvasx);
        last_mousey = parseInt(e.clientY - canvasy);
        mousedown = true;        

    });

    //Mouseup
    $(canvas).on('mouseup', function (e) {
        mousedown = false;        
    });

    //Mousemove
    $(canvas).on('mousemove', function (e) {
        mousex = parseInt(e.clientX - canvasx);
        mousey = parseInt(e.clientY - canvasy);
        if (mousedown) {            
            //ctx.clearRect(0, 0, canvas.width, canvas.height); 
            var width = mousex - last_mousex;
            var height = mousey - last_mousey;
            ctx.beginPath();            
            ctx.rect(last_mousex, last_mousey, width, height);
            ctx.strokeStyle = 'black';
            ctx.lineWidth = 1;
            ctx.stroke();
        }
        //Output
        $('#results').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
    });
        
})
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
 Use mouse to draw multiple rectangles with in the canvas
</h3>
<canvas id="myCanvas"></canvas>
<div id="results">

</div>

Upvotes: 1

Views: 2182

Answers (2)

ChickenSoups
ChickenSoups

Reputation: 975

I think you can come to another approach

By using mousedown event only then save all rectangle to an array variable

Then you can clear and redraw the whole canvas with the saved variable

var shapes = [];
canva.addEventListener('mousedown', mouseDownListener);

class Rectangle() { 
   public ctx, x, y, w, h;

   public Rectangle(ctx, x, y, w, h) {
      this.ctx = ctx;
      this.x = x;
      this.y = y;
      this.w = w;
      this.h = h;
   }
   public draw() {
      // draw using ctx here
   }
}

function mouseDownListener() { 
    // create rectable
    var rectangle = new Rectangle(ctx, x, y, width, height);
    // save rectangle to an array
    shapes.push(rectangle);
    // redraw canvas
    redraw();
}

function redraw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    // draw all rectangle
    shapes.forEach(function(shape) {
        // draw shape
        shape.draw();
    })
}

Upvotes: 0

Roy Yosef
Roy Yosef

Reputation: 238

your mistake was you cleared all the canvas:

ctx.clearRect(0, 0, canvas.width, canvas.height);

instead of clearing just the area you drew before:

ctx.clearRect(prev_x-1, prev_y-1, prev_w+2, prev_h+2);

I wrote the basic idea here, but you need to add some code to clear the area depends on the direction the mouse was, and moving to (try to move your mouse to each of the corners and see what happens).

$("#clear").click(function(){
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillText("Sample String", 20, 50);
});

$(function(){
				var canvas = document.getElementById('myCanvas');
        if (canvas.getContext){
          var ctx = canvas.getContext('2d');
          ctx.fillText("Sample String", 20, 50);
        }
        
        var ctx = canvas.getContext('2d');
    //Variables
    var canvasx = $(canvas).offset().left;
    var canvasy = $(canvas).offset().top;
    var last_mousex = last_mousey = w = h = 0;
    var prev_x = prev_y = prev_w = prev_h = 0;
    var mousex = mousey = 0;
    var mousedown = false;

    //Mousedown
    $(canvas).on('mousedown', function (e) {
        last_mousex = parseInt(e.clientX - canvasx);
        last_mousey = parseInt(e.clientY - canvasy);
        mousedown = true;        

    });

    //Mouseup
    $(canvas).on('mouseup', function (e) {
        w = h = 0;
        mousedown = false;        
    });

    //Mousemove
    $(canvas).on('mousemove', function (e) {
        mousex = parseInt(e.clientX - canvasx);
        mousey = parseInt(e.clientY - canvasy);
        if (mousedown) {   
            prev_x = last_mousex;
            prev_y = last_mousey;
            prev_w = w;
            prev_h = h;
            ctx.clearRect(prev_x-1, prev_y-1, prev_w+2, prev_h+2);

            w = mousex - last_mousex;
            h = mousey - last_mousey;
            ctx.beginPath();            
            ctx.rect(last_mousex, last_mousey, w, h);
            ctx.strokeStyle = 'black';
            ctx.lineWidth = 1;
            ctx.stroke();
        }
        //Output
        $('#results').html('current: ' + mousex + ', ' + mousey + '<br/>last: ' + last_mousex + ', ' + last_mousey + '<br/>mousedown: ' + mousedown);
    });
        
})
canvas { border: 1px solid black; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h3>
 Use mouse to draw multiple rectangles with in the canvas
</h3>
<button id="clear">clear</button>
<br />
<canvas id="myCanvas"></canvas>
<div id="results">
</div>

Upvotes: 2

Related Questions