实现html转png
公司要求将一些重要数据全部以图片的形式放在官网上,防止网络爬虫。
之前都是UI作图,人工上传,为了解放生产力,于是我们程序处理。
步骤:
1、html得到与原图一致的图片(交给前端处理)
2、html转png
3、配置动态html转动态png,放到对应位置
解决过程:
1、百度找插件
2、百度找插件
3、问人
4、研究替换使用
方案一:
html2canvas插件
官网地址:
http://html2canvas.hertzen.com/
使用例子:
<html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title></title> <style> .main{ width: 900px; margin: 2rem auto; padding: 2rem 3rem; box-shadow: 0 0 23px #ddd6; } h1{ text-align: center; font-size: 32px; color: #3e3e3e; } h1 span{ text-align: center; font-size: 16px; color: #ddd; display: block; } h2{ border-left: 5px solid #ff6a00; padding-left: 11px; font-size: 28px; font-weight: normal; line-height: 25px; margin-bottom: 50px; margin-top: 40px; } .box{ width: 20%; box-shadow: 0 0 22px rgba(221, 221, 221, 0.65); height: 6rem; padding: 1rem; font-size: 29px; text-align: center; margin-right: 1%; display: inline-block; margin-bottom: 2%; } .box em{ font-weight: bold; font-style: normal; display: block; line-height: 1.5rem; margin-top: 1rem; font-size: 27px; } .box span{ font-size: 14px; color: #bdbdbd; } .clear{ clear: both; visibility: hidden; } </style> <script type="text/javascript" src="jquery.min.js"></script> <script type="text/javascript" src="html2cavas.js"></script> <script type="text/javascript"> $(function(){ $("#saveImg").click(function(){ html2canvas($(".main")[0]).then(function(canvas) { var imgUri = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); //alert(imgUri); // 获取生成的图片的url window.location.href= imgUri; // 下载图片 }); }); }); </script> </head> <body> <div class='main'> <h1>蚂米平台实时运营数据 <span>数据统计截止时间:2018-05-27</span> </h1> <div> <h2>交易数据</h2> <h3>数据概览</h3> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <h3>数据概览</h3> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <h2>出借方和借款方信息</h2> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='clear'></div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> </div> </div> <button id="saveImg">保存图片</button> </body> </html>
中间遇到问题:
结果:
样式有些缺失,官网明确指出不支持box-shadow等css样式
方案二:使用svg的forginObject属性将dom内容放入svg
链接:https://www.zhihu.com/question/20681535 中dion的回答
拷贝它的写法在我们的基础上修改,但是最后图片是svg形式。
<!DOCTYPE html> <html> <head> <style> .main{ width: 900px; margin: 2rem auto; padding: 2rem 3rem; box-shadow: 0 0 23px rgba(221, 221, 221, 0.4); } h1{ text-align: center; font-size: 32px; color: #3e3e3e; } h1 span{ text-align: center; font-size: 16px; color: #ddd; display: block; } h2{ border-left: 5px solid #ff6a00; padding-left: 11px; font-size: 28px; font-weight: normal; line-height: 25px; margin-bottom: 50px; margin-top: 40px; } .box{ width: 20%; box-shadow: 0 0 22px rgba(221, 221, 221, 0.65); height: 6rem; padding: 1rem; font-size: 29px; text-align: center; margin-right: 1%; display: inline-block; margin-bottom: 2%; } .box em{ font-weight: bold; font-style: normal; display: block; line-height: 1.5rem; margin-top: 1rem; font-size: 27px; } .box span{ font-size: 14px; color: #bdbdbd; } .clear{ clear: both; visibility: hidden; } </style> </head> <body> <h2>Input Div:</h2> <div id="input" style="width:900px"> <div class='main' id="main"> <h1>蚂米平台实时运营数据 <span>数据统计截止时间:2018-05-27</span> </h1> <div> <h2>交易数据</h2> <h3>数据概览</h3> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <h3>数据概览</h3> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <h2>出借方和借款方信息</h2> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='clear'></div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> </div> </div> </div> <h2>Output Image:</h2> <script> var divContent = document.getElementById('input').innerHTML; var data = "data:image/svg+xml," + "<svg xmlns='http://www.w3.org/2000/svg'>" + "<foreignObject width='100%' height='100%'>" + "<div xmlns='http://www.w3.org/1999/xhtml' style='font-size:16px;font-family:Helvetica'>" + divContent + "</div>" + "</foreignObject>" + "</svg>"; var img = new Image(); img.src = data; img.width = "1000"; img.height = "2000"; document.getElementsByTagName('body')[0].appendChild(img); </script> <img id="outputImg" /> </body> </html>
中途遇到的问题:
svg对应image width和height没有正确设置,导致输出部分有时候展示不全
结果:
得到了svg,但是无法得到png
替代做法,使用svg代替png为图片资源,引用如下,t1.svg是从前面展示的out里面图片另存为得到的:
<html> <head></head> <body> <img src="t1.svg" style="display:block;width:1000px;height:2000px"> </body> </html>
方案三:dom->svg->canvas->png
参考链接:http://www.zhangxinxu.com/wordpress/2017/08/svg-foreignobject/
代码:
<html> <head> <style> .main{ width: 900px; margin: 2rem auto; padding: 2rem 3rem; box-shadow: 0 0 23px rgba(221, 221, 221, 0.4); } h1{ text-align: center; font-size: 32px; color: #3e3e3e; } h1 span{ text-align: center; font-size: 16px; color: #ddd; display: block; } h2{ border-left: 5px solid #ff6a00; padding-left: 11px; font-size: 28px; font-weight: normal; line-height: 25px; margin-bottom: 50px; margin-top: 40px; } .box{ width: 20%; box-shadow: 0 0 22px rgba(221, 221, 221, 0.65); height: 6rem; padding: 1rem; font-size: 29px; text-align: center; margin-right: 1%; display: inline-block; margin-bottom: 2%; } .box em{ font-weight: bold; font-style: normal; display: block; line-height: 1.5rem; margin-top: 1rem; font-size: 27px; } .box span{ font-size: 14px; color: #bdbdbd; } .clear{ clear: both; visibility: hidden; } </style> </head> <body> <div class='main' id="main"> <h1>蚂米平台实时运营数据 <span>数据统计截止时间:2018-05-27</span> </h1> <div> <h2>交易数据</h2> <h3>数据概览</h3> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <h3>数据概览</h3> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <h2>出借方和借款方信息</h2> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='clear'></div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> <div class='box'> <em>204571155.20</em> <span>累计借贷金额(元)</span> </div> </div> <img/> </div> <button id="down">保存图片</button> <script type="text/javascript"> // DOM转图片的方法 var domToImg = (function () { // 转png需要的canvas对象及其上下文 var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); // canvas绘制图片元素方法 var draw = function (img) { var width = img.width, height = img.height; // canvas绘制 canvas.width = width; canvas.height = height; // 画布清除 context.clearRect(0, 0, width, height); //白色背景 context.fillStyle = '#fff'; context.fillRect(0, 0, canvas.width, canvas.height); // 绘制图片到canvas context.drawImage(img, 0, 0); }; // canvas画布绘制的原图片 var img = new Image(); // 回调 var callback = function () {}; // 图片回调 img.onload = function () { draw(this); // 回调方法 callback(); }; var exports = { dom: null, // DOM变成svg,并作为图片显示 dom2Svg: function () { var dom = this.dom; if (!dom) { return this; } // 复制DOM节点 var cloneDom = dom.cloneNode(true); cloneDom.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); cloneDom.classList.remove('outline'); // 如果有图片,变成base64 var imgDom = null; if (cloneDom.tagName.toLowerCase() == 'img') { imgDom = cloneDom; } else { // 这里就假设一个图片,多图自己遍历转换下就好了 imgDom = cloneDom.querySelector('img'); } if (imgDom) { draw(imgDom); //imgDom.src = canvas.toDataURL(); imgDom.src = canvas.toDataURL("image/png");; } // 图片地址显示为DOM转换的svg img.src = 'data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="' + dom.offsetWidth + '" height="' + dom.offsetHeight + '"><foreignObject x="0" y="0" width="100%" height="100%">'+ new XMLSerializer().serializeToString(cloneDom).replace(/#/g, '%23').replace(/\n/g, '%0A') + document.querySelector('style').outerHTML + '</foreignObject></svg>'; return this; }, // 作为图片下载,JS前端下载可参考这篇文章: // JS前端创建html或json文件并浏览器导出下载 - http://www.zhangxinxu.com/wordpress/?p=6252 download: function () { // 创建隐藏的可下载链接 var eleLink = document.createElement('a'); // 下载图片文件名就按照时间戳来 eleLink.download = 'zxx_png-' + (+new Date() + '').slice(1, 9) + '.png'; eleLink.style.display = 'none'; // 触发图片onload是个异步过程,因此,需要在回调中处理 callback = function () { eleLink.href = canvas.toDataURL(); // 触发点击 document.body.appendChild(eleLink); eleLink.click(); // 然后移除 document.body.removeChild(eleLink); }; // dom变图片 this.dom2Svg(); } }; return exports; })(); // 实例页面的交互代码 var button = document.getElementById('down'); // 点击并下载图片 button.addEventListener('click', function (event) { var eleTarget = document.getElementById("main"); if (eleTarget !== this) { domToImg.dom = eleTarget; domToImg.download(); } }); </script> </html>
中途问题:
canvas转png时候得到的背景总是黑色的,听说转png时候是透明背景,jpeg是黑色背景,在toDataURL()中指定转换的类型
解决方案:
//白色背景
context.fillStyle = '#fff';
context.fillRect(0, 0, canvas.width, canvas.height);
基本上就这样了。