HTML2canvas生成模糊图像

35
我正在使用jsPDF,它使用html2canvas从一些HTML元素中生成图像并插入到.pdf文件中。但是html2canvas存在一个问题,它会从HTML生成模糊的图像。请看下面的示例:
HTML内容:

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

html2canvas生成的图片:

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

有没有什么方法可以修复它,或者有没有更好的选项来从HTML中获取图像?
谢谢!

你是否检查过这是否涉及所有的网络浏览器? - Mikko Ohtamaa
我会尝试将imageSmoothingEnabled设置为false(注意供应商前缀)。 - GameAlchemist
9个回答

38

您可以在html2canvas中使用缩放选项。

在最新的版本v1.0.0-alpha.1中,您可以使用scale选项来增加分辨率(scale:2将使分辨率加倍,默认为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
});

12
最新版本中未使用dpi选项,因此请使用比例尺来获取高质量图像。 - Ricky sharma
2
缩放功能完美运作 :) 另一个解决方法是在调用html2canvas之前更改 window.devicePixelRatio = 2; - Patrik Kelemen
@PatrikKelemen 这对我来说很有效,也是最简单和最清晰的选择,代码变动最小。谢谢! - AJQShake

14

因为我使用的是Retina显示器,所以遇到了这个问题。我通过MisterLamb在这里提供的解决方案解决了它。

$(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和PNG

输入图像描述

缩放的HTML和PNG

输入图像描述


你在使用哪个版本的html2canvas库来进行此修复? - gyochum
1
对我来说完美运作。确保您包含此版本的html2canvas脚本以使其正常工作。 - Tanuj Dhaundiyal
3
这并没有按照预期生成。它将702的尺寸增加到了800宽度,但当图像生成时,它显示得更小,并且从图像的顶部和右侧被裁切掉了。 - saadk
@crclayton:另外,“canvas.width”和“canvas.style.width”有什么区别? - saadk
我和saadk有同样的问题。 - Caleb Pitman
我认为新版本在缩放时保持了质量。我使用了带有缩放配置的版本1,工作得非常完美。 - Ishan Fernando

10

我曾经遇到过这个问题,但通过使用domtoimage解决了它。之前用HTML2CANVAS的方案对我不起作用,尽管有缩放选项可以在捕捉前增加目标div的大小,但如果该div内部有无法调整大小的元素,则此方法无效,例如在我的情况下,是编辑工具中的画布。

总之,我选择了domtoimage,相信我,这是所有解决方案中最好的。

我没有遇到任何html2canvas的问题,例如:

需要在网页顶部以便html2canvas能够完全捕捉截图和低dpi问题。

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');
    });
}

将DOM转化为图像的CDN:

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

用于jspdf的CDN:

https://cdnjs.com/libraries/jspdf


1
您给我的domtoimage建议真是太棒了!html2canvas让我头疼不已,而domtoimage解决了像素问题。非常感谢您的帮助 :) - adir1521
截至2022年,dom-to-image已经五年没有更新了,所以我使用html-to-image。 - foske

5

解决方法非常简单,在经过X个小时的测试后。

将所有DIV的高度加倍,将IMG的高度加倍,最后将HTML缩放为0.5,或者如果你想要更好的质量,可以将它们设置为3倍高(在这种情况下,HTML缩放必须为0.33或更低),假设原始图像尺寸较大。

例如:

HTML

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

CSS之前

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

CSS after(仅更改)

html {
   zoom: 0.5;
}

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

以下是我的结果:

之前的PDF 之后的PDF


1
我已经试了几个小时来修复我的模糊PDF文件。由于 jspdf 和 html2canvas 可能的各种组合,我无法找到任何有效的 js 解决方案。然而,这个 CSS 解决方案完美地满足了我的需求。感谢您提供如此简单的答案。 - CChoma

2

16
我也遇到了这个模糊图像的问题,但我没有理解你的答案。能否再详细解释一下?请不要改变原意,使语言更加通俗易懂。 - Mohammad Faizan khan
3
请让解决方案更加明显易懂 :) - kashesandr
1
@YoYo,实际上不是的。使用纯前端技术栈无法从各种HTML+SVG中打印PDF文件的适当解决方案。但是,您可以配置一些简单的网页来使其正常工作。您可能应该使用Phantomjs进行PDF打印功能,它更加稳定,但需要额外的服务器。此外,还有在线服务,您可以提供公共URL并获取PDF文件。同时,欢迎您为前端编写pdf打印库 :) - kashesandr

2
这是对我有用的解决方法。 不是因为我正在使用视网膜显示器(因为我没有):

只需使用此 getBounds() 方法更改 html2canvas.js 中的方法即可:

https://github.com/niklasvh/html2canvas/issues/576
 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 {};
    }

4
请注意,尽管这使得它比以前更好,但仍然不能完美地解决问题。 - Shai UI

1

2
虽然这样确实有效,但将比例值设置得更高也会增加文件的大小。 - krish

0

dom-to-image 库对我来说完美运作!

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;


-5

尝试使用Canvas2Image库,对我来说它可以提供更好质量的图像(fiddle中的div)

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

祝你好运!


3
如果html2canvas已经生成了低质量的图像,Canvas2Image无法提高图像质量,这正是问题的根本原因。 - Martin Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接