I. Problem description
When I was working on an H5 project, THERE was a requirement to generate HTML-generated images for users to save by long pressing. At the beginning, I was lazy to use HTML2Canvas, but I found that HTML2Canvas also had a lot of holes, and the picture was not saved completely from time to time. After trying many methods, Finally, I gave up html2Canvas and decided to draw directly on canvas. However, after drawing, the image generated by calling canvas.todataURL () method is very fuzzy, which seriously affects the user experience.
Finally, I solved this problem by referring to the materials. I made a note here for the convenience of using canvas later.
Ii. Problem analysis
There is a devicePixelRatio property in the browser’s window variable, which determines how many pixels the browser will render a pixel. For example, suppose the devicePixelRatio of a screen is 2, a 100×100 pixel image, under this screen, One pixel of the image is rendered with the width of 2 pixels, so the image actually takes up 200×200 pixels on the screen, which is equivalent to doubling the size of the image, so the image becomes blurred.
Similarly, there is a backingStorePixelRatio property in the Canvas Context (Safari and Chrome only), whose value determines how many pixels the browser will use to store the canvas information before rendering the canvas. The method of obtaining the backingStorePixelRatio attribute varies among browser vendors, so a browser prefix is required to achieve compatibility.
Three, how to solve
The key to Retina adaptation is to know the device pixel ratio of the current screen, then zoom the canvas up to that device pixel ratio to draw, and then compress the canvas to double for display.
Pay attention to the basics:
- To set the canvas size of a canvas, use canvas.width and canvas.height;
- To set the actual render size of the canvas, use the style property or CSS Settings width and height, simply scale the canvas.
The actual canvas size is 750px × 1334px, but the actual rendered page size is 375px × 667px, which is equivalent to doubling the size to display.<canvas width="750" height="1334" style="width:375px; height:667px"></canvas>
Copy the code
// get the Canvas object
let canvas = document.getElementById('capture_canvas');
this.ctx = canvas.getContext('2d');
/ / 2, obtain pixel ratio, amplification ratio for: devicePixelRatio/webkitBackingStorePixelRatio, written here are compatible
let backingStore = this.ctx.backingStorePixelRatio ||
this.ctx.webkitBackingStorePixelRatio ||
this.ctx.mozBackingStorePixelRatio ||
this.ctx.msBackingStorePixelRatio ||
this.ctx.oBackingStorePixelRatio ||
this.ctx.backingStorePixelRatio || 1;
let ratio = (window.devicePixelRatio || 1) / backingStore;
To set the Canvas size, use canvas.width and canvas.height.
let oldWidth = canvas.width;
let oldHeight = canvas.height;
canvas.width = oldWidth * ratio;
canvas.height = oldHeight * ratio;
To set the actual render size of the canvas, use the style property or CSS set width and height, simply scale the canvas.
canvas.style.width = oldWidth + 'px';
canvas.style.height = oldHeight + 'px';
// 5. Magnification factor: After Canvas is enlarged, the corresponding drawing picture also needs to be enlarged, so you can directly use scale method
this.ctx.scale(ratio, ratio);
Copy the code