Matthew Jones

Given how often I've mentioned it recently, my dear readers, you are probably aware that my team and I have been working on a new project. Said project's primary goal was to replace an application that has been in use for many years at our company, in which users could create "drawings" of basic shapes, lines, text, and colors to map out where certain things should be placed at their facilities (think along the lines of an emergency-exit map).

In the process of developing this application, my team and I settled on using a JavaScript library called FabricJS to implement the drawing portion. FabricJS is a library which enables, according to their own site, an "interactive object model on top of canvas element" and, more importantly for us, the ability to save drawings in the JSON format. It was a no-brainer.

It also occurred to us that there weren't any good, long-form tutorials about how to use FabricJS, so that's what I'm writing here. For this post and the next eight, we're going to see how to develop a drawing application using FabricJS and TypeScript.

Credit and Caveat

Before we get started, I need to give credit where credit is due: the code used in these samples was originally developed by my teammate (and fellow long-haired dude) Christopher Jestice. He gave permission for me to use this code and credit him. Refinements to his original code base (as well as certain changes made just for this series) are by me, so we consider these examples a truly joint effort.

Further, Chris and I want you dear readers to know the following: neither of us are intimately familiar with the workings of TypeScript. We chose it because of its similarity to our most-familiar language C#. If anyone out there has suggestions on how to improve the code we use in these posts, please feel free to let us know in the comments.

Goals

The main goal of this blog series is to create a drawing canvas, using FabricJS and TypeScript, which can do the following things:

Draw straight lines

Draw basic shapes (ovals, rectangles, triangles) and text

Draw freeform lines

Use colors for lines and fill

Use a few line styles (e.g. dotted, solid, dashed)

Display status messages

Implement cut/copy/paste with hotkeys

Have an undo/redo feature with hotkeys

Have a "save to server" feature with hotkey

More specifically, we want our final canvas to look like this:

By the end of this nine-part series, our canvas will fully implement all of the above features.

The Sample Project

As with all my code-based posts, this series has a sample project hosted on GitHub. Check it out!

Without any further ado, let's get started building our drawing canvas with FabricJS and TypeScript!

Setting Up TypeScript

Before we can create the TypeScript classes to represent our drawing, we need a tsconfig.json file to give the TypeScript compiler a group of settings. Here's a shortened version of the one this sample project uses:

The two important properties to notice are the "lib" property and the "outFile" property. The "lib" property sets a list of TypeScript library files that need to be included in the compilation; because this project will use some pretty recent features, our list includes "es2015" for ECMAScript 2015 and "dom.iterable" for iteration properties.

Setting Up Libraries

There is some additional setup we need to do: we need to include the libraries for FabricJS, jQuery, Bootstrap, and a few typings for TypeScript. How you choose to include these libraries is up to you; Chris and I both use Visual Studio, and as such we chose to use the unimaginatively-named Library Manager (LibMan) extension. Here's the libman.json file we used:

Note the "destination" settings for the jQuery and FabricJS typings: they are included in the DrawingEditor directory, which is where we will place our TypeScript classes.

The Starting Markup

We can now start building the markup and script for our drawing canvas.

(NOTE: For this series, we are using ASP.NET Core Razor Pages. If you are unfamiliar with this tech stack, check some of my other posts about it. The markup won't be terribly different in other stacks, I believe.)

FabricJS uses a Canvas element to represent the drawing area. In our case, we want our canvas to use up as much of the visible area of the page as possible, so we are going to create the canvas in a sort-of roundabout way.

Notice: there's no Canvas element! That's because we're going to replace that innermost div with the Canvas when we create our drawing class in TypeScript. In other words, the innermost div is just a placeholder.

We now need a TypeScript class to represent the drawing area itself. This class needs to be able to replace the inner div with the markup for a FabricJS canvas, as well as create that canvas to a specified size. Here's the typescript for that class:

The Example Page

With all our pieces in place, we can now run the project. The drawing page gives us the following screenshot:

It's not quite what we saw in the goal photo earlier in the post, but it's a start. The real test is to check the markup.

See the markup in the red box? It shows that a new div, one with class "canvas-container" was inserted where our innermost div was previously, and within the new div are two canvas objects. This is a function of how FabricJS behaves.

We did it! We created a brand new FabricJS canvas onto our Razor Pages app! But it doesn't actually do anything yet, and in the next part of this series, we'll add some very basic line-drawing functionality to our new canvas.