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 -
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 -**
I am not understanding how come eraser moves getting replaced with black colour while saving canvas as an image.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With