Technologies:
Tolerim
a month ago
How can I delete the drawings without removing the image templates in my drawing program?
ctx.globalCompositeOperation = "destination-over";
const canvas = document.getElementById("canvas1");
const ctx = canvas.getContext("2d");
let selectedImage = null;
let imageElements = document.querySelectorAll(".carousel img");
for (let i = 0; i < imageElements.length; i++) {
imageElements[i].addEventListener("click", function() {
selectedImage = imageElements[i];
drawSelectedImage();
});
}
function drawSelectedImage() {
if (selectedImage) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
let image = new Image();
image.onload = function () {
let x = (canvas.width - image.width) / 2;
let y = (canvas.height - image.height) / 2;
ctx.drawImage(image, x, y);
};
image.src = selectedImage.src;
}
}
const handleClick = (e) => {
if (e.target.tagName === "IMG") { // Image is clicked
const img = e.target;
const imgWidth = img.clientWidth;
const imgHeight = img.clientHeight;
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
const x = (canvasWidth - imgWidth) / 4.5;
const y = (canvasHeight - imgHeight) / 65;
const newImgWidth = imgWidth * 2.8;
const newImgHeight = imgHeight * 2.8;
const ctx = canvas.getContext("2d");
ctx.globalCompositeOperation = "destination-over";
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
let isDrawing = false;
function startDrawing(e) {
isDrawing = true;
if (selectedTool === "eraser") {
ctx.strokeStyle = "#123333";
}
}
function draw(e) {
if (!isDrawing) return;
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
lastX = e.offsetX;
lastY = e.offsetY;
}
function stopDrawing() {
ctx.closePath();
isDrawing = false;
if (e.type != "mousedown") {
paths_array.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
paths_index += 1;
}
}
}
};
ctx.globalCompositeOperation
to create an eraser tool that would only erase the brush and pencil drawings, but it either erased everything or caused unexpected behavior.Answers(2)
Vogi
a month ago
Verified Answer
You can use the globalCompositeOperation property to set how new shapes are drawn onto an existing image. The default value is source-over, which means that new shapes are drawn on top of the existing canvas content. By setting it to destination-out, you can erase parts of the canvas content. However, this will erase everything on the canvas, including the image you want to keep.
To erase only the brush and pencil drawings, you can create a new canvas element and draw the brush and pencil drawings on it. Then, you can use this new canvas element as a mask for the original canvas element. Here is an example code snippet that demonstrates this approach:
const brushCanvas = document.createElement('canvas');
brushCanvas.width = canvas.width;
brushCanvas.height = canvas.height;
const brushCtx = brushCanvas.getContext('2d');
// Draw brush strokes on brushCanvas
// ...
// Use brushCanvas as a mask for the original canvas
ctx.save();
ctx.globalCompositeOperation = 'destination-out';
ctx.drawImage(brushCanvas, 0, 0);
ctx.restore();
This code creates a new canvas element called brushCanvas and sets its dimensions to match the original canvas element. Then, it gets the 2D context of this new canvas element and draws the brush strokes on it. Finally, it saves the current state of the original canvas context using ctx.save(), sets the globalCompositeOperation property to destination-out, which will erase parts of the original canvas content that overlap with the brush strokes on brushCanvas, draws brushCanvas onto the original canvas using ctx.drawImage(), and restores the saved state of the original canvas context using ctx.restore().
I hope this helps! Let me know if you have any other questions.
Sources
How to Erase Pencil on Canvas | Top 10 Instructions (2023) - DIY QuicklyHow to remove pencil marks from canvas /How to erase on canvasWhat to Use for Sketching on Canvas - My Sketch JournalTolerim
a month ago
To make the eraser tool erase only the brush and pencil drawings, you can create a separate layer for the image and set the layer with the brush and pencil drawings to "destination-over". Then, when the eraser is used, you can set its globalCompositeOperation to "destination-out" so that it only affects the topmost layer (i.e. the brush and pencil drawings layer) and not the bottom layer with the image.
Here's an updated code snippet that implements this:
const canvas = document.getElementById("canvas1");
const ctx =canvas.getContext("2d");
let selectedImage = null;
// keep track of layers
const layers = [];
let currentLayer = null;
let imageElements = document.querySelectorAll(".carousel img");
for (let i = 0; i < imageElements.length; i++) {
imageElements[i].addEventListener("click", function() {
selectedImage = imageElements[i];
drawSelectedImage();
});
}
function drawSelectedImage() {
if (selectedImage) {
// clear all layers and create new bottom layer with image
layers.length = 0;
layers.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
ctx.clearRect(0, 0, canvas.width, canvas.height);
let image = new Image();
image.onload = function () {
let x = (canvas.width - image.width) / 2;
let y = (canvas.height - image.height) / 2;
ctx.drawImage(image, x, y);
// create new layer for brush/pencil drawings
currentLayer = ctx.getImageData(0, 0, canvas.width, canvas.height);
layers.push(currentLayer);
// set current layer to topmost layer
ctx.putImageData(currentLayer, 0, 0);
// set globalCompositeOperation to "destination-over" for brush/pencil drawings layer
ctx.globalCompositeOperation = "destination-over";
};
image.src = selectedImage.src;
}
}
let selectedTool = "pencil";
const handleClick = (e) => {
if (e.target.tagName === "IMG") {
const img = e.target;
const imgWidth = img.clientWidth;
const imgHeight = img.clientHeight;
const canvasWidth = canvas.width;
const canvasHeight = canvas.height;
const x = (canvasWidth - imgWidth) / 4.5; // Calculate the x-coordinate to center the image
const y = (canvasHeight - imgHeight) / 65; // Calculate the y-coordinate to center the image
const newImgWidth = imgWidth * 2.8; // Set the new image width to be half of the original size
const newImgHeight = imgHeight * 2.8; // Set the new image height to be half of the original size
// Get the canvas context
const ctx = canvas.getContext("2d");
// Draw the image on the canvas at the center
//ctx.drawImage(img, x, y, newImgWidth, newImgHeight);
// set selected tool
selectedTool = e.shiftKey ? "eraser" : "pencil";
// set stroke style depending on selected tool
if (selectedTool === "eraser") {
ctx.strokeStyle = "#123333";
// set globalCompositeOperation to "destination-out" for eraser
ctx.globalCompositeOperation = "destination-out";
} else {
ctx.strokeStyle = "#000000";
// set globalCompositeOperation to "source-over" for pencil
ctx.globalCompositeOperation = "source-over";
}
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
}
};
let isDrawing = false;
let lastX, lastY;
function startDrawing(e) {
isDrawing = true;
lastX = e.offsetX;
lastY = e.offsetY;
}
function draw(e) {
if (!isDrawing) return;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
lastX = e.offsetX;
lastY = e.offsetY;
}
function stopDrawing() {
isDrawing = false;
// save current layer to paths array
layers.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
// set current layer to topmost layer
currentLayer = layers[layers.length - 1];
ctx.putImageData(currentLayer, 0, 0);
}
canvas.addEventListener('click', handleClick);
As you can see, the code now keeps track of layers using an array. When a new image is selected, it clears all layers and creates a new bottom layer containing the image. When the eraser tool is selected, it sets the globalCompositeOperation to "destination-out" for the brush and pencil drawings layer so that it only erases those drawings. Finally, when a new stroke is drawn, it saves the current layer to the layers array and sets the current layer to the topmost layer.