100%
Contents

How I Built an Infinite Canvas: the why

• vee
This is going to be a series of articles on disecting the source code and the design decisions of the infinite canvas tool kit library @ue-too/board.

What is an Infinite Canvas?

Web applications like figma, miro, whimsical, excalidraw, tldraw, and team one are all using infinite canvases. If you've used any of these tools, you've probably seen the infinite canvas in action. Infinite canvas allows user to zoom in and out and pan around the canvas. It is not bounded by the traditional way of 1 axis scrolling. It's like a giant drawing board that you can scatter ideas on and move them around. The Infinite Canvas website has a great explanation of the concept. Seeing the star growing rate of the excalidraw and tldraw, we can see that the concept gained more traction since the pandemic.

Doesn't HTML canvas support this out of the box?

Unfortunately, the HTML canvas element does not support this out of the box. Every application mentioned above has their own implementation of the infinite canvas. Let me show you a bare minimal example of turning a canvas element into an infinite canvas. I'll use the canvas elemenet example from the MDN documentation. It's a simple example of drawing a green rectangle on the canvas.

html<canvas id="canvas"></canvas>
javascriptconst canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

ctx.fillStyle = "green";
ctx.fillRect(10, 10, 150, 100);

Your browser does not support the canvas element.

This is an actual canvas element not a screenshot

You can see that the rectangle is drawn on the canvas. But it's just like a static image. There's no way to interact with the elements on the canvas. This is what canvas is essentially is, a static image.

Canvas element transformed into an infinite canvas would be like this:
Your browser does not support the canvas element.

The canvas is now interactive.

You can pan the canvas using:

  • keyboard and mouse: middle mouse button or left mouse button while holding down the spacebar
  • trackpad: two finger swipe
  • touch screen: two finger swipe

You can zoom in and out using:

  • keyboard and mouse: scroll wheel + ctrl key
  • trackpad: two finger pinch
  • touch screen: two finger pinch

You can easily see how the canvas is much more interactive now. There are many more features that can be added to the canvas. But this is a good starting point.

Why Bother Building One from Scratch?

Given the popularity of infinite canvas applications, there are many libraries that can help on building an infinite canvas. So why did I decide to build one from scratch?

At the time I was working on a horse racing simulation game as a side project. I needed a way to model out the race tracks in real life in order to run the simulation. I tried building an online 2D bezier curve editor. I wasn't familiar with the concept of infinite canvas at the time, but I did manage to find an example using the keywords: "html", "canvas", "pan". This is the codepen that I found and it was a great starting point.

Only after I already had the early version of the @ue-too/board library, I realized that I was actually building an infinite canvas library. That's when I also started to survey the landscape of the infinite canvas libraries and found that none of them satisfies my requirements.

I was looking for four main things:

  • Independent of any framework: not just frontend framework but also the canvas framework; it should be able to work with any canvas framework but not tied to any specific one.
  • Easy to use: since there are some maths involved, I want it to have intuitive API.
  • Customizable: a some sort of plugin system to allow users to customize the behavior of the infinite canvas.
  • Flexible: I was planning to have an offscreen canvas in the worker thread. I need the library to also be able to handle the offscreen canvas.

I'll list out some of the libraries that I've surveyed and why I didn't choose them. Maybe some of them are exactly what you're looking for.

  • pixi-viewport: it's a great library and it's the closest to what I want. But it's tied to the pixi.js framework; the plugin system is exactly what I initially planned for @ue-too/board but then I realized that I needed to have a more flexible plugin system. pixi-viewport's plugin is tied to the event handlers but not all behaviors are directly related to those.
  • infinite-canvas: it wraps around the canvas 2D rendering context and provides a way to actually draw lines or geometries on the canvas that extends to infinity. Although it does come with some viewport management features, there are too many other features that I don't need.
  • scroller: it's a standalone library that is independent of any framework but when I surveyed the library it not was being activly maintained. But seems like the author is making new updates recently.

In the next article, I'll start to dissect the source code of @ue-too/board.