Sketchpad in JavaScript from scratch

In this article we will be building a simple sketch pad application in JavaScript from scratch. It will have a brush and eraser with variable size. For simplicity, lets limit it to draw and erase. The finished application can be viewed here.

The requirements for this application are basic knowledge of html and JavaScript. 

The file structure of application looks like this:
  1. index.js : contains the html code
  2. script.js : contains the JavaScript of the application


First of all let us start with the html file. We will need one canvas for rendering, one textbox for changing the stroke of brush and one button for toggling between brush and eraser. The html code is shown below :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<html>

<head>
    <title> SketchPad </title>
</head>

<body>

    <!--Canvas to draw-->
    <canvas id="canvas" height="500px" width="500px" style="border-style:solid"></canvas>
    <br>

    <!--Textbox to change the size of stroke-->
    <input type="text" id="size" value="1" />

    <!--Button to switch eraser and pen-->
    <button id="toggle">Brush/eraser</button>


    <!--JavaScript file-->
    <script type="text/javascript" src="script.js"></script>
</body>

</html>


The canvas is given the height and width of ‘500px’ and border style ‘solid’ so we can view it clearly. It is given the id ‘canvas’ to reference it from script.js file. Another element is a textbox with id ‘size’ and its initially set to 1 i.e. the initial brush size is 1. The next one is  a button with id ‘toggle’. The <script> tag loads the ‘script.js’ file. It is inserted at last to make page load  faster. That’s all for HTML. Open it in your browser and you will see a white square and some controls.

Now let’s move on to scripting part. Initially we get reference to the canvas so that we can draw on it.
1
2
3
4
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.lineCap = 'round';
ctx.lineJoin = 'round';

In order to use canvas we get reference to the context of the canvas. The parameter ‘2d’ is passed, which specifies that we are working in 2D. To draw smooth and round lines linecap and linejoin property of ctx are set to round. Next, we declare some variables to hold mouse coordinates, tool type and mousedown flag.

1
2
3
4
5
6
var iX, //initial
    iY,//and
    fX,//final
    fY,//positions
    mousedown = false, // initially set mousedown to false
    tool = 'brush';

(iX,iY) and (fX,fY) hold initial and final mouse position. ‘mousedown’ and ‘tool’ specifies mouse status and current tool. If mouse is pressed mousedown is set to true, else false. The tool is initially set to ‘brush’.

Then we take care of  three mouse events on canvas : mousedown, mouseup, mousemove. When mouse is down/pressed, the coordinate of mouse at that instant is stored in iX, iY and mousedown is set to true. Similarly, when the pressed mouse is released/up mousedown is set to false.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
canvas.onmousedown = function (e) {
    // on mousedown set initial positions
    iX = e.pageX;
    iY = e.pageY;
    mousedown = true;
}

canvas.onmouseup = function (e) {
    // on mouse up set 'mousedown' to false
    mousedown = false;
}

The actual magic happens when the mouse is moved . Let’s explain it line by line.

Initial line checks whether the mouse is pressed or not. If pressed, the code inside the braces will execute. In our case let’s assume its pressed . Then it sets the final positions (fX, fY) to the latest mouse coordinates. The next if..else block checks whether current tool is brush or eraser. If its eraser it sets the brush color to white, else to black.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
canvas.onmousemove = function (e) {
    // draw if mouse is pressed
    if (mousedown) {

        //set fX & fY to final position of cursor
        fX = e.pageX;
        fY = e.pageY;

        // check if its brush or eraser
        if (tool === 'brush') ctx.strokeStyle = 'black';
        else ctx.strokeStyle = 'white';

        // draw line from (iX,iY) to (fX, fY)
        ctx.beginPath();
        ctx.moveTo(iX, iY);
        ctx.lineTo(fX, fY);
        ctx.stroke();
        ctx.closePath();

        //set initial positions to final positions
        iX = fX;
        iY = fY;
    }
}

The above code is the main logic of the application. The moveTo() function sets the initial position of line to (iX,iY) and lineTo() sets final position to (fX,fY). Ctx.draw() draws a line joining the two specific points. Each line is drawn irrespective of the previous one, so beginpath() and closepath() are called each time at the beginning and end. Once a line is drawn, we then set the (iX,iY) to (fX,fY) for drawing next line.

 The same process happens again and again each time the mouse is moved. What it basically does is that it joins initial and final position of a mouse once it is moved. Save the code and run it in browser, you can draw like pencil in the canvas.

Finally, we add some more features to our application so that we can increase the size of brush and erase what we draw.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
document.getElementById('size').onkeyup = function (e) {
    //set linewidth of ctx to the value of textbox
    ctx.lineWidth = parseInt(document.getElementById('size').value);
}

document.getElementById('toggle').onclick = function () {
    //toggle tool
    if (tool === 'brush') tool = 'eraser';
    else tool = 'brush';
}

That’s it. Now open the ‘index.html’ file in your browser and view your sketchpad in action.

What we made it just a simple application. You can add more features like:
  1. Color Picker
  2. Separate cursor icon for pencil and eraser
  3. Option to change background and pencil color
  4. Save canvas as image file etc.
If you get stuck, you can view the full source code here.
Have any queries ? Please do ask in the comments below. I will be happy to answer.

Happy Coding !!

1 comment: