Drawing consistent freehand dotted line in HTML5 Canvas - javascript

I am trying to create a whiteboarding web app using HTML5 and Canvas.
I have implement a simple pen and paintbrush shaped pen with help from this brilliant article:
http://perfectionkills.com/exploring-canvas-drawing-techniques/
My issue is withe dotted line pen and highlighter pen.
The dotted line looks like a simple unbroken line if the mouse moves slowly, and with large gaps if moved quickly. What I want is a consistently spaced dotted line.
I tried setting the context.setLineDash but this has no effect on the result.
I then tried to calculate a minimum distance between the last point and current point and draw if over the dot gap lenth but this also does not seemeingly affect the result.
Here is my code:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var lastPoint;
var isDrawing = false;
context.lineWidth = 4;
context.lineJoin = context.lineCap = 'round';
canvas.onmousedown = function(e) {
isDrawing = true;
lastPoint = {
x: e.clientX,
y: e.clientY
};
lastPoint = {
x: e.offsetX,
y: e.offsetY
};
};
canvas.onmousemove = function(e) {
if (!isDrawing) return;
context.beginPath();
context.strokeStyle = 'red';
context.fillStyle = 'red';
mx = e.clientX; // mouse pointer and stroke path is off if use this
my = e.clientY;
mx = e.offsetX; // mouse pointer and stroke path match using this
my = e.offsetY;
context.setLineDash([5, 25]);
xlen = Math.abs(mx - lastPoint.x) + context.lineWidth;
ylen = Math.abs(my - lastPoint.y) + context.lineWidth;
gap = Math.sqrt((ylen * ylen) + (xlen * xlen));
if (gap >= 5) {
context.moveTo(lastPoint.x, lastPoint.y);
context.lineTo(mx, my);
context.stroke();
lastPoint = {
x: mx,
y: my
};
}
};
canvas.onmouseup = function() {
isDrawing = false;
};
html,body,canvas
{
width: 100%;
height: 100%;
margin: 0;
}
<canvas id="canvas" ></canvas>
The result is this:
With the highlighter, I get overlapping points which give dark spots on the path. The code for this is:
context.globalAlpha = 0.3;
context.moveTo(lastPoint.x, lastPoint.y);
context.lineTo(mx, my);
context.stroke();
lastPoint = { x: mx, y: my };
The result:

Related

I'm making a drawing based web-app and I'm using HTML Canvas to handle the drawing, however the drawing is offset to the right a lot?

const map = document.getElementById('map')
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
const grid = document.getElementById('grid')
function resize() {
canvas.width = map.offsetWidth
canvas.height = map.offsetHeight
ctx.width = map.offsetWidth
ctx.height = map.offsetHeight
}
resize();
grid.appendChild(canvas)
canvas.style.gridColumn = 2
canvas.style.gridRow = 1
let pos = { x: 0, y: 0 };
window.addEventListener('resize', resize);
document.addEventListener('mousemove', draw);
document.addEventListener('mousedown', setPosition);
document.addEventListener('mouseenter', setPosition);
function setPosition(e) {
pos.x = e.clientX;
pos.y = e.clientY;
}
function draw(e) {
if (e.buttons !== 1) return;
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();
}
Heres the code that generates the canvas relative to the size of a picture and allows the user to draw on the canvas. I've looked over another StackOverflow post with the same problem but no relevant answers. I know that the cause of the problem is that the canvas is stretched from it's standard proportion of 300 x 150 and is drawing at the correct position mathematically but not physically. How do I fix this?

Drawing Dynamic Gradients in HTML5 Canvas

