News for hackers. Stuff that matters.
Re:It's always been you, Canvas2D by simonsarris on Friday March 04, 2022 @12:30PM (#30557680)
99% the problem is one of pixel density. That is, you have a 400x400 canvas, and a 400x400 CSS pixel space you are drawing it to, but your devices pixel ratio is higher than 1, so it looks kinda blurry. This is because devices squish more than one "hardware pixel" per CSS pixel. Often at a ratio of 1.5 or 2, or higher.

The solution is to make a larger canvas, say, 800x800 and put it into that 400x400 space.

Here is an example, using that MDN code, with a 400x400 canvas (red) next to a 800x800 canvas (blue). CSS is forcing them both to appear the same 400x400 size. The blue one should look sharper on most devices.

Note how the 800x800 canvas needs to be scaled double with ctx2.scale(2,2) so that it appears correct.

https://codepen.io/simonsarris/pen/eYexbOb

Pixel ratio is variable (window.devicePixelRatio), so this canvas pixel density is something you'll want to programmatically set for each user.

Re:It's always been you, Canvas2D by Trufa on Friday March 04, 2022 @12:35PM (#30557741)
Dude!! Freaking awesome!! Thanks a bunch!! That's exactly what I was looking for! If you have some sort of ko-fi account or whatever I'll buy you a coffee!
Re:It's always been you, Canvas2D by etimberg on Friday March 04, 2022 @01:09PM (#30558221)
One thing to keep in mind with the window.devicePixelRatio is that it is not a static value as it can change over time. Some common reasons it could change are if the user drags the browser window from a low density screen to a high density one. Additionally, it will change if the user zooms the page in and out.
Re:It's always been you, Canvas2D by leeoniya on Friday March 04, 2022 @02:33PM (#30559318)
you can use matchMedia to detect devicePixelRatio changes and re-sync:

https://github.com/leeoniya/uPlot/blob/190134aa844cfa2a0c052...

everything stays crisp even as you browser-zoom. e.g. https://leeoniya.github.io/uPlot/demos/area-fill.html

Re:It's always been you, Canvas2D by moron4hire on Friday March 04, 2022 @03:20PM (#30559937)
Zooming also fires the Window's `resize` event, which will also catch a user rotating their smartphone/tablet, or, erh, resizing the window on desktop.
Re:It's always been you, Canvas2D by leeoniya on Friday March 04, 2022 @03:43PM (#30560276)
resize and orientationchange don't change devicePixelRatio though, so they're somewhat different concerns.
Re:It's always been you, Canvas2D by moron4hire on Friday March 04, 2022 @07:04PM (#30562326)
No, it's the same concern. The concern is not "how do I keep track of just devicePixelRatio?" It's "how do I fill this window with a canvas at native resolution?" Resize handles all of that. Device changes orientation? Resize fires. User zooms on content (this changing devicePixelRatio)? Resize fires. Anything that changes the page's clientWidth/clientHeight causes the Resize event to fire. You need only the one event.
Re:It's always been you, Canvas2D by Dylan16807 on Friday March 04, 2022 @09:39PM (#30563597)
> The concern is not "how do I keep track of just devicePixelRatio?" It's "how do I fill this window with a canvas at native resolution?"

Not everyone's canvas is filling the window.

Re:It's always been you, Canvas2D by moron4hire on Friday March 04, 2022 @10:32PM (#30563956)
All the ways in which you will care about how to buffer dimensions of your canvas to avoid aliasing artifacts can be handled with just the window.onresize event, whether your canvas is fixed or proportionally sized.

https://codepen.io/SeanMcBeth/pen/QWOoLNX

Throw a check in there to make sure the native dimensions actually did change so you don't needlessly redraw. Debounce it with setTimeout if you're super worried about people waggling their windows around or whatever.

Re:It's always been you, Canvas2D by inDigiNeous on Friday March 04, 2022 @03:27PM (#30560046)
Yeah I was struggling with this one a while, seems there is no way to know the actual devicePixelRatio of the display inside a browser, as the browser zoom level directly affects that.

Or does anyone here happen to know a way ?

Re:It's always been you, Canvas2D by moron4hire on Friday March 04, 2022 @07:29PM (#30562521)
DevicePixelRatio and clientWidth/clientHeight change together. You need only the Resize event on the Canvas. Your canvas.clientWidth * window.devicePixelRatio will always be the native width of the canvas.
Re:It's always been you, Canvas2D by simonsarris on Friday March 04, 2022 @01:01PM (#30558110)
Haha well, you could always subscribe to my newsletter for a month. You might get a kick out of it anyway.

I'm glad to have solved your mystery!

Re:It's always been you, Canvas2D by Trufa on Saturday March 05, 2022 @09:19AM (#30567798)
Done!!
Re:It's always been you, Canvas2D by altairprime on Friday March 04, 2022 @02:12PM (#30559037)
To add a small caveat here for others, assuming 2x as the necessary scaling multiplier is not necessarily a safe shortcut when choosing your virtual canvas size; iPhones use 3x resources to look crisp, and 5K macOS users can have their 5120x2880 displays set to 2048x1152 or 1600x900 which are 2.5x and 3.2x respectively.

It still helps when you do your canvas at 2x rather than just at 1x. But if you're looking for best-fidelity rather than better-fidelity, duly noted.

Re:It's always been you, Canvas2D by jorl17 on Friday March 04, 2022 @09:54PM (#30563693)
I recently embarked on a months-long just-for-fun effort of porting an old AS3/Flash game to Haxe and make sure it worked on every imaginable Haxe target I could find. If there was something that bit me was how ugly everything looked inside the browser, even when using a WebGL backend.

It turns out it was very obviously exactly what you described. You basically have to double the resolution to get it to look decent on retina and 4k screens. Once I found this out I was over the moon!

(On a related note, colouring looks way off on the HTML5 target compared to native ones, and I spent an embarassing number of hours manually brute-forcing a shader to make everything look similar.

Oh, and sound sucks in the browser.

Oh, and Safari sucks. Seriously, it just sucks. The amount of hacks I put in place to workaround its egregious limitations, particularly regarding canvas operations is insane.)

Re:It's always been you, Canvas2D by ngcc_hk on Friday March 04, 2022 @09:10PM (#30563375)
Wow. Great hint. Thanks.