Lets create a Drawing APP with JS
Tags: javascript, webdev, tutorial, beginners
Published: 2021-11-10 05:47:47

In this article I will show you how you can create a Drawing/Pain APP using JavaScript and HTML5 canvas.
## Features:
1. Draw on Canvas
2. Multiple colors
3. Clear canvas
4. Save drawing as Image
![JavaScript Paint app demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xcidgte6sn0ipc59w1l6.gif)

First lets create a **index.html** file with  a canvas element.
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>JavaScript Drawing APP</title>
</head>
<body>
    <canvas id="canvas"></canvas>

    <script src="main.js"></script>
</body>
</html>
```
Now let's create the **style.css** with basic resets
```css
*{
    margin: 0;
    padding: 0;
}
```
And then finally we will create our **main.js** where we will target our canvas and set it's size to the size of our screen.
```js
const canvas = document.getElementById("canvas")
canvas.height = window.innerHeight
canvas.width = window.innerWidth

// ctx is the context of our canvas
// we use ctx to draw on the canvas
const ctx = canvas.getContext("2d")

// lets create a rectangle for testing purposes
ctx.fillStyle = "red"
ctx.fillRect(100, 100, 100, 100)
```
Now if we open it in our browser we should see a red rectangle.
![Basing shape on canvas](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vpz3j47hpwl1qv1e93mb.png)

Okay lets delete the rectangle and whenever the use moves his mouse we want to get the mouse position. We can use `mousemove` event for that.
```js
const canvas = document.getElementById("canvas")
canvas.height = window.innerHeight
canvas.width = window.innerWidth

const ctx = canvas.getContext("2d")

window.addEventListener("mousemove", (e) => {
    console.log("Mouse X: " + e.clientX)
    console.log("Mouse Y: " + e.clientY)
})
```
![Get mouse position in JS](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8gnd0492j9fhqn03keia.png)
Great!!! Now we also need to keep track of the previous mouse position and draw a line from the previous mouse position to current mouse position.
```js
const canvas = document.getElementById("canvas")
canvas.height = window.innerHeight
canvas.width = window.innerWidth

const ctx = canvas.getContext("2d")

// previous mouse positions
// They will be null initially
let prevX = null
let prevY = null

// How thick the lines should be
ctx.lineWidth = 5

window.addEventListener("mousemove", (e) => {
    // initially previous mouse positions are null
    // so we can't draw a line
    if(prevX == null || prevY == null){
        // Set the previous mouse positions to the current mouse positions
        prevX = e.clientX
        prevY = e.clientY
        return
    } 

    // Current mouse position
    let currentX = e.clientX
    let currentY = e.clientY

    // Drawing a line from the previous mouse position to the current mouse position
    ctx.beginPath()
    ctx.moveTo(prevX, prevY)
    ctx.lineTo(currentX, currentY)
    ctx.stroke()

    // Update previous mouse position
    prevX = currentX
    prevY = currentY
})
```
![Drawing line on mouse move javascript canvas](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zjj6632cv4rnlr3vomqo.png)
Now if you move your mouse you will see a line will be drawn. But we don't want the line to be drawn uncontrollably. So we will declare a variable `let draw = false`. And we will only draw in `draw` is `true`.
So we can listen to the `mousedown` and `mouseup` event. And set `draw` to `true` when user presses the mouse and `false` when releases the mouse.
```js
const canvas = document.getElementById("canvas")
canvas.height = window.innerHeight
canvas.width = window.innerWidth

const ctx = canvas.getContext("2d")

let prevX = null
let prevY = null

ctx.lineWidth = 5

let draw = false

// Set draw to true when mouse is pressed
window.addEventListener("mousedown", (e) => draw = true)
// Set draw to false when mouse is released
window.addEventListener("mouseup", (e) => draw = false)

window.addEventListener("mousemove", (e) => {
    // if draw is false then we won't draw
    if(prevX == null || prevY == null || !draw){
        prevX = e.clientX
        prevY = e.clientY
        return
    }

    let currentX = e.clientX
    let currentY = e.clientY

    ctx.beginPath()
    ctx.moveTo(prevX, prevY)
    ctx.lineTo(currentX, currentY)
    ctx.stroke()

    prevX = currentX
    prevY = currentY
})
```
![Basic JavaScript paint app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yu5ltj70ucr6tz0vslbm.png)

Awesome!!! Now lets add some button in our HTML for changing colors, clearing canvas and saving the drawing.
```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
    <canvas id="canvas"></canvas>
    <div class="nav">
        <!-- We will be accessing the data-clr in JavaScript -->
        <div class="clr" data-clr="#000"></div>
        <div class="clr" data-clr="#EF626C"></div>
        <div class="clr" data-clr="#fdec03"></div>
        <div class="clr" data-clr="#24d102"></div>
        <div class="clr" data-clr="#fff"></div>
        <button class="clear">clear</button>
        <button class="save">save</button>
    </div>
    
    <script src="main.js"></script>
</body>
</html>
```
And we also need to style them in our css.
```css
*{
    margin: 0;
    padding: 0;
}

.nav{
    width: 310px;
    height: 50px;
    position: fixed;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    justify-content: space-around;
    opacity: .3;
    transition: opacity .5s;
}
.nav:hover{
    opacity: 1;
}