I'm working on an art app and I want to be able to draw a gradient as a color. For example, if I keep drawing in a straight line or in circles, I want the gradient to repeat itself over and over. Right now the gradient is isolated to one side of the screen when I draw, but I would like to be able to draw with the gradient anywhere.
I have included the drawing function and color variable for reference.
HTML
<canvas id="canvas"></canvas>
JS
window.addEventListener('load', () => {
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
let painting = false;
var gradient = ctx.createLinearGradient(0, 0, 170, 0);
gradient.addColorStop("0", "magenta");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "red");
function windowSize() {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
}
function startPosition(e) {
painting = true;
draw(e);
}
function finishedPosition() {
painting = false;
ctx.beginPath();
}
function draw(e) {
if(!painting) return;
ctx.lineWidth = 10;
ctx.lineCap = "round";
ctx.strokeStyle = gradient;
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX, e.clientY);
}
canvas.addEventListener('mousedown', startPosition);
canvas.addEventListener('mouseup', finishedPosition);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('touchstart', startPosition);
canvas.addEventListener('touchend', finishedPosition);
canvas.addEventListener('touchmove', draw);
window.addEventListener('resize', windowSize);
});
As I understand, you are trying to make a repeating-linear-gradient pattern.
It's supported in css, but not yet in the canvas gradient.
If all what you want to archive is a drawing like in your example, I will suggest you to do th following:
add a css gradient as a background and cover all unused space in white.
cover all the space in white
set the ctx.globalCompositeOperation = 'destination-out'; (so it will clean the drawing instead of draw)
Like this:
window.addEventListener('load', () => {
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'destination-out';
let painting = false;
function windowSize() {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
}
function startPosition(e) {
painting = true;
draw(e);
}
function finishedPosition() {
painting = false;
ctx.beginPath();
}
function draw(e) {
if(!painting) return;
ctx.lineWidth = 10;
ctx.lineCap = "round";
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX, e.clientY);
}
canvas.addEventListener('mousedown', startPosition);
canvas.addEventListener('mouseup', finishedPosition);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('touchstart', startPosition);
canvas.addEventListener('touchend', finishedPosition);
canvas.addEventListener('touchmove', draw);
window.addEventListener('resize', windowSize);
});
canvas {
background: repeating-linear-gradient(to right, magenta, blue, red, magenta) repeat-x;
background-size: 50px 100%;
}
<canvas id="canvas"></canvas>
--- EDIT ---
Also, you can use different (single) color at each event, instead of use gradient, and change the hue over time.
It will produce very different result. not sure what you like more..
Will be looking like that:
window.addEventListener('load', () => {
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');
let colorIdx = 0;
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
let painting = false;
function getColor() {
colorIdx += 5;
return `hsl(${colorIdx}, 100%, 50%)`;
}
function windowSize() {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
}
function startPosition(e) {
painting = true;
draw(e);
}
function finishedPosition() {
painting = false;
ctx.beginPath();
}
function draw(e) {
if(!painting) return;
ctx.lineWidth = 10;
ctx.lineCap = "round";
ctx.strokeStyle = getColor();
ctx.lineTo(e.clientX, e.clientY);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX, e.clientY);
}
canvas.addEventListener('mousedown', startPosition);
canvas.addEventListener('mouseup', finishedPosition);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('touchstart', startPosition);
canvas.addEventListener('touchend', finishedPosition);
canvas.addEventListener('touchmove', draw);
window.addEventListener('resize', windowSize);
});
<canvas id="canvas"></canvas>
Repeated gradient on 2D canvas
There are several ways to repeat a gradient. However they are all somewhat involved and will have some limitations and problems.
2 methods
The simplest is to manually repeat the color stops (see example) but suffers from floating point error
Use a pattern to repeat a gradient. Render a single repeat gradient to an offscreen canvas and use that canvas as a pattern, setting the pattern repeat appropriately. You will also have to align the gradient to the offscreen canvas axis and then set the pattern transform to match the orientation of the desired pattern.
Repeating color stops
The following function creates a gradient and adds a function to it that will create repeated color stops.
function RepeatingGradient(ctx, x1, y1, x2, y2, repeats) {
const dx = x2 - x1, dy = y2 - y1;
const gradient = ctx.createLinearGradient(x1, y1, x1 + dx * repeats, y1 + dy * repeats);
return Object.assign(gradient, {
addRepeatColorStop(pos, color) {
var i = 0;
const step = 1 / repeats;
const offset = pos / repeats;
while (i < repeats) {
const p = (i++) * step + offset;
// Rounding error may cause exception so check that p is not greater than 1
gradient.addColorStop(p > 1 ? 1 : p, color)
}
}
});
}
Usage
RepeatingLinearGradient(ctx, x1, y1, x2, y2, repeats) It needs a 2D context ctx, then the standard linear gradient arguments, x1, y1, x2, y2 and then the number of repeats repeats.
The repeats extend the area of the gradient. Thus if the positioning arguments are 0,0,0,10 and the repeat is 10 then the gradient will cover the area 0,0,0,100
You add repeating color stops using the new function gradient.addRepeatColorStop(pos, color)
You use the resulting gradient as normal
const grad = RepeatingGradient(ctx, 0,0,0,10, 10);
grad.addRepeatColorStop(0, "#000");
grad.addRepeatColorStop(1, "#FFF");
ctx.strokeStyle = grad;
Example use
Use mouse to draw using repeated gradient.
function RepeatingGradient(ctx, x1, y1, x2, y2, repeats) {
const dx = x2 - x1;
const dy = y2 - y1;
const gradient = ctx.createLinearGradient(x1, y1, x1 + dx * repeats, y1 + dy * repeats);
return Object.assign(gradient, {
addRepeatColorStop(pos, color) {
var i = 0;
const step = 1 / repeats, offset = pos / repeats;
while (i < repeats) {
const p = (i++) * step + offset;
gradient.addColorStop(p > 1 ? 1 : p, color);
}
}
});
}
const lineWidth = 20;
const ctx = canvas.getContext('2d');
canvas.height = innerHeight;
canvas.width = innerWidth;
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";
const gradient = RepeatingGradient(ctx, 0, 0, 80, 80, 20);
gradient.addRepeatColorStop(0, "#F00");
gradient.addRepeatColorStop(0.25, "#FF0");
gradient.addRepeatColorStop(0.5, "#0F0");
gradient.addRepeatColorStop(0.75, "#FF0");
gradient.addRepeatColorStop(1, "#F00");
ctx.strokeStyle = gradient;
const mouse = {x : 0, y : 0, ox: 0, oy: 0, button : false, updateFunc: undefined}
mouse.updateFunc = function draw() {
if (mouse.button) {
ctx.beginPath();
ctx.lineTo(mouse.ox, mouse.oy);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
}
}
function mouseEvents(e){
const bounds = canvas.getBoundingClientRect();
mouse.ox = mouse.x;
mouse.oy = mouse.y;
mouse.x = e.pageX - bounds.left - scrollX;
mouse.y = e.pageY - bounds.top - scrollY;
mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
mouse.updateFunc && mouse.updateFunc();
}
["down","up","move"].forEach(name => document.addEventListener("mouse" + name, mouseEvents));
canvas { position : absolute; top : 0px; left : 0px; }
<canvas id="canvas"></canvas>
Click drag mouse to draw.
Notes
The repeat is not infinite. You need to ensure that you cover all of the area you want painted.
Repeats will reduce performance by a small amount depending on the number of repeats.
Gradients use FLOATS (32 bit floating point) not DOUBLES (64 bit floating point). Adding too many repeats and you will start to get some artifacts (not all repeats are identical, some stops may be out of order). Try to keep the number of repeats to the minimum needed to fit the render area. (FLOAT is the upper size, low end devices may only support lower than 32bit precision floating point)
If rounding errors start to effect the quality, try adding repeat stop ends slightly off 0 and 1
eg
gradient.addRepeatColorStop(0.01, "#F00"); // slightly above
gradient.addRepeatColorStop(0.99, "#F0F"); // slightly below
For the best results try to have the first and last position in the repeat match each other.
eg
gradient.addRepeatColorStop(0, "#F00"); // start
gradient.addRepeatColorStop(0.5, "#0F0"); // mid
gradient.addRepeatColorStop(1, "#F00"); // Match start
Using pattern to repeat gradients
The next method uses a pattern. Warning calling this function too often can result in a out of memory exception (gecko)
The function
function RepeatingLinearGradient(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const length = (dx * dx + dy * dy) ** 0.5 | 0;
const can = document.createElement("canvas"); // support for OffscreenCanvas() limited
can.width = length;
can.height = 1;
const ctxP = can.getContext("2d");
const nx = dx / length;
const ny = dy / length;
const matrix = new DOMMatrixReadOnly([nx, ny, -ny, nx ,x1, y1]);
const gradient = ctxP.createLinearGradient(0, 0, length, 0);
var dirty = true;
function update() {
ctxP.fillStyle = gradient;
ctxP.fillRect(0,0,length, 1);
var pattern;
Object.assign(pattern = ctxP.createPattern(can, "repeat"), {
addColorStop(pos, color) {
gradient.addColorStop(pos, color);
return update();
}
});
pattern.setTransform(matrix);
return pattern;
}
return update();
}
The function creates an off screen canvas and renders an axis align gradient to it. Each time you add a color stop a new pattern is created and returned.
To align the pattern with the desired gradient the patterns transform is set to match the gradients orientation.
Usage
Similar to a normal gradient but returns a pattern. Arguments are two coordinate pairs x1, y1, x2, y2
IMPORTANT As patterns are not live you must reassign the gradient every time you make a change (eg add color stop)
var gradient = RepeatingLinearGradient(0, 0, 80, 80);
/* MUST!!! reassign */
gradient = gradient.addColorStop(0, "#000"); // MUST!!! reassign
gradient = gradient.addColorStop(1, "#FFF"); // MUST!!! reassign
ctx.strokeStyle = gradient;
Example
Use mouse to draw
function RepeatingGradient(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const length = (dx * dx + dy * dy) ** 0.5 | 0;
const can = document.createElement("canvas");
can.width = length;
can.height = 1;
const ctxP = can.getContext("2d");
const nx = dx / length;
const ny = dy / length;
const matrix = new DOMMatrixReadOnly([nx, ny, -ny, nx ,x1, y1]);
const gradient = ctxP.createLinearGradient(0, 0, length, 0);
var dirty = true;
function update() {
ctxP.fillStyle = gradient;
ctxP.fillRect(0,0,length, 1);
var pattern;
Object.assign(pattern = ctxP.createPattern(can, "repeat"), {
addColorStop(pos, color) {
gradient.addColorStop(pos, color);
return update();
}
});
pattern.setTransform(matrix);
return pattern;
}
return update();
}
const lineWidth = 20;
const ctx = canvas.getContext('2d');
canvas.height = innerHeight;
canvas.width = innerWidth;
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";
var gradient = RepeatingGradient(0, 0, 40, 20);
gradient = gradient.addColorStop(0, "#F00");
gradient = gradient.addColorStop(0.25, "#FF0");
gradient = gradient.addColorStop(0.5, "#0F0");
gradient = gradient.addColorStop(0.75, "#FF0");
gradient = gradient.addColorStop(1, "#F00");
ctx.strokeStyle = gradient;
const mouse = {x : 0, y : 0, ox: 0, oy: 0, button : false, updateFunc: undefined}
mouse.updateFunc = function draw() {
if (mouse.button) {
ctx.beginPath();
ctx.lineTo(mouse.ox, mouse.oy);
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
}
}
function mouseEvents(e){
const bounds = canvas.getBoundingClientRect();
mouse.ox = mouse.x;
mouse.oy = mouse.y;
mouse.x = e.pageX - bounds.left - scrollX;
mouse.y = e.pageY - bounds.top - scrollY;
mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;
mouse.updateFunc && mouse.updateFunc();
}
["down","up","move"].forEach(name => document.addEventListener("mouse" + name, mouseEvents));
canvas { position : absolute; top : 0px; left : 0px; }
<canvas id="canvas"></canvas>
Click drag mouse to draw.
Notes
Does not suffer the same floating point issues as the first method.
Is slower when creating patterns and uses more memory.
Can throw memory error if creating too often or adding stops too often.
Repeats are infinite, You can not limit the number of repeats.
Uses DOMMatrixReadOnly this may not be supported by all browsers.

