Convert div into downloadable Image

32,001

Solution 1

Here is a simple way to do this.

<div id="my-node">
  You will get a image downloaded.
</div>

<button id="foo">download img</button>

<script>
var node = document.getElementById('my-node');
var btn = document.getElementById('foo');
btn.onclick = function() {
node.innerHTML = "I'm an image now."
  domtoimage.toBlob(document.getElementById('my-node'))
    .then(function(blob) {
      window.saveAs(blob, 'my-node.png');
    });
}
</script>

Here is a demo: this JSFiddle.

In this fiddle, two libraries are used:
dom-to-image: https://github.com/tsayen/dom-to-image
FileSaver.js: https://github.com/eligrey/FileSaver.js/

First one is used to turn dom into image, second one is used to download the image.

Update: If you want to get a img of base64 instead of just downloading img as the blob format. You can do as below:

domToImage
    .toBlob(document.getElementById("my-node"))
    .then(function(blob) {
      saveBlobAsFile(blob, "XX.png");
    });
  // this function is to convert blob to base64 img
  function saveBlobAsFile(blob, fileName) {
    var reader = new FileReader();
    reader.onloadend = function() {
      var base64 = reader.result;
      var img = document.createElement("img");
      img.classList.add("me-img");
      img.setAttribute("src", base64);
      // insert the img to dom
      document.getElementById("bar").appendChild(img);
    };
    reader.readAsDataURL(blob);
  }

Here FileSaver.js is not needed, we use html5 api FileReader to do the trick.

Solution 2

Increase resolution by making more pixels

Resolution kind of equals pixel density. If you want greater resolution then one attempt to create more pixels is to create a second canvas with a proportionally larger width & height and then use secondaryContext.scale & secondaryContext.drawImage(mainCanvas,0,0) to enlarge & draw the main canvas content onto the second canvas. Use this larger canvas, for example, on a printer.

Here's an example that increases the pixel density at the cost of some clarity. You don't state why you desire more resolution, but this example is useful, for example if you're outputting the image to a printer. Note: The printed page will be clearer than the density-increased image you feed to the printer because the printer prints at higher density (maybe 300dpi printer resolution vs maybe 72/96ppi).

var divX2=document.createElement('canvas');
divAt2X('#download',1.5);

$('#go').on('click',function(){
    // save
    var a = document.createElement('a');
    a.href = divX2.toDataURL("image/png");       
    a.download = 'image.png';
    a.click();                
});

function divAt2X(id,upscale){
    var w=$(id).width();
    var h=$(id).height();
    html2canvas($(id),{
        onrendered:
            function(canvasDiv){
                // scale up
                ctx=divX2.getContext('2d');
                divX2.width=w*upscale;
                divX2.height=h*upscale;
                ctx.scale(upscale,upscale);
                ctx.drawImage(canvasDiv,0,0);
            }
        }
    );
}
        #download{
            margin:10% 20%;
        }
        .download-btn{
          padding:10px;
          font-size:20px;
          margin:0 20px;
        }
        #test{
          background:#3399cc;
          padding:50px;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src='https://html2canvas.hertzen.com/build/html2canvas.js'></script>
