Build A Drawing App with Vuejs and Html5 Canvas

Build A Drawing App with Vuejs and Html5 Canvas


In this tutorial, we will be building a simple drawing app with Vuejs and Html5 Canvas.

Basically the HTML <canvas> element is used to draw graphics on a web page. Vuejs is a progressive Javascript framework for building user interfaces.

Here’s the demo of our app!

Prerequisites

  • Familiarity with HTML, CSS, and JavaScript (ES6+).
  • Vs code or any code editor installed on your development machine.
  • Basic knowledge of vuejs

Before we kick off

Learn Vue.js and modern, cutting-edge front-end technologies from core-team members and industry experts with our premium tutorials and video courses on VueSchool.io.

Click here to Browse all Courses on VueSchool.io

Building the file structure

Let’s start by creating a file structure for the application. We will basically need just 3 files:index.html ,main.css and app.js file(s).To create this files open up the terminal and type the following code:

cd desktop
mkdir drawing-app && cd drawing-app
touch index.html && touch app.js && main.css

After creating these files, lets setup our index.html file and bring in vue into the project. Let’s define a simple boilerplate and then link the CSS stylesheet and the javascript to the index.html file and also initialize vue by adding the vue development CDN. Open up the terminal and add the following code to your index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Drawing App</title>
    <link rel="stylesheet" href="main.css">
</head>
<body>
    <div id="app">
  <h1>{{ message }}</h1>
 <canvas id="canvas"></canvas>
</div>
   
    https://cdn.jsdelivr.net/npm/vue/dist/vue.js
    http://app.js
</body>
</html>

And then to set up vue, let’s also add the following to the app.js file. We start by storing the vue instance in a variable app then we define the root div.:

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

in our main.css file lets add borders to the canvas:

html body {
    padding: 0px;
    margin: 0px;
}
#canvas {
    border: 3px solid black;
    height: 100px;
    width: 100px
}

We can run our application by using live-server.If you don’t have live-server installed on you local machine, then install it by running npm i live-server -g .The -g flag will install the package globally in our local machine. After installing it, you can now move into your development project using the terminal by using the cd command followed by the location of your application. To run our application using live-server open up the terminal and run the following commands:

cd desktop
cd drawing-app && live-server --port=4040

This will open up our application on a live-server running on port 4040.
Let’s continue building our application.
Let’s continue by defining the canvas instance in the mounted life cycle hook in our app.js:


mounted() {
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");  
  this.vueCanvas = ctx;
}

And then add vueCanvas in our data property:

data: {
    message: 'Hello Vue!',
    vueCanvas:null
  },

Now we want to programmatically define the width and height of our canvas. So to do that we will leverage on window.innerHeight and window.innerWidth .Let’s add the codes in the mounted life cycle hook:

canvas.height = window.innerHeight;
canvas.width = window.innerWidth;

Drawing basic shapes

Drawing a Simple Square

Let see how to draw simple shapes using canvas.Let’s start by drawing a simple square shape. There are a lot of properties that we could use with the ctx instance that we defined earlier. To draw a simple square shape we will use the fillRect property which takes in four parameters. The first parameter will be the X position, the second parameter is the Y position,the third parameter will be the width of the shape and the forth parameter will be the height of the shape. For e.g ctx.fillRect(x,y,width,height);

ctx.fillRect(100,100,300,300)

This means that the shape will take the position of 100 at the X axis, 100 at y axis and will take 300 for the height and then 300 for the width of the shape. By default, the shape will come with a black background. To have a transparent background you could use the strokeRect property. You could change the color by setting strokeStyle to any color of your choice.

Note that the strokeStyle should always be above the shape you are trying to style. Meaning that it should always take this format:

ctx.strokeStyle = "red"
ctx.strokeRect(100,100,300,300)

And not this: 

ctx.strokeRect(100,100,300,300)
ctx.strokeStyle = "red" 

Drawing A Simple Triangle

To draw a simple triangle, we will use the beginPath property. The ctx.beginPath property is called before beginning each line. Then the next thing is to use the ctx.moveTo property. The moveTo property begins a new sub-path at the point specified. This actually means that we have to specify the x and y parameter. So picture this as picking up your pen and placing it on a notebook without writing:

ctx.moveTo(x, y);

Now to actually draw a line we will use the lineTo property which adds a straight line to the current sub-path by connecting the sub-paths last point to the specified (x, y) coordinates which is passed as a parameter.

ctx.lineTo(200,100)

This method does not directly render anything until you use the stroke property.