Dynamically drawing in canvas

I'm trying to create a simple, purely JS program for drawing in a canvas. I have an acceptable solution right now, but if I draw very quickly, my drawing pen isn't continuous and I get scattered circles, probably because the computer can't keep up with the pace.
var draw = false;
function yesDraw() {
draw = true;
}
function mouseCoordinates(e) {
if (draw) {
var x = e.offsetX;
var y = e.offsetY;
drawing(x, y);
}
}
function noDraw() {
draw = false;
}
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function drawing(x, y) {
ctx.beginPath();
ctx.arc(x, y, 10, 0, 2 * Math.PI);
ctx.fillStyle = "black";
ctx.fill();
}
<canvas id="myCanvas" height="400" ; width="1000" onmousedown="yesDraw()" onmousemove="mouseCoordinates(event)" onmouseup="noDraw()" onmouseout="noDraw()" style="border: solid 1px black;">Your browser does not support canvas.</canvas>
Is there any way to get a continuous flow of drawing and still keep it 100% JS?
Line segments from previous mouse position.
Rather than draw arcs draw line segments from the previous mouse position to the new one. As you don't want the line to be drawn from the end of the previous draw, you also need to indicate when a new line starts and set the previous mouse position to the current mouse.
To do this I added 3 variables lineStart, lastX,and lastY
lineStart is set to true when the mouse down event fires. In the draw function if line start is true then the lastX and lastY are set to the x,y and lineStart is set to false.
lastX, lastY hold the previous mouse position. They are set to x,y at the end of every draw call.
The line segments need to have the 2D context properties ctx.lineWidth set to the line width. To ensure the line is continuous the ctx.lineCap property is set to "round". This adds a semi circle to the start and end of the line.
Drawing past the edge
Having the pen turn off when the mouse moves out is annoying, you do this because if you don't you lose the mouse up events and the mouse keeps drawing with the mouse button up.
If you add the mouse to the document rather than the canvas, you don't have to worry about the mouse going outside the frame. You will still get the mouse up events even if the mouse is completely of the tab and browser.
Though you will have to use a slightly different way of getting the mouse coordinates, as you will want to still draw while off the canvas by at least half the draw line width. See code on how to get the mouse coordinates.
const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
const r = 10; // draw radius
ctx.lineWidth = r * 2;
ctx.lineCap = "round";
ctx.fillStyle = "black";
var draw = false;
var lineStart = true;
var lastX, lastY;
function yesDraw() { draw = true; lineStart = true }
function mouseMove(e) {
const bounds = c.getBoundingClientRect();
const x = e.pageX - bounds.left - scrollX;
const y = e.pageY - bounds.top - scrollY;
if(draw && x > -r && x < c.width + r && y > -r && y < c.height + r){
drawing(x,y);
}
}
function noDraw() { draw = false }
document.addEventListener("mousemove",mouseMove);
document.addEventListener("mousedown",yesDraw);
document.addEventListener("mouseup",noDraw);
function drawing(x, y) {
if(lineStart){
lastX = x;
lastY = y;
lineStart = false;
}
ctx.beginPath();
ctx.lineTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.stroke();
lastX = x;
lastY = y;
}
<canvas id="myCanvas" height="400" ; width="1000" style="border: solid 1px black;">Your browser does not support canvas.</canvas>
Use lineTo and end each line in an arc to make continuous smooth lines.
//Create Canvas
//(You can do this in HTML)
var c = document.body.appendChild(document.createElement("canvas"));
c.height = 400;
c.width = 1000;
var ctx = c.getContext("2d");
ctx.lineWidth = 20;
//Control drawing variable
var drawing = false;
c.onmousedown = c.onmouseout = c.onmouseup = function(evt) {
drawing = (evt.type === "mousedown");
};
//Keep track of last position
var oldX = null;
var oldY = null;
/**
* Draw the latest line
*
* #param {number} x
* #param {number} y
*/
function draw(x, y) {
if (drawing) {
if (oldX !== null) {
//If drawing, move to old coordinates for continual line
ctx.beginPath();
ctx.moveTo(oldX, oldY);
} else {
//Else simply move to current coordinates
ctx.moveTo(x, y);
ctx.beginPath();
}
//Draw a line
ctx.lineTo(x, y);
ctx.closePath();
ctx.stroke();
//Add an arc to the end of the line to make it smooth
ctx.beginPath();
ctx.arc(x, y, 0, 0, Math.PI * 2);
ctx.closePath();
ctx.stroke();
//Save new coordinates as old for next draw cycle
oldX = x;
oldY = y;
} else {
//If not drawing, cut line byt setting "old" to null
oldX = null;
oldY = null;
}
}
//Bind drawing
c.onmousemove = function(evt) {
draw(evt.offsetX, evt.offsetY);
};
canvas {
border: solid 1px black;
background-color: #eee;
}

