SoFunction
Updated on 2025-02-28

How to implement the example code of page screenshot function of JS

"Page screenshot" is a common need encountered by the front-end, such as page generation posters, pop-up image sharing, etc. Because the browser does not have a native screenshot API, it is necessary to use canvas to achieve the requirements for exporting images.

Feasibility Plan

  1. Solution 1: Rewrite the DOM to canvas, and upload it to Qiniu Cloud or server immediately by calling the toBlob or toDataURL method of canvas.
  2. Solution 2: Implement canvas using third-party libraries to produce canvas elegantly without changing the page already has DOM

Solution selection

Solution 1: You need to manually calculate the Computed Style of each DOM element, and then you need to calculate the size position of the element and other attributes of the canvas.

Plan 1 Difficulty

  • You need to deprecate the existing html page and rewrite it with canvas instead.
  • When the page structure layer is complex, it is written in canvas, which is not easy to reconstruct.
  • Have a certain foundation of canvas.

Plan 2: The project has more than 20,000 stars on Github, and the author is still actively maintaining it. The API is very simple and works out of the box in existing projects.

html2canvas

Because it is a common need, the community will have mature solutions. First, try the community's solutions.

<div  style="padding: 10px; background: #f5da55">
    <h4 style="color: #000; ">Hello world!</h4>
</div>
html2canvas(("#capture")).then(canvas => {
    (canvas)
});

The above is the example usage of the official website. A new canvas DOM appears on the web page. Next we just need to convert canvas into pictures. Here we use the toDataURL and toBlob methods native to canva to last time.

Pay attention when using it. Here, if there are cross-domain pictures in the production canvas, you need to configure allowTaint to true.

If it is a native canvas implementation, canvas needs to complete all cross-domain image requests before it can be drawn. There are two solutions

  • Solution 1: Write the img tag on html and write the corresponding image url in src. The disadvantages are obvious, which will pollute the layout structure of the page.
  • Solution 2: Use js and use new Image() method. Set src to the corresponding picture url and process related operations in the onload callback. Advantages: The most feasible, but there is a problem of callback hell. Let's rewrite it with Promise
function asyncImage(url) {
    const img = new Image();
     = url;
    ('crossOrigin', 'anonymous');
    return new Promise((resolve, reject) => {
         = () => resolve(img);
         = reject;
    });
}

OK, the job is done~ Can you deliver the demand? I happily took the test, but when I tested it on the mobile terminal, I found that the pictures produced were very blurry. This is not possible, it is obviously much lower (the test does not give orz).

Github has corresponding solutionsPortal, This answer also solves the problems of many people

Basic principle: enlarge the width and height of the canvas twice. Set the css style to 1x the size of the canvas.

    var shareContent = YourTargetElem; 
    var width = ; 
    var height = ; 
    var canvas = ("canvas"); 
    var scale = 2 ||  ; //You can also use the device pixel ratio
     = width * scale; 
     = height * scale; 
    ("2d").scale(scale, scale); 

    var opts = {
        scale: scale, 
        canvas: canvas, 
        logging: true, 
        width: width, 
        height: height 
    };
    html2canvas(shareContent, opts).then(function (canvas) {
        var context = ('2d');

        var img = (canvas, , );

        (img);
        $(img).css({
            "width":  / 2 + "px",
            "height":  / 2 + "px",
        })
    });

We already know the principle, and the image becomes much clearer after actual operation. But the problem has not been solved.

Although shrinking improves clarity, the image we need is the size of the original proportion. .

After many attempts failed, I chose to give up using the framework. Just use native canvas to pick one!

canvas drawing

We know that under high-definition screen devices, any image, text, lines, and shapes drawn in canvas may have blurred problems. It can be effectively solved by introducing hidpi-canvas in GitHub.

  1. First go to GitHub to download the file:Portal
  2. Introduce files in the project;
  3. Call the getPixelRatio() function to get the ratio value;
  4. In drawImage(), multiply width and height by ratio;
  5. The final canvas is exported as a Blog, converted into a file object and uploaded to Qiniu Cloud.

The core code is as follows

    function asyncImage(url) {
        const img = new Image();
         = url;
        ('crossOrigin', 'anonymous');
        return new Promise((resolve, reject) =&gt; {
             = () =&gt; resolve(img);
             = reject;
        });
    }
    async function drawCanvas(){
        var canvas = ('canvas');
        var context = ('2d');
        var ratio = getPixelRatio(context);  // Key code         = 300 * ratio; // Canvas width         = 300 * ratio; // Canvas height        var divWidth = 300 * ratio; // Used for centering content        var divHeight = 300 * ratio; // Used for centering content        const image = await asyncImage('picUrl')
        const imgWidth = 550
        const imgHeight = 300
        (this, 50, 50, imgWidth * ratio, imgHeight * ratio)
        // Some other code
        const Blob = ((Blob)=&gt;{
            //Upload Qiniu Cloud        });
    } 

The final generated image is finally clear... You only need to adapt to different screens according to the offsetWidth of the dom.

Summarize

If the clarity of the picture is not high, or the picture requires a thumbnail image to be generated. Using html2canvas is a very good choice.
Otherwise, the pictures drawn with canvas will be clearer.

This is the article about how JS implements the screenshot function of pages. For more related content on JS pages, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!