是否有一种方法将html渲染成PNG那样的图像?我知道这是可能的与画布,但我想渲染标准的html元素,如div为例。


当前回答

有很多选择,它们都有各自的优点和缺点。

选项1:使用API

ApiFlash(基于chrome) EvoPDF(有html选项) Grabzit HTML/CSS图像API ...

Pros

执行Javascript 近乎完美渲染 正确使用缓存选项时快速 缩放由api处理 精确计时,视口,… 大多数时候,他们提供的是免费方案

Cons

如果你打算经常使用它们,就不是免费的

选项2:使用众多可用库中的一个

dom-to-image Wkhtmltoimage(包含在wkhtmltopdf工具中) IMGKit(用于ruby和基于wkhtmltoimage) Imgkit(适用于python,基于wkhtmltoimage) python-webkit2png ...

Pros

大多数时候,转换是相当快的

Cons

坏的呈现 不执行javascript 不支持最近的网页功能(FlexBox,高级选择器,网页字体,盒子大小,媒体查询,…) 有时不容易安装 缩放复杂

选项3:使用PhantomJs和包装器库

PhantomJs node-webshot(用于PhantomJs的javascript包装库) ...

Pros

执行Javascript 很快

Cons

坏的呈现 不支持最近的网页功能(FlexBox,高级选择器,网页字体,盒子大小,媒体查询,…) 缩放复杂 不那么容易使它工作,如果有图像要加载…

选项4:使用Chrome Headless和一个包装器库

Chrome无头 chrome-devtools-protocol Puppeteer (Chrome无头浏览器的javascript包装库) ...

Pros

执行Javascript 近乎完美渲染

Cons

要得到想要的结果并不容易: 页面加载时间 视窗尺寸 缩放复杂 相当慢,甚至更慢,如果html包含外部链接

披露:我是ApiFlash的创始人。我尽力提供了一个诚实而有用的答案。

其他回答

我读了Sjeiti的答案,我觉得很有趣,在那里你只需要几行简单的JavaScript就可以在图像中呈现HTML。

当然,我们必须意识到这种方法的局限性(请在他的回答中阅读其中的一些)。

在这里,我进一步使用了他的代码。

svg图像原则上具有无限分辨率,因为它是矢量图形。但您可能已经注意到,Sjeiti的代码生成的图像分辨率并不高。在将SVG-image转移到canvas-element之前,可以通过缩放SVG-image来解决这个问题,我在下面给出的两个(可运行的)示例代码中的最后一个代码中已经做到了这一点。我在该代码中实现的另一件事是最后一步,即将其保存为png文件。只是为了完成整个过程。

因此,我给出了两个可运行的代码片段:

第一个演示了SVG的无限分辨率。运行它并使用浏览器放大,以查看分辨率是否随着放大而减小。

在您可以运行的代码片段中,我已经使用反勾号指定了一个带有换行符的所谓模板字符串,以便您可以更清楚地看到呈现的HTML。但是,如果HTML在一行之内,那么代码就会非常短,就像这样。

const body = document.getElementsByTagName('BODY')[0];
const img = document.createElement('img')
img.src = 'data:image/svg+xml,' + encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;"><style>em {color:red;}.test {color:blue;}</style>What you see here is only an image, nothing else.<br /><br /><em>I</em> really like <span class="test">cheese.</span><br /><br />Zoom in to check the resolution!</div></foreignObject></svg>`);        
body.appendChild(img);

这里是一个可运行的代码片段。

const body = document.getElementsByTagName('BODY')[0]; const img = document.createElement('img') img.src = 'data:image/svg+xml,' + encodeURIComponent(` <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <foreignObject width="100%" height="100%"> <div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;"> <style> em { color:red; } .test { color:blue; } </style> What you see here is only an image, nothing else.<br /> <br /> <em>I</em> really like <span class="test">cheese.</span><br /> <br /> Zoom in to check the resolution! </div> </foreignObject> </svg> `); body.appendChild(img);

放大并检查SVG的无限分辨率。

