Reputation: 107
I am making a drawing tool for my photo editor application. I managed to make the drawing tool. However, since I have multiple tools like filters and text, the canvas has to be cleared and redrawn. I had to do this when I added text earlier. That was pretty easy, because the text was always stored in a function. Therefore I could just call that function after clearing the canvas to redraw the things that was already there. However, that is not as easy with a drawn path, as the path is never saved in a variable or a function. I have noe idea how I can manage to do that.
I basically want the drawn paths to be stored in some way, so that I can call them whenever I want to. Then they should appear on the canvas in the exact same way. Because right now they disappear whenever I use another tool, since I have to clear the canvas.
I am using Vanilla JS.
Here are the necessary parts of the HTML and JavaScript code:
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('imageCanvas');
var ctx = canvas.getContext('2d');
var img;
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
img = new Image();
img.onload = function(){
var ratio = this.height / this.width;
canvas.height = canvas.width * ratio;
ctx.drawImage(img,0,0,canvas.width, canvas.height);
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
var pos = { x: 0, y: 0 };
document.addEventListener('mousemove', draw);
document.addEventListener('mousedown', setPosition);
document.addEventListener('mouseenter', setPosition);
function setPosition(e) {
var rect = canvas.getBoundingClientRect();
pos.x = e.clientX - rect.left
pos.y = e.clientY - rect.top
}
function draw(e) {
if (e.buttons !== 1) return;
console.log(pos.x)
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.strokeStyle = '#c0392b';
ctx.moveTo(pos.x, pos.y);
setPosition(e);
ctx.lineTo(pos.x, pos.y);
ctx.stroke();
}
<input type="file" id="imageLoader"/>
<div class="container" id="container">
<canvas id="imageCanvas"></canvas>
</div>
Upvotes: 1
Views: 1101
Reputation: 6366
One of the simplest solutions would be to keep a secondary canvas to keep your pixel manipulations on.
Something like this might work for you:
let canvas = document.getElementById("imageCanvas");
let canvasContext = canvas.getContext("2d");
let canvasShadow = canvas.cloneNode();
let canvasContextShadow = canvasShadow.getContext("2d");
function SaveCanvas() {
canvasContextShadow.clearRect(0, 0, canvasShadow.width, canvasShadow.height);
canvasContextShadow.drawImage(canvas, 0, 0);
}
function ResetCanvas() {
canvasContext.clearRect(0, 0, canvas.width, canvas.height);
canvasContext.drawImage(canvasShadow, 0, 0);
}
//Events
var pos = {
x: 0,
y: 0
};
document.addEventListener('mousemove', draw);
document.addEventListener('mousedown', setPosition);
document.addEventListener('mouseenter', setPosition);
document.getElementById("reset").addEventListener('click', ResetCanvas);
document.getElementById("save").addEventListener('click', SaveCanvas);
function setPosition(e) {
var rect = canvas.getBoundingClientRect();
pos.x = e.clientX - rect.left;
pos.y = e.clientY - rect.top;
}
function draw(e) {
if (e.buttons !== 1)
return;
canvasContext.beginPath();
canvasContext.lineWidth = 5;
canvasContext.lineCap = 'round';
canvasContext.strokeStyle = '#c0392b';
canvasContext.moveTo(pos.x, pos.y);
setPosition(e);
canvasContext.lineTo(pos.x, pos.y);
canvasContext.stroke();
}
canvas {
background: #eee
}
<canvas id="imageCanvas" width="100" height="100"></canvas>
<button id="reset">Reset</button>
<button id="save">Save</button>
Upvotes: 1