Render HTML to an image

后端 未结 17 2111
栀梦
栀梦 2020-11-22 16:06

Is there a way to render html to image like PNG? I know that it is possible with canvas but I would like to render standard html element like div for example.

17条回答
  •  忘掉有多难
    2020-11-22 16:25

    I read the answer by Sjeiti which I found very interesting, where you with just a few plain JavaScript lines can render HTML in an image.

    We of course have to be aware of the limitations of this method (please read about some of them in his answer).

    Here I have taken his code a couple of steps further.

    An SVG-image has in principle infinite resolution, since it is vector graphics. But you might have noticed that the image that Sjeiti's code generated did not have a high resolution. This can be fixed by scaling the SVG-image before transferring it to the canvas-element, which I have done in the last one of the two (runnable) example codes i give below. The other thing I have implemented in that code is the last step, namely saving it as a PNG-file. Just to complete the whole thing.

    So, I give two runnable snippets of code:

    The first one demonstrates the infinite resolution of an SVG. Run it and zoom in with your browser to see that the resolution does not diminish as you zoom in.

    In the snippet that you can run I have used backticks to specify a so called template string with line breaks so that you can more clearly see the HTML that is rendered. But otherwise, if that HTML is within one line, then the code will be very short, like this.

    const body = document.getElementsByTagName('BODY')[0];
    const img = document.createElement('img')
    img.src = 'data:image/svg+xml,' + encodeURIComponent(`
    What you see here is only an image, nothing else.

    I really like cheese.

    Zoom in to check the resolution!
    `); body.appendChild(img);

    Here it comes as a runnable snippet.

    const body = document.getElementsByTagName('BODY')[0];
    const img = document.createElement('img')
    img.src = 'data:image/svg+xml,' + encodeURIComponent(`
      
        
          
    What you see here is only an image, nothing else.

    I really like cheese.

    Zoom in to check the resolution!
    `); body.appendChild(img);

    Zoom in and check the infinite resolution of the SVG.

    The next runnable, below, is the one that implements the two extra steps which I mentioned above, namely improving resolution by first scaling the SVG, and then the saving as a PNG-image.

    window.addEventListener("load", doit, false)
    var canvas;
    var ctx;
    var tempImg;
    function doit() {
        const body = document.getElementsByTagName('BODY')[0];
        const scale = document.getElementById('scale').value;
        let trans = document.getElementById('trans').checked;
      if (trans) {
        trans = '';
      } else {
        trans = 'background-color:white;';
      }
        let source = `
            
    What you see here is only an image, nothing else.

    I really like cheese.

    Scaling:
    ${scale} times!
    ` document.getElementById('source').innerHTML = source; canvas = document.createElement('canvas'); ctx = canvas.getContext('2d'); canvas.width = 200*scale; canvas.height = 200*scale; tempImg = document.createElement('img'); tempImg.src = 'data:image/svg+xml,' + encodeURIComponent(` ` + source + ` `); } function saveAsPng(){ ctx.drawImage(tempImg, 0, 0); var a = document.createElement('a'); a.href = canvas.toDataURL('image/png'); a.download = 'image.png'; a.click(); }
    The claims in the HTML-text is only true for the image created when you click the button.
         In this example the PNG-image will be squarish even if the HTML here on the left is not exactly squarish. That can be fixed.
         To increase the resolution of the image you can change the scaling with this slider.
    110  

    Try with different scalings. If you for example set scaling to 10, then you get a very good resolution in the generated PNG-image. And I added a little extra feature: a checkbox so that you can make the PNG-image transparent if you like.

    Notice:

    The Save-button does not work in Chrome and Edge when this script is run here at Stack Overflow. The reason is this https://www.chromestatus.com/feature/5706745674465280 .

    Therefore I have also put this snippet on https://jsfiddle.net/7gozdq5v/ where it works for those browsers.

提交回复
热议问题