user5728791
user5728791

Reputation:

html 5 canvas, I can only draw a single rectangle, how do i draw multiple rectangles and have them remain on the canvas

Problem

I can draw a single rectangle but when i click to draw another one the first rectangle disappears. I know why this is happening but want i want to do is be able to draw multiple rectangles and each rectangle to stay on the canvas as i draw it. Do i have to use multiple contexts?

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

 var canvasx = $(canvas).offset().left;
 var canvasy = $(canvas).offset().top;
 var last_mousex = last_mousey = 0;
 var mousex = mousey = 0;
 var mousedown = false;


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


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


$(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); //clear canvas
      ctx.beginPath();
      var width = mousex-last_mousex;
      var height = mousey-last_mousey;
      ctx.rect(last_mousex,last_mousey,width,height);
      ctx.strokeStyle = 'black';
      ctx.lineWidth = 10;
      ctx.stroke();
}

Here is a link to the jsfiddle

https://jsfiddle.net/richardcwc/ukqhf54k/

Upvotes: 0

Views: 187

Answers (1)

Blindman67
Blindman67

Reputation: 54089

Store render objects

You will need to store each object as you draw them as an object then every time you clear the canvas you redraw all the stored objects.

This will work well when the number of objects is in the 100s, but if the count is to get very high you will need to use another approach.

Maintain a pixel store

The second approach is to create a second canvas. Each time you clear the main canvas draw the second canvas on top of it, drawing the new box over it when the mouse if down.

When the mouse changes to up, clear the second canvas and draw the first one onto it. This makes a copy of the current pixels that is used as a background as you continue adding boxes.

I have added a basic background to your code, in between the comments //==========

 var canvas = document.getElementById('canvas');
 var ctx = canvas.getContext('2d');
 var canvasx = $(canvas).offset().left;
 var canvasy = $(canvas).offset().top;
 var last_mousex = last_mousey = 0;
 var mousex = mousey = 0;
 var mousedown = false;

 //=================================================
 // Background canvas
 const background = document.createElement("canvas");
 background.width = canvas.width; 
 background.height = canvas.height; 
 const bgCtx = background.getContext("2d");
 //=================================================

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

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

  //==============================
  // capture new background
  bgCtx.clearRect(0,0,canvas.width, canvas.height);
  bgCtx.drawImage(canvas, 0, 0); 
  //==============================
});

$(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); //clear canvas
      
      //==============================
      // draw background
      ctx.drawImage(background, 0, 0); 
      //==============================

      ctx.beginPath();
      var width = mousex-last_mousex;
      var height = mousey-last_mousey;
      ctx.rect(last_mousex,last_mousey,width,height);
      ctx.strokeStyle = 'black';
      ctx.lineWidth = 10;
      ctx.stroke();
}

Upvotes: 2

Related Questions