So far, it's mobile touch pencil tool, which can draw perfectly, but I'm wondering... how would I make it so that it draws a completely straight line instead of a basic pencil tool which can draw outside the line?
Here's the code so far:
// "Draw Line" Button
$(document).ready(function () {
initialize();
});
// works out the X, Y position of the click inside the canvas from the X, Y position on the page
function getPosition(mouseEvent, sigCanvas) {
var x, y;
if (mouseEvent.pageX != undefined && mouseEvent.pageY != undefined) {
x = mouseEvent.pageX;
y = mouseEvent.pageY;
} else {
x = mouseEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = mouseEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
return { X: x - sigCanvas.offsetLeft, Y: y - sigCanvas.offsetTop };
}
function initialize() {
// get references to the canvas element as well as the 2D drawing context
var sigCanvas = document.getElementById("canvasSignature");
var context = sigCanvas.getContext("2d");
context.strokeStyle = 'Black';
// This will be defined on a TOUCH device such as iPad or Android, etc.
var is_touch_device = 'ontouchstart' in document.documentElement;
if (is_touch_device) {
// create a drawer which tracks touch movements
var drawer = {
isDrawing: false,
touchstart: function (coors) {
context.beginPath();
context.moveTo(coors.x, coors.y);
this.isDrawing = true;
},
touchmove: function (coors) {
if (this.isDrawing) {
context.lineTo(coors.x, coors.y);
context.stroke();
}
},
touchend: function (coors) {
if (this.isDrawing) {
this.touchmove(coors);
this.isDrawing = false;
}
}
};
// create a function to pass touch events and coordinates to drawer
function draw(event) {
// get the touch coordinates. Using the first touch in case of multi-touch
var coors = {
x: event.targetTouches[0].pageX,
y: event.targetTouches[0].pageY
};
// Now we need to get the offset of the canvas location
var obj = sigCanvas;
if (obj.offsetParent) {
// Every time we find a new object, we add its offsetLeft and offsetTop to curleft and curtop.
do {
coors.x -= obj.offsetLeft;
coors.y -= obj.offsetTop;
}
// The while loop can be "while (obj = obj.offsetParent)" only, which does return null
// when null is passed back, but that creates a warning in some editors (i.e. VS2010).
while ((obj = obj.offsetParent) != null);
}
// pass the coordinates to the appropriate handler
drawer[event.type](coors);
}
// attach the touchstart, touchmove, touchend event listeners.
sigCanvas.addEventListener('touchstart', draw, false);
sigCanvas.addEventListener('touchmove', draw, false);
sigCanvas.addEventListener('touchend', draw, false);
// prevent elastic scrolling
sigCanvas.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false);
}
else {
// start drawing when the mousedown event fires, and attach handlers to
// draw a line to wherever the mouse moves to
$("#canvasSignature").mousedown(function (mouseEvent) {
var position = getPosition(mouseEvent, sigCanvas);
context.moveTo(position.X, position.Y);
context.beginPath();
// attach event handlers
$(this).mousemove(function (mouseEvent) {
drawLine(mouseEvent, sigCanvas, context);
}).mouseup(function (mouseEvent) {
finishDrawing(mouseEvent, sigCanvas, context);
}).mouseout(function (mouseEvent) {
finishDrawing(mouseEvent, sigCanvas, context);
});
});
}
}
// draws a line to the x and y coordinates of the mouse event inside
// the specified element using the specified context
function drawLine(mouseEvent, sigCanvas, context) {
var position = getPosition(mouseEvent, sigCanvas);
context.lineTo(position.X, position.Y);
context.stroke();
}
// draws a line from the last coordiantes in the path to the finishing
// coordinates and unbind any event handlers which need to be preceded
// by the mouse down event
function finishDrawing(mouseEvent, sigCanvas, context) {
// draw the line to the finishing coordinates
drawLine(mouseEvent, sigCanvas, context);
context.closePath();
// unbind any events which could draw
$(sigCanvas).unbind("mousemove")
.unbind("mouseup")
.unbind("mouseout");
}
Thanks,
Wardenclyffe
Anchor the pen down point at first touch and then wherever the next touch is draw a straight line from the first touch to the new touch. Have a floating check mark above the new touch to accept the new line. If the check mark isn't selected and there is another touch then remove the previous line, draw a new line, and show another check mark to save the new line. Provide an (x) above the original pen down point to cancel the line drawing tool.
The difference between a straight line tool and a pencil tool is that the pencil draws as many points as possible, and connects them with (possibly smoothed) line segments. A straight line tool connects a small number of lines with relatively large line segments.
One option would be for the pencil tool to lay down points as long as the finger touches the screen. And then the line tool draws from tap to tap. Alternately, if you tap and slide, the line tool could rubber-band the line from the touch point to the drag point, and then keep the last point before the touch lifts.
Related
I'm wanting to implement canvas as background for my website so users can use their cursors to paint on the webpage like this codepen: https://codepen.io/cocotx/pen/PoGRdxQ?editors=1010
(this is an example code from http://www.dgp.toronto.edu/~clwen/test/canvas-paint-tutorial/)
if(window.addEventListener) {
window.addEventListener('load', function () {
var canvas, context;
// Initialization sequence.
function init () {
// Find the canvas element.
canvas = document.getElementById('imageView');
if (!canvas) {
alert('Error: I cannot find the canvas element!');
return;
}
if (!canvas.getContext) {
alert('Error: no canvas.getContext!');
return;
}
// Get the 2D canvas context.
context = canvas.getContext('2d');
if (!context) {
alert('Error: failed to getContext!');
return;
}
// Attach the mousemove event handler.
canvas.addEventListener('mousemove', ev_mousemove, false);
}
// The mousemove event handler.
var started = false;
function ev_mousemove (ev) {
var x, y;
// Get the mouse position relative to the canvas element.
if (ev.layerX || ev.layerX == 0) { // Firefox
x = ev.layerX;
y = ev.layerY;
} else if (ev.offsetX || ev.offsetX == 0) { // Opera
x = ev.offsetX;
y = ev.offsetY;
}
// The event handler works like a drawing pencil which tracks the mouse
// movements. We start drawing a path made up of lines.
if (!started) {
context.beginPath();
context.moveTo(x, y);
started = true;
} else {
context.lineTo(x, y);
context.stroke();
}
}
init();
}, false); }
The problem is that the cursor stops painting when I scroll until I move my mouse again. Any idea on how to keep cursor painting even when I scroll?
Thanks in advance! Much appreciated!
You will have to store the last mouse event and fire a new fake one in the scroll event.
Luckily, the MouseEvent constructor accepts an mouseEventInit object on which we can set the clientX and clientY values of our new event, so we just need to store these values from the previous event and dispatch it in the scroll event.
Now, I couldn't help but rewrite almost everything from your code.
It had a lot of checks for old browsers (like very old ones which should never face the web again anyway), you may want to add it again if you wish.
It wasn't clearing the context, meaning that every time it drew a new line, it also did draw again the previous lines over themselves, leading in fatter lines, with a lot of noise at the beginning, and smoother lines at the end.
This could be fixed in many ways, the less intrusive one was to just clear the context at each frame.
To get the relative mouse position, it now uses the clientX and clientY properties of the event.
And the rest of the changes is commented in the snippet.
window.addEventListener('load', function () {
const canvas = document.getElementById('imageView');
context = canvas.getContext("2d");
let last_event; // we will store our mouseevents here
// we now listen to the mousemove event on the document,
// not only on the canvas
document.addEventListener('mousemove', ev_mousemove);
document.addEventListener('scroll', fireLastMouseEvent, { capture: true } );
// to get the initial position of the cursor
// even if the mouse never moves
// we listen to a single mouseenter event on the document's root element
// unfortunately this seems to not work in Chrome
document.documentElement.addEventListener( "mouseenter", ev_mousemove, { once: true } );
// called in scroll event
function fireLastMouseEvent() {
if( last_event ) {
// fire a new event on the document using the same clientX and clientY values
document.dispatchEvent( new MouseEvent( "mousemove", last_event ) );
}
}
// mousemove event handler.
function ev_mousemove (ev) {
const previous_evt = last_event || {};
const was_offscreen = previous_evt.offscreen;
// only for "true" mouse event
if( ev.isTrusted ) {
// store the clientX and clientY props in an object
const { clientX, clientY } = ev;
last_event = { clientX, clientY };
}
// get the relative x and y positions from the mouse event
const point = getRelativePointFromEvent( ev, canvas );
// check if we are out of the canvas viewPort
if( point.x < 0 || point.y < 0 || point.x > canvas.width || point.y > canvas.height ) {
// remember we were
last_event.offscreen = true;
// if we were already, don't draw
if( was_offscreen ) { return; }
}
// we come from out-of-screen to in-screen
else if( was_offscreen ) {
// move to the previous point recorded as out-of-screen
const previous_point = getRelativePointFromEvent( previous_evt, canvas );
context.moveTo( previous_point.x, previous_point.y );
}
// add the new point to the context's sub-path definition
context.lineTo( point.x, point.y );
// clear the previous drawings
context.clearRect( 0, 0, canvas.width, canvas.height );
// draw everything again
context.stroke();
}
function getRelativePointFromEvent( ev, elem ) {
// first find the bounding rect of the element
const bbox = elem.getBoundingClientRect();
// subtract the bounding rect from the client coords
const x = ev.clientX - bbox.left;
const y = ev.clientY - bbox.top;
return { x, y };
}
});
#container {
width: 400px;
height: 200px;
overflow: auto;
border: 1px solid;
}
#imageView { border: 1px solid #000; }
canvas {
margin: 100px;
}
<div id="container">
<canvas id="imageView" width="400" height="300"></canvas>
</div>
I'm having a problem with moving an object on the canvas but only on x or y-axis once at a time.
Idea:
The user can drag an object with CTRL / Shift pressed and then he's able to move an object on the x-axis or y-axis only. I move an object on an axis that I'm further away from starting position. This feature is present in most vector software (Corel, Inkscape, etc.).
On this video you can see what I mean:
https://www.youtube.com/watch?v=9AheCfh13Aw
To be honest - I don't know where to start. I guess I have to track the origin position of the object while dragging so I can check which axis should be locked while mouse movement.
Forked jsFiddle I'm using for developing:
https://jsfiddle.net/sores/1emj47q9/38/
Mouse movement event listener:
canvas.addEventListener('mousemove', function(e) {
if (myState.dragging) {
console.warn('mouseMove and dragging');
console.warn('object position: ', myState.selection);
var mouse = myState.getMouse(e);
console.warn('mouse: ', mouse);
// We don't want to drag the object by its top-left corner, we want to drag it
// from where we clicked. Thats why we saved the offset and use it here
// get the very first position of the object?
myState.selection.x = mouse.x - myState.dragoffx;
// y locked
// myState.selection.y = mouse.y - myState.dragoffy;
console.warn('new position: ', myState.selection);
myState.valid = false; // Something's dragging so we must redraw
}
}, true);
If anyone is familiar with such a thing I will be very grateful for any tips.
Thanks!
This answer is posted as code untested. The theory should point you in the right direction, though. I've commented the additions I've made to hopefully make it clearer but the basic rundown is;
Get the current mouse position
Move the mouse
Get the new mouse position
Compare the new mouse position against the old one
The biggest difference in positions determines the axis
When you've determined the direction (such as y), reset the position of the other axis (in this case, x) as it'll probably move slightly. I haven't included code for this.
// A reference to the previous mouse position
let initialMousePosition = {
x: 0,
y: 0
}
// A reference to locked axis that can be set or unset later
let dragLock: {
x: false,
y: false
}
// A reference to the control key
let ctrlPressed = false;
// Moved previousMousePosition logic in to on mouse down for increased reliability
canvas.addEventListener('mousedown', function(e){
var mouse = myState.getMouse(e);
initialMousePosition.x = mouse.x;
initialMousePosition.y = mouse.y;
})
canvas.addEventListener('mousemove', function(e) {
if (myState.dragging) {
var mouse = myState.getMouse(e);
// check for 0 positions to skip the first tick
if (initialMousePosition.x > 0 || initialMousePosition.y > 0) {
// compare previous mouse x & y positions to the current mouse positions
// assume the biggest difference is the direction of dragging
if (mouse.x - initialMousePosition.x > mouse.y - initialMousePosition.y) {
dragLock.y = true;
} else {
dragLock.x = true;
}
}
if (!dragLock.x || !ctrlPressed) myState.selection.x = mouse.x - myState.dragoffx;
if (!dragLock.y || !ctrlPressed) myState.selection.y = mouse.y - myState.dragoffy;
myState.valid = false; // Something's dragging so we must redraw
}
}, true);
//
canvas.addEventListener('keydown', function(e) {
if (event.which == "17")
ctrlPressed = true;
});
canvas.addEventListener('keyup', function(e) {
ctrlPressed = false;
})
I have a problem with my canvas drawing.
case1:
My PC can be used as touch screen as well as having a mouse. However, I can only draw using the touch screen. The mouse doesn't work.
case2:
My friend's PC only has a mouse and the canvas works fine.
Please help. I can see where the problem, but I'm not good enough to make changes.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Desktops and Tablets</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
initialize();
});
// works out the X, Y position of the click inside the canvas from the X, Y position on the page
function getPosition(mouseEvent, sigCanvas) {
var x, y;
if (mouseEvent.pageX != undefined && mouseEvent.pageY != undefined) {
x = mouseEvent.pageX;
y = mouseEvent.pageY;
} else {
x = mouseEvent.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = mouseEvent.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
return { X: x - sigCanvas.offsetLeft, Y: y - sigCanvas.offsetTop };
}
function initialize() {
// get references to the canvas element as well as the 2D drawing context
var sigCanvas = document.getElementById("canvas1");
var context = sigCanvas.getContext("2d");
context.strokeStyle = 'Black';
// This will be defined on a TOUCH device such as iPad or Android, etc.
var is_touch_device = 'ontouchstart' in document.documentElement;
if (is_touch_device) {
// create a drawer which tracks touch movements
var drawer = {
isDrawing: false,
touchstart: function (coors) {
context.beginPath();
context.moveTo(coors.x, coors.y);
this.isDrawing = true;
},
touchmove: function (coors) {
if (this.isDrawing) {
context.lineTo(coors.x, coors.y);
context.stroke();
}
},
touchend: function (coors) {
if (this.isDrawing) {
this.touchmove(coors);
this.isDrawing = false;
}
}
};
// create a function to pass touch events and coordinates to drawer
function draw(event) {
// get the touch coordinates. Using the first touch in case of multi-touch
var coors = {
x: event.targetTouches[0].pageX,
y: event.targetTouches[0].pageY
};
// Now we need to get the offset of the canvas location
var obj = sigCanvas;
if (obj.offsetParent) {
// Every time we find a new object, we add its offsetLeft and offsetTop to curleft and curtop.
do {
coors.x -= obj.offsetLeft;
coors.y -= obj.offsetTop;
}
// The while loop can be "while (obj = obj.offsetParent)" only, which does return null
// when null is passed back, but that creates a warning in some editors (i.e. VS2010).
while ((obj = obj.offsetParent) != null);
}
// pass the coordinates to the appropriate handler
drawer[event.type](coors);
}
// attach the touchstart, touchmove, touchend event listeners.
sigCanvas.addEventListener('touchstart', draw, false);
sigCanvas.addEventListener('touchmove', draw, false);
sigCanvas.addEventListener('touchend', draw, false);
// prevent elastic scrolling
sigCanvas.addEventListener('touchmove', function (event) {
event.preventDefault();
}, false);
}
else {
// start drawing when the mousedown event fires, and attach handlers to
// draw a line to wherever the mouse moves to
$("#canvas1").mousedown(function (mouseEvent) {
var position = getPosition(mouseEvent, sigCanvas);
context.moveTo(position.X, position.Y);
context.beginPath();
// attach event handlers
$(this).mousemove(function (mouseEvent) {
drawLine(mouseEvent, sigCanvas, context);
}).mouseup(function (mouseEvent) {
finishDrawing(mouseEvent, sigCanvas, context);
}).mouseout(function (mouseEvent) {
finishDrawing(mouseEvent, sigCanvas, context);
});
});
}
}
// draws a line to the x and y coordinates of the mouse event inside
// the specified element using the specified context
function drawLine(mouseEvent, sigCanvas, context) {
var position = getPosition(mouseEvent, sigCanvas);
context.lineTo(position.X, position.Y);
context.stroke();
}
// draws a line from the last coordiantes in the path to the finishing
// coordinates and unbind any event handlers which need to be preceded
// by the mouse down event
function finishDrawing(mouseEvent, sigCanvas, context) {
// draw the line to the finishing coordinates
drawLine(mouseEvent, sigCanvas, context);
context.closePath();
// unbind any events which could draw
$(sigCanvas).unbind("mousemove")
.unbind("mouseup")
.unbind("mouseout");
}
</script>
</head>
<body>
<h1>Canvas test</h1>
<div id="canvasDiv">
<!-- It's bad practice (to me) to put your CSS here. I'd recommend the use of a CSS file! -->
<canvas id="canvas1" width="500px" height="500px" style="border:2px solid #000000; margin-left: 400px;
margin-top: 100px; "></canvas>
</div>
</body>
</html>
The code below is causing your trouble -- it exclusively binds to only touch events or only mouse events.
if (is_touch_device) {
....
}
else {
....
}
Maybe you could use jQuery's vmouse? Or try binding to both touch and mouse events...
I have 2 canvases:-
<canvas id="myCanvas" width="915" height="650" style="border: 2px double #000000;"></canvas>
<canvas id="pharmacy" width="915" height ="320" style ="border:2px double #000000;"></canvas>
They are separate canvases, on the same aspx page.
The idea is to have them both represent a timeline. i.e they are both scrollable left to right and vice-versa.
I had created the first canvas a while ago, and recently decided to implement the 2nd canvas.
When I copy pasted the original code in the 2nd canvas to emulate the scrolling part, I figured out that in practice, when I scrolled , only the original canvas would scroll and the new canvas doesn't.
If I comment out the code for the original canvas then the new canvas scrolls.
Which led me to think, that the event based scrolling I was trying to achieve has some form of flaw in its naming convention. (since a mouse click is represented as an event and then dragging is allowed; my code was only registering dragging event of the original canvas and not the new canvas).
http://jsfiddle.net/przBL/3/
I would greatly appreciate if someone could take a look at the code and let me know where I am going wrong??
The goal:- is to click on either of the canvases, drag the mouse, and both canvases scroll at the same time.
1st canvas:-
// when mouse is clicked on canvas
window.onmousedown = function (e) {
var evt = e || event;
// dragging is set to true.
dragging = true;
lastX = evt.offsetX;
}
// when mouse is clicked again and the canvas is deselected
window.onmouseup = function () {
// dragging is set to false.
dragging = false;
}
// when mouse is dragging the canvas sideways
can.onmousemove = function (e) {
var evt = e || event;
if (dragging) {
var delta = evt.offsetX - lastX;
translated += delta;
//console.log(translated);
ctx.restore();
ctx.clearRect(0, 0, 930, 900);
ctx.save();
ctx.translate(translated, 0);
lastX = evt.offsetX;
timeline();
}
}
2nd canvas:-
// when mouse is clicked on canvas
window.onmousedown = function (e) {
var evt = e || event;
// dragging is set to true.
dragging = true;
lastX = evt.offsetX;
}
// when mouse is clicked again and the canvas is deselected
window.onmouseup = function () {
// dragging is set to false.
dragging = false;
}
// when mouse is dragging the canvas sideways
can1.onmousemove = function (e) {
var evt = e || event;
if (dragging) {
var delta = evt.offsetX - lastX;
translated += delta;
//console.log(translated);
ctx1.restore();
ctx1.clearRect(0, 0, 915, 600);
ctx1.save();
ctx1.translate(translated, 0);
lastX = evt.offsetX;
pharm_line();
}
}
now I want both can and can1 to move synchronously on any mousedown and mousemove event and stop when mouse is up.
You can use common mouse-handlers to identically scroll both canvas's.
See window.onmousemove below which keeps both canvas's in translated sync.
// when mouse is clicked on canvas
window.onmousedown = function (e) {
var evt = e || event;
// dragging is set to true.
dragging = true;
lastX = evt.offsetX;
}
// when mouse is clicked again and the canvas is deselected
window.onmouseup = function (e) {
// dragging is set to false.
dragging = false;
}
window.onmousemove = function(e) {
var evt = e || event;
if (dragging) {
var delta = evt.offsetX - lastX;
translated += delta;
move(ctx,930,900);
move(ctx1,915,600);
lastX = evt.offsetX;
timeline();
pharm_line();
}
}
// common code used to service either canvas
function move(context,width,height){
context.restore();
context.clearRect(0, 0, width, height);
context.save();
context.translate(translated, 0);
}
I have this html5 drawing app that draws just fine on the canvas element. My problem is, I have an img of an eraser and I want the user to be able to click it and it will erase the canvas. Extra karma points if you can tell me also how to change the stroke color to white.
This is my html:
<div id="draw_area">
<canvas id="myCanvas" />
<p>browser sucks, here's links blah blah blah</p>
</canvas>
</div>
This is the JS to complement it:
var points = new Array();
var outlineImage = new Image();
function clearCanvas(){
context.clearRect(0, 0, canvas.width, canvas.height);
}
if (window.addEventListener) {
window.addEventListener('load', function () {
var canvas, context, tool;
function init() {
// Find the canvas element.
canvas = document.getElementById('imageView');
if (!canvas) {
alert('Error: I cannot find the canvas element!');
return;
}
if (!canvas.getContext) {
alert('Error: no canvas.getContext!');
return;
}
// Size the canvas:
canvas.width = 367;
canvas.height= 249;
// Get the 2D canvas context.
context = canvas.getContext('2d');
if (!context) {
alert('Error: failed to getContext!');
return;
}
// Pencil tool instance.
tool = new tool_pencil();
// Attach the mousedown, mousemove and mouseup event listeners.
canvas.addEventListener('mousedown', ev_canvas, false);
canvas.addEventListener('mousemove', ev_canvas, false);
canvas.addEventListener('mouseup', ev_canvas, false);
}
// This painting tool works like a drawing pencil which tracks the mouse
// movements.
function tool_pencil() {
var tool = this;
this.started = false;
// This is called when you start holding down the mouse button.
// This starts the pencil drawing.
this.mousedown = function (ev) {
context.beginPath();
context.moveTo(ev._x, ev._y);
tool.started = true;
};
// This function is called every time you move the mouse. Obviously, it only
// draws if the tool.started state is set to true (when you are holding down
// the mouse button).
this.mousemove = function (ev) {
if (tool.started) {
context.lineTo(ev._x, ev._y);
context.stroke();
}
};
// This is called when you release the mouse button.
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
}
};
}
// The general-purpose event handler. This function just determines the mouse
// position relative to the canvas element.
function ev_canvas(ev) {
if (navigator.appName == 'Microsoft Internet Explorer' || navigator.vendor == 'Google Inc.' || navigator.vendor == 'Apple Computer, Inc.') { // IE or Chrome
ev._x = ev.offsetX;
ev._y = ev.offsetY;
} else if (ev.layerX || ev.layerX == 0) { // Firefox
ev._x = ev.layerX - this.offsetLeft;
ev._y = ev.layerY - this.offsetTop;
} else if (ev.offsetX || ev.offsetX == 0) { // Opera
ev._x = ev.offsetX;
ev._y = ev.offsetY;
}
// Call the event handler of the tool.
var func = tool[ev.type];
if (func) {
func(ev);
}
points.push(ev);
}
init();
}, false);
}
I think I need a redraw function, but I don't really know what I'm talking about in regards to this issue. Any insight is much appreciated!
Assuming your background color is white, which is what clearRect will give you, then all you need to do is change the stroke color to white when the user selects the eraser. This can easily be done with
context.strokeStyle = 'white';
See http://www.w3.org/TR/2dcontext/#fill-and-stroke-styles for more information about changing colors.
If your eraser image is drawn on the canvas, then you will have to detect the clicking of it in your mousedown or mouseup event handlers. If it is outside the canvas, then just add a onclick function to set the strokeStyle when it is clicked. However, if you want the eraser to erase everything then do
function clearCanvas(){
context.clearRect(0, 0, context.canvas.width, context.canvas.height);
}
Your canvas variable was not available in the scope where clearCanvas is called. While there are other ways to fix this, simply do this:
function clearContext( ctx ){
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
and pass the context into your function when you call it.
However note that if you context is transformed in any way the above will not clear the entire visible region. To safeguard against this, you may want:
function clearContext( ctx ){
ctx.save();
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
ctx.restore();
}