Reputation:
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
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:
window.devicePixelRatio
value changes to reflect the new physical-to-logical pixel ratio.window.innerWidth
and window.innerHeight
) changes in response.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.
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
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:
height
and width
of your canvas by a particular factor (e.g. 4),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:
As an added bonus, your canvas will also print more smoothly (in case someone is into killing trees).
Upvotes: 23