primers

In my recent work, I encountered the second problem after the canvas width and height problem.

Display blur problem

When displayed on a PC browser, no obvious blurring was found and it was acceptable. But on a phone, there’s a noticeable blur. Here is an example, scan access qr code below.

In this example, CSS is used to control the width and height of the canvas, and the display effect of the pictures inside is inconsistent. Query the data, find the same problem in StackOverflow, test it out:

  • Properties of the Canvas element itselfwidthheightDetermines how many pixels can be displayed on the canvas. If not set, width defaults to 300 and height to 150.
  • CSS propertieswidthheight, refers to the size of the element displayed on the screen. If CSS Settings are not applied to the Canvas, the canvas’s default size will be used.
  • If CSS properties are setwidthheight, when used inside the canvasdrawImageWhen setting the width and height of the picture, the displayed width and height will be converted according to a certain proportion. For example, in the above example, the image is set to be 300 wide and 90 high, and the canvas renders pixels 300 and 150 by default. (CSS height/Canvas property height) * drawImage sets the height = (90/150) * 90 = 54.

I don’t really see that in the specification.

why

Find a related question on StackOverflow and an introduction to the HTML5 Rocks article in the answer. The reason is that the canvas is drawn independently of the devicePixelRatio. Affected by devicePixelRatio, one logical pixel corresponds to multiple actual device physical pixels on an HD display. For example, on a device with a devicePixelRatio of 2, CSS set to 100px means that the device needs to be filled with 200px physical pixels. So when the canvas draws a 100px area, it actually wants to fill the device with 100px physical pixels. But because devicePixelRatio required that the device display 200px of physical pixels, the browser intelligently filled in the Spaces between the pixels to display the elements at the appropriate size.

Safari6 supports a property called backingStorePixelRatio, which determines how many pixels the browser will use to render the canvas’s information. Something like devicePixelRatio. Safari6 had a value of 2, so the canvas was not blurred in Safari6, but it was later removed, and browsers now do not support this property, see Issue 277205.

The solution

The solution is to detect the pixel ratio of the device and draw the canvas element with the corresponding multiple ratio. The method is as follows:

function createHDCanvas (w=300,h=150) {
  var ratio = window.devicePixelRatio || 1;
  var canvas = document.createElement('canvas');
  canvas.width = w * ratio; // Actual render pixels
  canvas.height = h * ratio; // Actual render pixels
  canvas.style.width = `${w}px`; // Control the display size
  canvas.style.height = `${h}px`; // Control the display size
  canvas.getContext('2d').setTransform(ratio, 0.0, ratio, 0.0);
  return canvas;
}
Copy the code

Here is a comparison example, scan access qr code below.

The resources

  • The canvas element
  • How do I fix blurry text in my HTML5 canvas?
  • Why context2d.backingStorePixelRatio deprecated?