1. 程式人生 > >實現html轉png

實現html轉png

rgb 拷貝 callback 缺失 另存為 輸出 play clear com

公司要求將一些重要數據全部以圖片的形式放在官網上,防止網絡爬蟲。

之前都是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);

基本上就這樣了。

實現html轉png