Support my work ♥

Implement simple anti-aliasing on JavaScript Canvas

Last year I made a little game: Connect Dots Offline

I did play a similar game, but it was riddled with adverts and flashy distractions to keep the dopamine flowing.

Baseline

This year I noticed that there is a stark difference in rendering quality between text in a div and on a canvas element on mobile browsers:

Before the optimisation

On my test device the text looked a bit blurry last year, but now it was bad. What has changed?

Well, I am not sure, but probably that the window.devicePixelRatio changed from 2.0 to 3.1578... with my new device.

Also switching from a plastic screen protector to a glass one "disables the natural diffuser".

Rendering at full scale

To keep the code flexible I added a scale_ratio that is reading window.devicePixelRatio.

Now the canvas needs to be scaled by attribute while staying the same with CSS:

width = canvas.offsetWidth;
width *= scale_ratio;
canvas.width = `${width}`;
// repeat for height as well

With CSS like this:

canvas {
    width: 100%; /* all the other rules ... */
}

Full scale

Nice rendering, but the events are broken now. Time to pre-process all touch and mouse input:

function screen_to_element_relative(element, clientX, clientY) {
    return {
        x: (clientX - element.offsetLeft) * scale_ratio,
        y: (clientY - element.offsetTop) * scale_ratio,
    };
}

This will be feed from Touch and Mouse Event's like this:

// TouchEvent or multi-touch
const xy = screen_to_element_relative(canvas, touch.clientX, touch.clientY);
// or MouseEvent
const xy = screen_to_element_relative(canvas, ev.clientX, ev.clientY);

2x Super Resolution

What if we increase the resolution?

This becomes simple, just add a scale_ratio * 2.0 and we are golden:

2xAA

Well that makes a difference of a few pixels, but no one can actually see this by eye.

So reverting back to the native resolution and save the battery for other tasks.

With all this tuning done, enjoy Connect and consider donating a bit or invite me for a snack when we meet in real life.

links

social