Back to all posts
4 min read

From Jobless to Chart.js: My 2D Wake-Up Call

javascript chartjs canvas open-source go alpine.js
From Jobless to Chart.js: My 2D Wake-Up Call

From Jobless to Chart.js: My 2D Wake-Up Call

So there I was, scrolling through GitHub like any normal human being with too much free time. That’s when I found this repo called Kaunta by a senior dev I follow.

First thing I noticed: it’s written in Go. Cool. Second thing: no release-please setup. So naturally, my first contribution was adding the YAML config and updating the Magefile for all the CI stuff like formatting, vetting, and benchmarking.

My first PR got merged, and then I had way too much time on my hands. Why? Well, let’s just say I’m currently between jobs. Not because HR delayed anything at my current job, but because, well, I don’t have one. Jobless life, baby.

The project looked interesting enough to keep tinkering with, so I decided to clean up the UI. Started with the home page, made a landing page (which was definitely NOT easy), and eventually got to the dashboard.

Here’s where things got fun. I’m pretty sure the dashboard worked fine before I touched it. And then suddenly, it didn’t. Classic developer move. Turns out there was a race condition where the chart was trying to draw itself before the canvas even existed on the page. Fixed it using the Alpine.js intersect plugin, which basically waits until the element is actually visible before doing anything. Also changed some chart colors because why not.

Everything else was smooth sailing. But the real discovery here was Chart.js itself. I’d never really worked with it before, so this was my first proper dive into how it actually works.

Installing Chart.js

Getting Chart.js set up is stupid simple. Grab it from npm, yarn, or just use a CDN. Nothing crazy. The interesting part is understanding what happens after you install it.

The Canvas Does All The Work

Here’s the thing about Chart.js that I didn’t realize at first: everything gets drawn on a single <canvas> element. Every line, every point, every label. It’s all just pixels on that one canvas.

If you open up DevTools and inspect a chart, you won’t find individual DOM elements for each bar or data point. Just one lonely <canvas> tag doing all the heavy lifting.

This also means if you want to manipulate individual elements directly, Chart.js isn’t really built for that. You’d need something more low level like D3.js.

Creating a Canvas

You start with basic HTML:

<canvas id="playground"></canvas>

I always give it an ID because it makes grabbing it in JavaScript way easier:

const playground = document.getElementById("playground");

In TypeScript, you have to be more specific:

const playground = document.getElementById("playground") as HTMLCanvasElement;

That as keyword is there because TypeScript likes to be extra careful. Also, always check if the element actually exists:

if (!playground) throw new Error("Canvas element not found");

Understanding Context

Once you have your canvas, you need to tell it how you want to draw. That’s where context comes in:

const ctx = playground.getContext("2d");

The context is basically your drawing toolkit. Chart.js uses 2D context by default. It’s what lets you actually draw shapes, lines, and colors on the canvas.

And yeah, check that the context exists before you start drawing:

if (!ctx) throw new Error("Context not created correctly");

Drawing Your First Shape

Before jumping into Chart.js, I wanted to understand what was happening underneath. So I tried drawing a simple rectangle:

ctx.beginPath();
ctx.rect(10, 10, 100, 100);
ctx.closePath();

I ran this and saw nothing. Confused the hell out of me. Turns out, this only defines the path of the shape. You haven’t actually drawn it yet.

To make it visible, you need to fill it:

ctx.beginPath();
ctx.rect(10, 10, 100, 100);
ctx.fill();
ctx.closePath();

This draws a black rectangle by default. Want a different color?

ctx.fillStyle = "#f00"; // Red
ctx.fill();

You can also just outline the shape instead:

ctx.strokeStyle = "#f00";
ctx.stroke();

Quick Math Thing

The canvas coordinate system starts at the top left corner of the browser window. That’s your (0, 0) point.

X axis goes left to right. Y axis goes top to bottom. Each unit is a pixel.

So when you write ctx.rect(10, 10, 100, 100), it means start 10 pixels from the left, 10 pixels from the top, and draw a rectangle that’s 100 pixels wide and 100 pixels tall.

Pretty straightforward once you get it.

Back to Chart.js

All this canvas stuff matters because Chart.js is doing all of this for you behind the scenes. You just pass in some config options and it handles all the drawing.

What looks simple on the surface is actually a bunch of complex canvas operations happening every time a chart renders.

Once I understood that, debugging and customizing charts became way easier. The official docs are actually really good, and the examples are genuinely helpful.

If you’ve never used Chart.js before, just try making a simple line chart. It’s pretty satisfying once you see it working.

Anyway, that’s my Chart.js learning journey. Now I’m gonna go scroll through GitHub some more and pretend I’m being productive.