Javascript: Canvas drawing - storing mouse coordinates I have a small JS application that allows a user, after clicking on a canvas, to draw a picture.

Once the user clicks the mouse, the user is allowed to drag the mouse wherever they want within the canvas and a line will be drawn from where they started moving the mouse to where the mouse stopped.

Only by clicking again will the drawing cease.

The code I have for this is below, and one concern of mine is how I'm storing the coordinates of the mouse's position each time it moves.

var draw = false;
var coords = [];
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
canvas.addEventListener('click', function (event) {
    coords = [];
    draw = !draw;
});
canvas.addEventListener('mousemove', function (event) {
    if (draw) {
        context = canvas.getContext("2d");
        var coord = { 'x': event.x - this.offsetLeft, 'y': event.y - thisoffsetTop };
        coords.push(coord);
        var max = coords.length - 1;
        if (typeof coords[max - 1] !== "undefined") {
            var curr = coords[max], prev = coords[max - 1];
            context.beginPath();
            context.moveTo(prev.x, prev.y);
            context.lineTo(curr.x, curr.y);
            context.stroke();
        }
    }
});


I have a feeling that I could be storing the coordinates more efficiently, rather than just add them to an ever-increasing Array. Is this the right approach, or is there a more efficient way of handling this sort of storage?
Firstly, I want to give you a thumbs up for a clear description of your code. It really helps with reading.

And another before-we-begin thing: you've got a missing . in your longest line of the code, near the end: -  thisoffsetTop };.



Main changes

Indeed, as you do not need to store all the coordinates, it's not efficient to save them all.
To draw a line between the current and previous point, all you need are those two points.
So, the first thing we can do with the code is to refactor that away: use prevCoord instead of an array.

Get rid of the array

First, we remove the coords declaration and replace it with a prevCoord.
Without adding initialization, it'll stay at undefined for the first round.
We're fine with that.

// old
var coords = [];

// new
var prevCoord;


Slightly different condition

We do not need to compute the max anymore -- the original code uses it to grab the "current" and "previous" coordinate, but we're moving away from that.
Also, the condition is now different.
We just need to ask if prevCoord is undefined.

// old
var max = coords.length - 1;
if (typeof coords[max - 1] !== "undefined") {

// new
if (typeof prevCoord !== "undefined") {


Simplify the contents of if

Let's see what happens inside.
Before we incorporate our change, let's notice that in your first line within if, you've got an expression coords[max].
That's actually the element you've just push'd, right?
So we can replace coords[max] with just coord (the current coordinate).

Then, we also not need the prev = coords[max - 1] part because we already have the previous coordinate stored in prevCoord.

In other words, that line's a goner because we have the refs we need at hand.

// old
var curr = coords[max], prev = coords[max - 1];

// new
// not needed: curr is coord and prev is prevCoord


Now, the drawing commands become the following:

// old
context.moveTo(prev.x, prev.y);
context.lineTo(curr.x, curr.y);

// new
context.moveTo(prevCoord.x, prevCoord.y);
context.lineTo(coord.x, coord.y);


Store the current as previous

Now, the main part.

The idea is not that far from what you have here.
Instead of pushing into array, you can just overwrite the prevCoord:

prevCoord = coord


Of course, you cannot do it as soon as you grab the coord from the event and offset stuff -- you need the prevCoord to draw the line.
So, just overwrite it after drawing.

// old
coords.push(coord);
if (typeof prevCoord !== "undefined") {
    // ...
}

// new
if (typeof prevCoord !== "undefined") {
    // ...
}
prevCoord = coord;


See -- just after using the prevCoord to draw a line between previous and current, we don't need the prevCoord anymore.
We can use this variable to prepare for the next cycle: on next mouse move, the "current" will become "previous"... meaning that when we run this function the next time, prevCoord will be just what it needs to be: the coordinate that was "mouse overed" the previous time.

Polish up

There's one more place let to change: the click handler.
Just as you reset your array, you should reset the prevCoord back to undefined.

// old
coords = [];

// new
prevCoord = undefined;


Full code

Here's the complete deal.



var draw = false;
var prevCoord;
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
canvas.addEventListener('click', function (event) {
    prevCoord = undefined
    draw = !draw;
});
canvas.addEventListener('mousemove', function (event) {
    if (draw) {
        context = canvas.getContext("2d");
        var coord = { 'x': event.x - this.offsetLeft, 'y': event.y - this.offsetTop };
        if (typeof prevCoord !== "undefined") {
            context.beginPath();
            context.moveTo(prevCoord.x, prevCoord.y);
            context.lineTo(coord.x, coord.y);
            context.stroke();
        }
        prevCoord = coord
    }
});
&lt;canvas id="canvas" style="border: 1px solid red"&gt;&lt;/canvas&gt;




More suggestions

A couple of things...

Redefining context

You have, on your fourth line, in the global scope a var context = ..., and then inside the if (draw) you have a context = .... 
There's no need to run that each time.
The context doesn't change.

// old
if (draw) {
    context = canvas.getContext("2d");

// new
if (draw)


Check for undefined

You don't need to use typeof x != 'undefined' here.
It's used when you're not sure if x has been declared.
A simple check would do.

// old
if (typeof prevCoord !== "undefined") {

// new
if (prevCoord !== undefined) {




That's all!