Is it possible to set the size of the bitmap in an HTML5 canvas so that it exactly matches the display size in device pixels, ie the number of physical pixels used to display the canvas, even when window.devicePixelRatio
is not an integer?
There is a good description of how to resize the canvas on webglfundamentals but it does not properly handle non-integer devicePixelRatio
s. My understanding so far:
- The display size of the canvas is set in CSS with, eg,
canvas {width: 200px;}
. - The underlying bitmap size is set with, eg,
<canvas width="100"/>
in HTML orcanvas.width = 100
in JS. - The bitmap will be stretched to fit the CSS size (how is affected by
object-fit
andobject-position
). - We can set bitmap size to be equal to some expression involving
canvas.clientWidth
. canvas.clientWidth
is an integer and its unit are CSS pixels and is the calculated width of the content (plus padding). I don't know if the browsers actually draw the content into a whole number of CSS pixels or a whole number of device pixels.
So webglfundamentals suggests something like
canvas.width = Math.floor(canvas.clientWidth * window.devicePixelRatio);
but if window.devicePixelRatio
is a fraction, this sometimes doesn't work (2 pixel wide lines drawn on integer coordinates are fuzzy). My 1920x1080 screen has devicePixelRatio
of 1.5 by default, and page zoom can affects this, so lots of reasons why devicePixelRatio
is not an integer as a rule. What can we do?
window.devicePixelRatio
will never be an integer, according to MDN: A double-precision floating-point value – Puto