Question

I am using jsPDF and it uses html2canvas to generate an image from some html element and insert on the .pdf file. But there is a problem on html2canvas, it generates blurry images from the html. See example below:

HTML content:

http://puu.sh/7SZz4.png

html2canvas generated image:

http://puu.sh/7SZAT.png

Is there any way to fix it or is there any better option to get the image form html?

thanks!

Was it helpful?

Solution 5

I have found out my problem. Happens that my screen is a Retina Display, so when the canvas2html will render the HTML, due to the difference of pixel density on retina screen, the image is rendered blurred.

Found out the solution here:

https://github.com/cburgmer/rasterizeHTML.js/blob/master/examples/retina.html

OTHER TIPS

you can use scale options in html2canvas.

In the latest release, v1.0.0-alpha.1, you can use the scale option to increase the resolution (scale: 2 will double the resolution from the default 96dpi).

// Create a canvas with double-resolution.
html2canvas(element, {
    scale: 2,
    onrendered: myRenderFunction
});
// Create a canvas with 144 dpi (1.5x resolution).
html2canvas(element, {
    dpi: 144,
    onrendered: myRenderFunction
});

I had this problem because I was on a retina display. I solved in by using MisterLamb's solution here.

$(window).load(function () {

    var scaleBy = 5;
    var w = 1000;
    var h = 1000;
    var div = document.querySelector('#screen');
    var canvas = document.createElement('canvas');
    canvas.width = w * scaleBy;
    canvas.height = h * scaleBy;
    canvas.style.width = w + 'px';
    canvas.style.height = h + 'px';
    var context = canvas.getContext('2d');
    context.scale(scaleBy, scaleBy);

    html2canvas(div, {
        canvas:canvas,
        onrendered: function (canvas) {
            theCanvas = canvas;
            document.body.appendChild(canvas);

            Canvas2Image.saveAsPNG(canvas);
            $(body).append(canvas);
        }
    });
});

HTML and PNG without scaling

enter image description here

HTML and PNG with scaling

enter image description here

I was facing this problem and i solved it by using domtoimage instead of html2canvas.

This HTML2CANVAS solution was not working good for me i know the scale option does increase the target div's size before capturing it but it won't work if you have something inside that div which won't resize e.g in my case it was canvas for my editing tool.

Anyway for this i opted for domtoimage and trust me i think that this is the best solution of them all.

I didn't had to face any problem of html2canvas for example:

need to be at the top of webpage so html2canvas can capture the shot completely and low dpi problem

function print()
{
    var node = document.getElementById('shirtDiv');
    var options = {
        quality: 0.95
    };

    domtoimage.toJpeg(node, options).then(function (dataUrl)
    {
        var doc = new jsPDF();
        doc.addImage(dataUrl, 'JPEG', -18, 20, 240, 134.12);
        doc.save('Test.pdf');
    });
}

Cdn for dom to image:

https://cdnjs.com/libraries/dom-to-image

Cdn for jspdf:

https://cdnjs.com/libraries/jspdf

solution is very simple, after X hours of testing.

Set your ALL div's 2x higher, your IMG 2x higher, and finally set html zoom on 0.5, or if you want better quality yet, set 3x higher (in this case the html zoom must be 0.33) or more, (the original image sizes are assumed to be larger).

For example:

HTML

<body>
 <div class="pdf">
   <img src="image.jpg">
 </div>
</body>

CSS before

body {
    background: #b2b2b2;
}
.pdf {
   background: #fff;
   /* A4 size */
   width: 842px;
   height: 595px;
 }
img {
   width: 300px;
   height: 200px;
}

CSS after (only changes)

html {
   zoom: 0.5;
}

.pdf {
   /* A4 size before . 2 */
   width: 1684; 
   height: 1190px; 
 }
img { /* size before . 2 */
   width: 600px;
   height: 400px;
}

AND here is my result:

PDF before PDF after

This is what fixed it for me. And it wasn't because I was using a retina display (because I don't have one):

https://github.com/niklasvh/html2canvas/issues/576

Just change the getBounds() method in html2canvas.js with this one:

 function getBounds (node) {
        if (node.getBoundingClientRect) {
            var clientRect = node.getBoundingClientRect();
            var width = node.offsetWidth == null ? clientRect.width : node.offsetWidth;
            return {
                top   : Math.floor(clientRect.top),
                bottom: Math.floor(clientRect.bottom || (clientRect.top + clientRect.height)),
                right : Math.floor(clientRect.left + width),
                left  : Math.floor(clientRect.left),
                width : width,
                height: node.offsetHeight == null ? clientRect.height : node.offsetHeight
            };
        }
        return {};
    }

If anyone is still looking for a solution to work for them I had success by setting scale: 5. Check it out here in their documentation. https://html2canvas.hertzen.com/configuration

dom-to-image library worked perfect for me!

import domtoimage from "dom-to-image";
// Convert dom to image function
const exportAsImage = async (el, imageFileName) => {
  domtoimage
    .toPng(el)
    .then(function (dataUrl) {
      const image = dataUrl;

      downloadImage(image, imageFileName);
    })
    .catch(function (error) {
      console.error("oops, something went wrong!", error);
    });
};
// dowload image function
const downloadImage = (blob, fileName) => {
  const fakeLink = window.document.createElement("a");
  fakeLink.style = "display:none;";
  fakeLink.download = fileName;
  fakeLink.href = blob;
  document.body.appendChild(fakeLink);
  fakeLink.click();
  document.body.removeChild(fakeLink);
  fakeLink.remove();
};

export default exportAsImage;

Try the Canvas2Image library, it gives a better quality image at least for me div to image (fiddle).

    html2canvas($("#widget"), {
        onrendered: function(canvas) {
            theCanvas = canvas;
            Canvas2Image.saveAsPNG(canvas);  // Convert and download as image with a prmompt. 
        }
    });

Good luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top