ctx.stroke()

With this, we just drew a straight line. To add a vertical line at the end of the line we just drew we will add :

ctx.lineTo(200,150)

Now to join the lines together will use the closePath property.

The code for drawing a triangle will look like this:

ctx.beginPath();
ctx.moveTo(100,100)
ctx.lineTo(200,100)
ctx.lineTo(200,150)
ctx.closePath()
ctx.stroke()

Implementing the Drawing App

Let’s start writing functions for the drawing app. The first thing we will do it to define a variable painting and then set it to false. This is to take note of if we are drawing or not. We will define that in the data property:

painting:false

After doing this let’s define some functions in the methods object that will mutate the value of painting:

methods: {
    startPainting() {
      this.painting = true;
      console.log(this.painting)
    },
    finishedPainting() {
      this.painting = false;
      console.log(this.painting)
    }
  },

Now we want a situation when the mouse is down we set the value of painting to true and when the mouse is up we then set the value of painting to false. So we add event listeners to the canvas tag in the index.html file:

<canvas @mousedown="startPainting" @mouseup="finishedPainting"  id="canvas"></canvas>

Ensure you test that this is working by opening up the console and then press the button on your mouse, doing this will output true on the console and when you leave the button it will output false on the console.


Now, will add an event listener on the canvas to listen to when the mouse is moving. Let’s define another method called paint. This is where we will implement the actual painting.

<canvas @mousedown="startPainting" @mouseup="finishedPainting" @mousemove="draw"  id="canvas"></canvas>

and define the paint method in the methods object:

draw(e) {
      console.log("Hello...Event is Working")
  }

Now move your mouse around on the canvas and then you will notice that Hello…The event is Working is logged on the console…this means that the event listener is working.


Let’s start by writing a condition that if we aren’t holding down the mouse the function shouldn’t be called:

draw(e) {
      if(!this.painting) return
      console.log("Hello...Event is Working")
    }

This is to ensure that the user is actually holding down the mouse.


Now let’s make the canvas and ctx variable global so that we can access it from anywhere. Let’s define canvas and ctx in the data object and set it to null.

canvas:null,
ctx:null

Now instead of using var canvas and  var ctx in the mounted life cycle hook we will be using this.canvas and this.ctx .


this.canvas = document.getElementById("canvas");
this.ctx = canvas.getContext("2d");  
  // Resize canvas
this.canvas.height = window.innerHeight;
this.canvas.width = window.innerWidth;

After doing this, lets set up some styles to our pen.By adding some lineWidth,lineCap:

draw(e) {
      if(!this.painting) return
      this.ctx.lineWidth = 10;
      this.ctx.lineCap ="round" 
    }

Now we will use the lineTo method to start drawing the line. Recall the lineTo property adds a straight line to the current sub-path by connecting the sub-paths last point to the specified (x, y) coordinates.We can use the e.clientX for the X-axis and e.clientY for the Y-axis. And also recall that this won’t work until we add the stroke property.

So now our draw method will now be:


draw(e) {
      if(!this.painting) return
      this.ctx.lineWidth = 10;
      this.ctx.lineCap ="round"
      
     this.ctx.lineTo(e.clientX,e.clientY)
     this.ctx.stroke()
      //  console.log(e.clientX); // x coordinate
      //   console.log(e. clientY); // y coordinate
  }

Yea….we just built our paint app…But there is still an issue…

After drawing and our mouse is lifted, and then we want to continue drawing, it continues from where we stopped…which isn’t supposed to be so.
so we need to add some more codes the draw function:


draw(e) {
      if(!this.painting) return
      this.ctx.lineWidth = 10;
      this.ctx.lineCap ="round"
      
     this.ctx.lineTo(e.clientX,e.clientY)
     this.ctx.stroke()

      this.ctx.beginPath()
     this.ctx.moveTo(e.clientX,e.clientY)
     
    }

And then we will also modify the finishedPainting method to:


 finishedPainting() {
      this.painting = false;
      console.log(this.painting);
      this.ctx.beginPath()
    },

And also modify the startPainting method to :


startPainting(e) {
      this.painting = true;
      console.log(this.painting)
      this.draw(e)
    },

And that’s basically it..we fixed the problem. We just used the canvas api to build a simple painting app.

Conclusion

We have seen how simple it is to build a simple application with the canvas API and vuejs. We also learned how to use some mouse event listeners in vuejs.

We could build more applications using the canvas API or we could add more features to the application like changing of the pen color or even changing the canvas background color. Click here for source code.


Share on social media

//