<button id='go'>Download 1.5X</button><span>(IE/Edge don't support download)</span>
<div id="download"><h1 id="test">Testing Download</h1></div>

If you have already dismissed html2Canvas, then your way forward is more difficult because html2Canvas is one (perhaps the only one) tool we have to read html+css and draw them to the canvas element.

Increase resolution with an image manipulation library

You can use the ImageMagick library. In particular, the ImageMagick resize method will change the embedded resolution of a .png image using resampling for better quality.

Use a headless-browser on the server to capture the Div

If you need cross-browser compatibility, then you can use a server-size headless browser like PhantomJS.

The captureJS extension to PhantomJS allows you to specify a target div using standard CSS selectors. CaptureJS lets you specify the viewport size -- effectively letting you increase the pixel density.

Solution 3

One good approach that we've used at work in a production system for 1M+ daily users is to do this completely on the server side - spawn a browser (Chrome); then take a screenshot of it; then stream it to the client. The results are very clear / not pixelated at all - all of the other options turned out quite pixelated.

Share:
32,001
Siren Brown
Author by

Siren Brown

Updated on July 09, 2022

Comments

  • Siren Brown
    Siren Brown almost 2 years

    This is the code which I am using to convert div into image and download that using html2canvas.js

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://html2canvas.hertzen.com/build/html2canvas.js"></script>
    <style>
        #download{
            margin:10% 40%;
        }
        .download-btn{
            padding:10px;
            font-size:20px;
            margin:0 20px;
        }
        #test{
            background:#3399cc;
            padding:50px;
        }
        .x2{
            transform: scale(2,2);
        }
    </style>
    
    
       <div id="download">
          <h1 id="test">Testing Download</h1>
       </div>
    
        <center>
            <button id="download-window" class="download-btn">New Window</button>
            <button id="download-png" class="download-btn">Download png</button>
            <button id="download-jpg" class="download-btn">Download jpg</button>
            <button id="download-pngx2" class="download-btn">Download pngx2</button>
        </center>
    
    
    <script>
        $('#download-window').click(function(){
    
                html2canvas($('#download'), 
                 {
                    onrendered: function (canvas) {
                        var img = canvas.toDataURL("image/png");
                        window.open(img);
                    }
                 });
                });
    
        $('#download-png').click(function(){
    
                html2canvas($('#download'), 
                 {
                    onrendered: function (canvas) {
                    var a = document.createElement('a');
                        a.href = canvas.toDataURL("image/png");       
                        a.download = 'image.png';
                        a.click();
                    }
                 });
                });
    
        $('#download-pngx2').click(function(){
             $('#download').addClass('x2');
                html2canvas($('#download'), 
                 {
                    onrendered: function (canvas) {
                    var a = document.createElement('a');
                        a.href = canvas.toDataURL("image/png");       
                        a.download = 'image.png';
                        a.click();
                    }
                 });
            });
    
      $('#download-jpg').click(function(){
        html2canvas($('#download'), 
        {
          onrendered: function (canvas) {
            var a = document.createElement('a');
            // toDataURL defaults to png, so we need to request a jpeg, then convert for file download.
            a.href = canvas.toDataURL("image/jpeg").replace("image/jpeg", "image/octet-stream");
            a.download = 'image.jpg';
            a.click();
          }
        });
      });
    </script>
    

    Here image generated is not having good resolution.

    Is there any other way to generate image with good resolution?

    Can php function be used for doing this task?

  • Siren Brown
    Siren Brown about 8 years
    can you please explain me a bit in detail?
  • Siren Brown
    Siren Brown about 8 years
    Phantomjs is not a solution as it does not capture html div into image. jsfiddle.net/enjoythedaycsk/9L966sdd/1 I tried to achieve high resolution thing in this example but didn't get that... Click on download pngx2 button.. Is it possible to do operations on backend like when button is clicked canvas turns into twice its size and then pic is captured and then again canvas is taken back to regular size..
  • markE
    markE about 8 years
    It would be helpful if you explain why you need the higher resolution -- printing, retina display, etc. Pending further explanations, I've added some detail to the suggestions in my answer. I've shown how to increase the pixel density of html2canvas's output. I've pointed you towards a more specific extension to PhantomJS which allows you to both capture a div-only and to change the pixel density. I've also suggested using an image manipulation library to increase an html2canvas image's resolution using traditional upscale-with-resampling. Cheers!
  • Tom Aranda
    Tom Aranda over 6 years
    In the future, please include all relevant code in your post and don't just include a link to a code hosting site. Your post should stand alone from any other resource; consider what would happen if that site went down in the future! You can easily incorporate the JS Fiddle code directly into your answer by editing your answer.