Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas- Eraser drawing black lines over canvas after canvas saved as image

Drawing on canvas is working perfectly fine. Even eraser also working perfectly fine. Issue is that while canvas saved as image it's drawing black lines instead of eraser.

For better understanding I added screens shots and code.

1. While erasing the draw -

a. Source code -

erase(){
      this.ctx.globalCompositeOperation = 'destination-out';
    } 

handleMove(ev){

  // let ctx = this.canvasElement.getContext('2d');
  let currentX = ev.touches[0].pageX - this.offsetX;
  let currentY = ev.touches[0].pageY - this.offsetY;

  this.ctx.beginPath();
  this.ctx.lineJoin = "round";
  this.ctx.moveTo(this.lastX, this.lastY);
  this.ctx.lineTo(currentX, currentY);
  this.ctx.closePath();
  this.ctx.strokeStyle = this.currentColour;
  this.ctx.lineWidth = this.brushSize;
  this.ctx.stroke();      


  this.undoList.push({
    x_start: currentX,
    y_start: currentY,
    x_end: this.lastX,
    y_end: this.lastY,
    color: this.currentColour,
    size: this.brushSize,
    mode: this.ctx.globalCompositeOperation
  });

  this.lastX = currentX;
  this.lastY = currentY;
  
}

b. Output -

enter image description here

2. Canvas saved as an Image -

a. Code -

this.ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
    setTimeout(() => {
      
      // this.drawImg(this.newImg);
       for(let i=0; i<this.textAreasList.length; i++){
         let txt = this.textAreasList[i];
         this.ctx.font = this.textAreasList[i].bold + ' ' + this.textAreasList[i].italic + ' ' + this.textAreasList[i].fontSize + ' ' + 'Comic Sans MS';
         this.ctx.fillStyle = this.textAreasList[i].color;  
         if(this.textAreasList[i].left=="" || this.textAreasList[i].left==undefined) {
           this.textAreasList[i].left = 50;
         }
         if(this.textAreasList[i].top=="" || this.textAreasList[i].top==undefined) {
          this.textAreasList[i].top = 50;
        }
         this.ctx.fillText(this.textAreasList[i].value, this.textAreasList[i].left, this.textAreasList[i].top);
       }

       this.redrawCanvas(this.undoUseList);
       let imgPath = this.canvasElement.toDataURL('image/png');
       let message= "";
       this.base64ToGallery.base64ToGallery(imgPath).then(
         res => message = "Image saved to gallery!",
         err => message = "Something went wrong!!"
       );
       this.spinner.hide();
       let toast = this.toastCtrl.create({
         message: message,
         duration: 3000,
         position: 'bottom',
         cssClass: 'changeToast'
       });
       this.navCtrl.push(HomePage);
     }, 5000);
  }



redrawCanvas(arr){
      // this.ctx.globalCompositeOperation = 'source-over';
      for(let i=0; i<arr.length; i++){
        for(let j=0; j< arr[i].length; j++){
          let ctx = this.canvasElement.getContext('2d');
          ctx.globalCompositeOperation = arr[i][j].mode;
          console.log('x start', arr[i][j].x_start);
          console.log('y start', arr[i][j].y_start);
          console.log('x end', arr[i][j].x_end);
          console.log('y end', arr[i][j].y_end);
          ctx.beginPath();
          ctx.lineJoin = "round";
          ctx.moveTo(arr[i][j].x_start, arr[i][j].y_start);
          ctx.lineTo(arr[i][j].x_end, arr[i][j].y_end);
          ctx.closePath();
          ctx.strokeStyle = arr[i][j].color;
          ctx.lineWidth = arr[i][j].size;
          ctx.stroke();
        }
        
      }
      
    }

**b. Output -** 

enter image description here

I am not understanding how come eraser moves getting replaced with black colour while saving canvas as an image.

like image 476
Flutterian Avatar asked Aug 24 '18 09:08

Flutterian


People also ask

Is there an eraser tool in canvas?

While there is no eraser tool available in Canva, there are a few workaround options that you can use to achieve a similar effect. The “clear” button located next to the pencil tool in the main menu can remove any lines or shapes drawn on the canvas but not any added text.

How do you erase a picture on canvas?

To clear the Canvas, you can use the clearRect() method. This method performs pretty well than others for clearing the canvas (such as resetting the width/height, destroying the canvas element and then recreating it, etc..) const context = canvas. getContext('2d'); context.

How do I reset my canvas?

From the course navigation menu, select Settings. In the "Settings" sidebar at the right, select Delete All Course Content. You will be prompted to confirm. To proceed, click Reset Course Content, or click Cancel to cancel.


1 Answers

So, you're redrawing your canvas using the undo list, right? And after that you output the image using toDataUrl()?

It seems to me that the issue lies on

this.undoList.push({
  x_start: currentX,
  y_start: currentY,
  x_end: this.lastX,
  y_end: this.lastY,
  color: this.currentColour, <== Is this an object?
  size: this.brushSize,
  mode: this.ctx.globalCompositeOperation
});

if this.currentColour is an object, I guess that the properties are changed somewhere else in the code and by the time you reconstruct the steps, you get the style black, not sure if it is the default one.

so you can try this instead

this.undoList.push({
  x_start: currentX,
  y_start: currentY,
  x_end: this.lastX,
  y_end: this.lastY,
  color: {
    prop1: this.currentColour.prop1
    prop2: this.currentColour.prop2
    ...
  }
  size: this.brushSize,
  mode: this.ctx.globalCompositeOperation
});

replacing prop1, prop2, etc by the actual properties you have in that object. In this way you are creating a new obj (copying it) instead of passing a ref to your old one.

You can make it fancier, but like this you can get the reasoning better.

like image 118
Victor Lia Fook Avatar answered Sep 29 '22 20:09

Victor Lia Fook