实现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{
   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{
   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{
   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{
   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="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;1000px;height:2000px">
    </body>
</html>

方案三:dom->svg->canvas->png

参考链接:http://www.zhangxinxu.com/wordpress/2017/08/svg-foreignobject/

代码:

<html>
<head>

<style>
.main{
   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{
   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(/
/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);

基本上就这样了。

原文地址:https://www.cnblogs.com/aigeileshei/p/9111925.html