BLOG

SVG whiteboard implementation with TypeScript and SVG.js

When it comes to drawing in a browser, it can be a long and difficult task to implement. This article describes our implementation of an SVG drawing board.

The task

In a recent project cliizii.com, a client wanted to have a drawing board in a browser where multiple users could interact. They already had a working whiteboard that we would have to redesign and improve according to their needs.

SVG whiteboard implementation with TypeScript and SVG.js

The problem
When we looked at the whiteboard’s code, we immediately realized that it wouldn’t work in the long term. The library version being used was quite outdated and a lot of source code could be improved since there are new patterns invented in that area. The update to the newest version wasn’t possible without digging into the version history.

The solution
After talking with the client, we got approval to start over from scratch. But that raised a few questions – Canvas or SVG? Are there ready-to-go implementations? If not, what libraries could we use for our own implementation?

Canvas or SVG?
The first question we addressed was whether to use Canvas or SVG. We dug into Google to search for ways that Canvas and SVG were being used and the differences between them. Then we decided which was the best for our needs. We found this article that summarizes our research quite well. Here are the relevant things for our drawing board that we discovered:

  • Canvas doesn’t scale. Using it with mobile would be impossible/hard to implement.
  • SVG elements allow us to interact with them (different DOM events, CSS styles, etc.).
  • Because SVG is an XML format, it makes saving to a database pretty easy. This also helps us create PDFs from the drawing board.

After all our research, SVG became the obvious choice and you may see all the differences in real life web system: cliizii.com.

Ready-to-go or custom implementation?
Because we didn’t find any ready-to-go libraries, we had to implement one ourselves. The next thing we searched for were libraries that make SVG interactions easy for developers. The big three were Raphaël, Snap.svg and SVG.js 

Raphaël
We almost immediately discarded this library because it was very rarely maintained and had several open issues on GitHub. We also didn’t like the documentation. This was the library that was used in the client’s existing whiteboard.

Snap.svg
Snap.svg was our initial library of choice. It was updated regularly and had more stars on GitHub than SVG.js. It had decent documentation and nice examples, and overall everybody on our team was optimistic about using it. So, we went with Snap.svg and overlooked SVG.js completely, as it was just beginning to gain popularity.

With Snap.svg, we had a working example with WebSockets in no time, and implementation went pretty smoothly. At least, that’s what we thought at the time. When our QA started testing our drawing board, we discovered several issues. Firstly, the calculations weren’t 100% accurate when we wanted to resize or rotate the shapes, so we had to recheck the math. This was our fault. Secondly, it wasn’t running the same way on all browsers. On Firefox, it was using a lot of memory and the browser was lagging. On IE, it wasn’t working at all. After that, we decided to give SVG.js a try.

SVG.js
After giving SVG.js another chance, we found out that it is very modular and you can add already made modules easily. It turned out that all the main features we needed were already made – draw, select, resize, drag. All we had to do was link them together, add our history control system (undo/redo), add permissions to actions and make it work with WebSockets. We were feeling dumb for overlooking this library.

Result

You can check out the working example when you sign up for a free trial at cliizii.com. Thank you!

Previous
Next