This canvas have been creating an error since I created it and I haven’t found a solution after all my research. so I need a hand. I need the canvas to create a straight line but it end up creating multiple straight lines from the starting point when the mouse is moving instead of one straight line.
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]> <html class="no-js"> <!--<![endif]-->
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="">
</head>
<style>
*{
box-sizing: border-box;
}
body,html{
padding: 0;
margin: 0;
height: 100vh;
width: 100vw;
}
</style>
<body>
<canvas>
</canvas>
<script>
var colorLine = 'black'
var fillLine = 'none'
var prevX = ''
var prevY = ''
var isDrawing = false
var snapshot;
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
let backgroundSetUp = () => {
canvas.height = window.innerHeight - 50;
canvas.width = window.innerWidth - 50;
ctx.fillStyle = colorLine;
ctx.fillStyle = fillLine
};
let startDrawing = e => {
isDrawing = true
prevX = e.offsetX
prevY = e.offsetY
ctx.beginPath();
ctx.strokeStyle = 'black'
ctx.fillStyle = '#fff'
}
let Drawing = e => {
if(isDrawing === false)
return
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke()
}
let stopDrawing = e => {
isDrawing = false
}
canvas.onmousedown = ( e => {
startDrawing(e)
})
canvas.onmousemove = ( e => {
Drawing(e)
})
canvas.onmouseup = ( e => {
stopDrawing(e)
})
backgroundSetUp()
</script>
</body>
</html>
2
Answers
You should clear your canvas drawing before you do another draw:
This will reset the canvas before you draw your ‘corrected’ line to the new mouse position. If you want to draw further lines you will need another canvas with a copy of the previous drawing, and draw it back into the output canvas instead of using
clear
.Here is one with a buffer instead, allowing you to continue drawing after the first line. I have also cleaned up some of your definitions (correctly using
const
andlet
, ignoringvar
and usingfunction
where it makes sense to create a little more concise and clear code):Store the position of existing line, so you can erase it
Disconcertingly, I needed to make the erasing-line a little thicker (3px) than the drawing line (1px) to get full erasure. Even 2px of erasing was not quite enough. I am open to explanations why this might be – it surprised me.
Alternatively, clear the canvas before drawing
If there was anything else on the canvas, you will lose it unless you store the information and re-draw it.
Why we need to erase with thicker lines and why XORing won’t work
I have found this StackOverflow answer explaining why the erasing line needs to be wider. It also explains why we can’t do a clever trick with XOR to allow us to draw and remove a line, without disturbing anything that was already on the canvas.
https://stackoverflow.com/a/16740592/7549483
In short, when we draw, the browser does anti-aliasing, which is a complex process that is not easily reversible. That requires the erasing line to be wider, and prevents XORing doing what we hope it would.