Issue on Drawing Straight Line with Mouse Down and Move Event

Can you please take a look at following demo and let me know how I can enable the code to draw 100% straight Line on the canvas?
$(function() {
var drawLine = false;
var theCanvas = document.getElementById('map');
var ctx = theCanvas.getContext('2d');
theCanvas.width = 420;
theCanvas.height = 300;
var canvasOffset = $('#map').offset();
$('#map').mousemove(function(e) {
if (drawLine === true) {
ctx.lineTo(e.pageX - canvasOffset.left, e.pageY - canvasOffset.top);
ctx.stroke();
}
});
$('#map').mousedown(function() {
drawLine = true;
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(e.pageX - canvasOffset.left, e.pageY - canvasOffset.top);
});
$(window).mouseup(function() {
drawLine = false;
});
});
#map{border:solid; margin-top: 50px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<canvas id="map"></canvas>
As you can see the code is working fine but what I want is drawing a straight line on drawing
Thanks
You would need to have 2 canvases:
temporary for animation
permanent to store drawing.
Algorithm:
ondown write start coordinates.
onmove record endpoint, clear canvas 1, draw a line on canvas 1 from start point to end point.
onup draw final line on 2nd canvas clear 1st canvas.
Too lazy create second canvas (it'll clear it every try now);
Put a comment where pass different canvas for permanent draw
$(function() {
var drawLine = false;
var theCanvas = document.getElementById('map');
var finalPos = {x:0, y:0};
var startPos = {x:0, y:0};
var ctx = theCanvas.getContext('2d');
theCanvas.width = 420;
theCanvas.height = 300;
var canvasOffset = $('#map').offset();
function line(cnvs) {
cnvs.beginPath();
cnvs.moveTo(startPos.x, startPos.y);
cnvs.lineTo(finalPos.x, finalPos.y);
cnvs.stroke();
}
function clearCanvas()
{
ctx.clearRect(0, 0, theCanvas.width, theCanvas.height);
}
$('#map').mousemove(function(e) {
if (drawLine === true) {
finalPos = {x: e.pageX - canvasOffset.left, y:e.pageY - canvasOffset.top};
clearCanvas();
line(ctx);
}
});
$('#map').mousedown(function(e) {
drawLine = true;
ctx.strokeStyle = 'blue';
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.beginPath();
startPos = { x: e.pageX - canvasOffset.left, y: e.pageY - canvasOffset.top};
});
$(window).mouseup(function() {
clearCanvas();
// Replace with var that is second canvas
line(ctx);
finalPos = {x:0, y:0};
startPos = {x:0, y:0};
drawLine = false;
});
});
#map{border:solid; margin-top: 50px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<canvas id="map"></canvas>

myContext.clearRect(0, 0, 500, 700); Not Clearing Canvas Correctly

I have an HTML5 Canvas that can be drawn on with the mouse. I would like to be able to clear the canvas so the user can make a new drawing. I do this with:
myContext.clearRect(0, 0, 500, 700);
The canvas appears clear but as soon as the user begins a new drawing the old drawing reappears. My JavaScript for the mouse drawing part is:
// Variables
var x1;
var y1;
var isPressed = false;
var myCanvas;
var myContext;
function startCanvas() {
// Canvas stuff
myCanvas = document.getElementById("can1");
myContext = myCanvas.getContext("2d");
// Specify a black background, and white lines that are 3 pixels thick.
myContext.fillStyle = '#000000';
myContext.strokeStyle = '#000000';
myContext.fillRect(0, 0, 500, 700);
myContext.lineWidth = 3;
myContext.fill();
}
function functionMouseDown(e) {
// Get coordinates
x1 = e.clientX - myCanvas.offsetLeft;
y1 = e.clientY - myCanvas.offsetTop;
isPressed = true;
}
function functionMouseMove(e) {
// If mouse is down and moved start drawing line
if (isPressed == true) {
drawLine(e);
}
}
function functionMouseUp() {
// Stop drawing line
isPressed = false;
}
function drawLine(e) {
// Draw line
var x = e.clientX - myCanvas.offsetLeft;
var y = e.clientY - myCanvas.offsetTop;
myContext.strokeStyle = '#ffffff';
myContext.lineWidth = 1;
myContext.moveTo(x1, y1);
myContext.lineTo(x, y);
myContext.stroke();
// Set start coordinates to current coordinates
x1 = x;
y1 = y;
}
startCanvas();
The HTML is:
<canvas id="can1" width="500" height="700"></canvas>
myContext.strokeStyle = '#000000';
myContext.beginPath();//<---- add this and read about this.
myContext.fillRect(0, 0, 500, 700);
myContext.lineWidth = 3; //why?
myContext.fill();

Categories