下面的下一个可运行文件实现了我上面提到的两个额外步骤,即通过缩放SVG来提高分辨率,然后将其保存为png图像。

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 = ` <div xmlns="http://www.w3.org/1999/xhtml" style="border:1px solid red;padding:20px;${trans}"> <style> em { color:red; } .test { color:blue; } </style> What you see here is only an image, nothing else.<br /> <br /> <em>I</em> really like <span class="test">cheese.</span><br /> <br /> <div style="text-align:center;"> Scaling: <br /> ${scale} times! </div> </div>` 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(` <svg xmlns="http://www.w3.org/2000/svg" width="${200*scale}" height="${200*scale}"> <foreignObject style=" width:200px; height:200px; transform:scale(${scale}); " >` + source + ` </foreignObject> </svg> `); } function saveAsPng(){ ctx.drawImage(tempImg, 0, 0); var a = document.createElement('a'); a.href = canvas.toDataURL('image/png'); a.download = 'image.png'; a.click(); } <table border="0"> <tr> <td colspan="2"> The claims in the HTML-text is only true for the image created when you click the button. </td> </tr> <tr> <td width="250"> <div id="source" style="width:200px;height:200px;"> </div> </td> <td valign="top"> <div> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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.<br> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;To increase the resolution of the image you can change the scaling with this slider. <div style="text-align:right;margin:5px 0px;"> <label style="background-color:#FDD;border:1px solid #F77;padding:0px 10px;"><input id="trans" type="checkbox" onchange="doit();" />&nbsp;&nbsp;Make it transparent</label> </div> <span style="white-space:nowrap;">1<input id="scale" type="range" min="1" max="10" step="0.25" value="2" oninput="doit();" style="width:150px;vertical-align:-8px;" />10&nbsp;&nbsp;<button onclick="saveAsPng();">Save as PNG-image</button></span> </div> </td> </tr> </table>

尝试不同的比例。例如,如果您将缩放设置为10,那么您将在生成的png图像中获得非常好的分辨率。我还添加了一个额外的功能:一个复选框,这样你就可以使png图像透明。

注意:

当这个脚本在Stack Overflow运行时,保存按钮在Chrome和Edge中不工作。原因是https://www.chromestatus.com/feature/5706745674465280。

因此,我也把这个片段放在https://jsfiddle.net/7gozdq5v/上,它适用于这些浏览器。

使用这段代码,它一定会工作:

<脚本type = " text / javascript”> 美元(文档)。Ready (function () { setTimeout(函数(){ downloadImage (); }, 1000) }); 函数downloadImage () { html2canvas (document.querySelector(“# dvContainer”))。然后(canvas => { a = document.createElement('a'); document.body.appendChild(一个); A.download = "test.png"; a.href = canvas.toDataURL(); a.click (); }); } > < /脚本

不要忘记在你的程序中包含Html2CanvasJS文件。 https://html2canvas.hertzen.com/dist/html2canvas.js

你可以添加引用HtmlRenderer到你的项目,并执行以下操作:

string htmlCode ="<p>This is a sample html.</p>";
Image image = HtmlRender.RenderToImage(htmlCode ,new Size(500,300));

你可以使用像wkhtmltopdf这样的HTML转PDF工具。然后你可以使用像imagemagick这样的PDF图像工具。不可否认,这是服务器端,一个非常复杂的过程…

我在Chrome、Firefox和MS Edge上使用的唯一一个库是rasterizeHTML。它输出比HTML2Canvas更好的质量,并且仍然受支持,不像HTML2Canvas。

获取元素和下载为PNG

var node= document.getElementById("elementId");
var canvas = document.createElement("canvas");
canvas.height = node.offsetHeight;
canvas.width = node.offsetWidth;
var name = "test.png"

rasterizeHTML.drawHTML(node.outerHTML, canvas)
     .then(function (renderResult) {
            if (navigator.msSaveBlob) {
                window.navigator.msSaveBlob(canvas.msToBlob(), name);
            } else {
                const a = document.createElement("a");
                document.body.appendChild(a);
                a.style = "display: none";
                a.href = canvas.toDataURL();
                a.download = name;
                a.click();
                document.body.removeChild(a);
            }
     });