Creating a simple drawing app using canvas. Saving and loading images

JavaScript

In this article, we grasp the very basics of a canvas. We learn every piece of knowledge that is needed to create a simple drawing app that can also save our images and load them back to the editor.

The basics of a canvas

With the  element, we can draw images using JavaScript. The above gives us many possibilities, limited by what you can imagine and put into life with your code. When you put the   in your page, you start with a blank rectangle with its size defined by the width and height – those are the only canvas-specific attributes.

As you can see, you can also put something inside of the   tag – if you do so, it acts as a fallback in case the browser does not support it. The chances of that happening are pretty slim though! The only culprit seems to be the Internet Explorer in version 8 and older.

caniuse.com

Since we need to access the canvas from our code, let’s give it an id.

I’m using the   here to make sure that our DOM tree is ready

Once we’ve got the canvas, we can access its context. It is a rendering context for our drawing surface, and we use it to draw any shape. Today we focus on 2D graphics, that’s we use the CanvasRenderingContext2D interface.

Let’s start by drawing some simple rectangles. To do this, we use the   function.

This gives us our first rectangle! The arguments of a function are:

  • x-coordinate of the upper-left corner
  • y-coordinate of the upper-left corner
  • width of the rectangle
  • height of the rectangle

As you can see, there is no argument for the color. The above is because we need to set it separately and to do that, we set the   attribute.

 

The fillStyle property accepts different ways of specifying the color

There are many other different ways to draw shapes and define how they look, such as the strokeStyle.

Drawing on the canvas

To draw on the canvas, we need to attach some event listeners. Let’s start with mousedown.

When to start drawing

The mousedown event is fired at an Element when a pointing device button is pressed while the pointer is inside the element.

As soon as someone presses a mouse inside of our canvas, we want to start drawing!

When to stop drawing

Another event that we need is the mouseup.

The mousedown event is fired at an Element when a pointing device button is pressed while the pointer is inside the element.

The drawing itself

In our simple example, we draw a rectangle every time the mouse moves if the previous conditions are met: the user hovers over the canvas and he clicked a mouse once. To do that, we need the mousemove event.

The mousemove event is fired at an element when a pointing device (usually a mouse) is moved while the cursor’s hotspot is inside it.

As you can see, in this example, I use an arrow function because I want to pass both the event and the context to the   function.

The   and   are coordinates of the cursor relative to the left edge of the entire document. This means that if the canvas is not in the top left corner of the page, it is not accurate. To account for it, we can use the   function.

And thanks to that, we have a fully working functionality of drawing on a canvas!

Saving and loading images

To save and load images, we need a button and an input first.

Saving an image

To save an image, we use the   function. It returns the data in the URI format that contain the representation of the image in the type that we choose.

In the   function, we create a dummy anchor, then attach the data, define a filename, and initiate the download.

Loading an image

To load an image, we listen for the change event of the input.

Since the input stores the files in an array, we need to choose the last element:

When we have the file, we need to read it to interpret it accurately. To do it, we need the File Reader.

As soon as it reads the file successfully, we resolve the promise. The last thing to do is to load the image to the canvas.

Since the   function that we want to use accepts an instance of the Image, we need to convert it first. When we have it, we clear the canvas and load the image.

Once we have all that, we can successfully load an image.

Putting it all together

My proposition of making it all work together is to use a class.

See the Pen
xoRJVx
by Marcin Wanago (@mwanago)
on CodePen.

Summary

In this article, we’ve learned how to create a simple drawing using canvas. To do this we had to learn the very basics of the canvas and how to work with certain event listeners. While this is an elementary example, you are free to expand it and add new features.

Subscribe
Notify of
guest
7 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
saifi
saifi
5 years ago

but on tablet or mobile not working touch event please help me

NPK
NPK
3 years ago
Reply to  saifi

Instead of “mousedown” use “touchstart” and “mousemove” use “touchmove” and “mouseup” use “touchend”.

https://www.w3schools.com/jsref/event_touchend.asp
https://www.w3schools.com/jsref/event_touchmove.asp
https://www.w3schools.com/jsref/event_touchstart.asp

Jhon
Jhon
4 years ago

Its interesting, but I’ve tryied to change stroke style to continous,red rounded pencil and has no success

mat
mat
2 years ago
Reply to  Jhon

To change to a continuous line and change color to red replace the draw(event) with the below snippet
draw(event) {
    if (this.isDrawing) {
      this.context.strokeStyle = “#000”;
      this.context.lineJoin = “round”;
      this.context.lineWidth = 1;
      this.context.strokeStyle = “#FF0000”;
      this.context.lineTo(
        event.pageX this.offsetLeft,
        event.pageY this.offsetTop
      );
      this.context.closePath();
      this.context.stroke();
      this.context.moveTo(
        event.pageX this.offsetLeft,
        event.pageY this.offsetTop
      );
    }
  }

Evan
3 years ago

How can have a “regular” line instead of the dotted one?

Rowan
3 years ago
Reply to  Evan

watch this tutorial on how to make a simple drawing program.
https://www.youtube.com/watch?v=3GqUM4mEYKA

Last edited 3 years ago by Rowan
Chrismed
Chrismed
2 years ago

Amazing, thank you, you save my day