.clr{
    height: 30px;
    width: 30px;
    background-color: blue;
    border-radius: 50%;
    border: 3px solid rgb(214, 214, 214);
    transition: transform .5s;
}
.clr:hover{
    transform: scale(1.2);
}
.clr:nth-child(1){
    background-color: #000;
}
.clr:nth-child(2){
    background-color: #EF626C;
}
.clr:nth-child(3){
    background-color: #fdec03;
}
.clr:nth-child(4){
    background-color: #24d102;
}
.clr:nth-child(5){
    background-color: #fff;
}

button{
    border: none;
    outline: none;
    padding: .6em 1em;
    border-radius: 3px;
    background-color: #03bb56;
    color: #fff;
}
.save{
    background-color: #0f65d4;
}
```
Okay the page should look something like this.
![Drawing app with buttons](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/to4pboijq7huv7yowevw.png)
Now whenever a div with a class of `clr` is clicked we add to set the color of our line to the `data-clr` property of that div.
```js
const canvas = document.getElementById("canvas")
canvas.height = window.innerHeight
canvas.width = window.innerWidth

const ctx = canvas.getContext("2d")

let prevX = null
let prevY = null

ctx.lineWidth = 5

let draw = false

// Selecting all the div that has a class of clr
let clrs = document.querySelectorAll(".clr")
// Converting NodeList to Array
clrs = Array.from(clrs)

clrs.forEach(clr => {
    clr.addEventListener("click", () => {
        ctx.strokeStyle = clr.dataset.clr
    })
})

window.addEventListener("mousedown", (e) => draw = true)
window.addEventListener("mouseup", (e) => draw = false)

window.addEventListener("mousemove", (e) => {
    if(prevX == null || prevY == null || !draw){
        prevX = e.clientX
        prevY = e.clientY
        return
    }

    let currentX = e.clientX
    let currentY = e.clientY

    ctx.beginPath()
    ctx.moveTo(prevX, prevY)
    ctx.lineTo(currentX, currentY)
    ctx.stroke()

    prevX = currentX
    prevY = currentY
})
```
![Multi color drawing app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4wlib6cmy9befqz5to6f.png)
Yayy!!! Now lets make the **clear** button work. So when we click on it it should clear our canvas.
```js
const canvas = document.getElementById("canvas")
canvas.height = window.innerHeight
canvas.width = window.innerWidth

const ctx = canvas.getContext("2d")

let prevX = null
let prevY = null

ctx.lineWidth = 5

let draw = false

let clrs = document.querySelectorAll(".clr")
clrs = Array.from(clrs)
clrs.forEach(clr => {
    clr.addEventListener("click", () => {
        ctx.strokeStyle = clr.dataset.clr
    })
})

let clearBtn = document.querySelector(".clear")
clearBtn.addEventListener("click", () => {
    // Clearning the entire canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height)
})


window.addEventListener("mousedown", (e) => draw = true)
window.addEventListener("mouseup", (e) => draw = false)

window.addEventListener("mousemove", (e) => {
    if(prevX == null || prevY == null || !draw){
        prevX = e.clientX
        prevY = e.clientY
        return
    }

    let currentX = e.clientX
    let currentY = e.clientY

    ctx.beginPath()
    ctx.moveTo(prevX, prevY)
    ctx.lineTo(currentX, currentY)
    ctx.stroke()

    prevX = currentX
    prevY = currentY
})
```
Almost there!!! Now all we have top do is save our drawing when the **save** button is clicked.
## So here is the final JavaScript codes
```js
const canvas = document.getElementById("canvas")
canvas.height = window.innerHeight
canvas.width = window.innerWidth

const ctx = canvas.getContext("2d")

let prevX = null
let prevY = null

ctx.lineWidth = 5

let draw = false

let clrs = document.querySelectorAll(".clr")
clrs = Array.from(clrs)
clrs.forEach(clr => {
    clr.addEventListener("click", () => {
        ctx.strokeStyle = clr.dataset.clr
    })
})

let clearBtn = document.querySelector(".clear")
clearBtn.addEventListener("click", () => {
    ctx.clearRect(0, 0, canvas.width, canvas.height)
})

// Saving drawing as image
let saveBtn = document.querySelector(".save")
saveBtn.addEventListener("click", () => {
    let data = canvas.toDataURL("imag/png")
    let a = document.createElement("a")
    a.href = data
    // what ever name you specify here
    // the image will be saved as that name
    a.download = "sketch.png"
    a.click()
})

window.addEventListener("mousedown", (e) => draw = true)
window.addEventListener("mouseup", (e) => draw = false)

window.addEventListener("mousemove", (e) => {
    if(prevX == null || prevY == null || !draw){
        prevX = e.clientX
        prevY = e.clientY
        return
    }

    let currentX = e.clientX
    let currentY = e.clientY

    ctx.beginPath()
    ctx.moveTo(prevX, prevY)
    ctx.lineTo(currentX, currentY)
    ctx.stroke()

    prevX = currentX
    prevY = currentY
})
```
![Paint app final demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ipuf2wup0rm3nnug888.png)
 
And there, We have done it. You can get the complete source code [here](https://github.com/0shuvo0/Angle-Brace-Tuts/tree/master/Drawing%20App).
Make sure you checkout my other articles and YouTube channel
{% link 0shuvo0/i-used-javascript-to-clean-the-ocean-31ep %}
## Was it helpful? Support me on Patreon
[![Patreon Logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vnw8g7vs5pok3jwgtgv.png)](https://www.patreon.com/0shuvo0)