user1056212
user1056212

Reputation:

Does HTML5 canvas support browser-based zooming?

I had setup a simple canvas with a fillText drawn on it. It looks quite good, but when I use the browser provided zooming feature (Safari, Firefox), the antialiasing looks ugly.

I tried to use scale() raise the grid, but it doesn't help.

Is there any way to draw on a canvas that it looks sharp even with a zoomed browser window?


Screenshot (no zoom): https://i.sstatic.net/CGWka.png

Screenshot (max zoom): https://i.sstatic.net/vNPjF.png

Upvotes: 19

Views: 4578

Answers (2)

DewiW
DewiW

Reputation: 148

The short answer is no, a canvas element will not automatically support browser-based zoom, i.e. as you zoom in, your canvas element will look ugly. Your browser simply can't draw detail that isn't there.

However, there are three things that happen when browser zoom is used on desktop:

  1. The window.devicePixelRatio value changes to reflect the new physical-to-logical pixel ratio.
  2. The reported width and height (window.innerWidth and window.innerHeight) changes in response.
  3. The onresize event fires.

This means you can listen for the onresize event, and re-create your canvas in response to the new pixel ratio and display size. On desktop, this will give you a canvas element that is always sharp, without needing to draw the canvas element at a higher resolution than is required.

codepen proof of concept

I've also written an article on Medium that goes in to more detail on this approach, and other techniques that can be used to make canvas elements more accessible to those with poor eyesight: HTML canvas and accessibility

Unfortunately, mobile/tablet pinch-zoom works slightly differently, and this approach does not work there. If anybody has an alternative approach that would work with pinch-zoom, I'd love to hear them!

Upvotes: 5

Phrogz
Phrogz

Reputation: 303421

You can 'zoom' a canvas by scaling the canvas context prior to drawing commands to result in items drawn at a larger size, smoothly. For example, see this example of mine that allows you to zoom way in on draw items and see details not available at the default presentation.

The problem with browser zooming is that the HTML5 canvas—like a JPG or PNG, and unlike SVG—is based on individual pixels. If you draw a circle in 10 pixels and then tell the browser to zoom it to 50 pixels the browser cannot "invent" data to draw a smooth circle. The best it can do is provide image interpolation to try to make the 'big pixels' look slightly smoother.

The Solution

With an image, you can take a picture with a lot of pixels (e.g. 1000x800) and tell the browser to display it at a different, smaller size (e.g. 250x200). When the browser zooms in, it has more pixels to display. For example:

<img src="1000x800.jpg" style="width:250px; height:200px">

You can do the same with a canvas. The number of pixels of data in the canvas are specified by the height and width attributes (in HTML or JavaScript). You can separately specify the CSS display size (like above) to a smaller size. You don't even need to modify your existing canvas drawing code; simply:

  1. Adjust the height and width of your canvas by a particular factor (e.g. 4),
  2. Use CSS to set the display height and width back to the original size, and then
  3. Before all other drawing commands, scale up your context with ctx.scale(4,4).

Edit: I have created an example of this here:
http://jsfiddle.net/u5QPq/embedded/result/ (code)

Here's what it looks like when you zoom in:
enter image description here

As an added bonus, your canvas will also print more smoothly (in case someone is into killing trees).

Upvotes: 23

Related Questions