html页面、canvas导出图片

背景:项目现场提出将一个html做的图形页面导出为一张图片的需求,在网上搜了一下,发现都不是很全面,所以综合了很多大神的帖子,自己再次封装,以适用项目需求。

所需js库:html2canvas.js(https://github.com/niklasvh/html2canvas); Export2Image.js(自己封装),其中new Export2Image(htmlDom,[opts]).export()是执行导出命令。opts = {400,height:400,type:"png",fname:"downloadName"}为可选参数。

注意:在使用过程中,发现一个问题,dom背景图片千万不能设置background-size:contain/conver,否则背景图片导不出来。

代码:

  1 /**
  2  * Created by tengri on 2016-5-9.
  3  */
  4 
  5 /**
  6  * 导出类
  7  * @param content  要导出的内容
  8  * @constructor
  9  */
 10 function Export2Image(content,opts){
 11     this.exportObj = typeof(content) == "string" ? document.getElementById(content) : content;
 12     if(!this.exportObj) throw new Error("导出内容对象只能传递ID和DOM对象");
 13     this.opts = opts || {};
 14     if(this.exportObj.nodeName !="CANVAS"){
 15         this.exportType = "html2Image";
 16         this.canvas = document.createElement("canvas");
 17         this.canvas.style.display = "none";
 18         //如果没有设置宽度和高度,实际是多大就导出多大
 19         this.canvas.width = this.opts.width || this.exportObj.scrollWidth + 10;
 20         this.canvas.height = this.opts.height || this.exportObj.scrollHeight + 10;
 21     }else{
 22         this.exportType = "canvas2Image";
 23         this.canvas = this.exportObj;
 24     }
 25     if(this.opts.width && this.opts.height){
 26         this.actualWidth = this.opts.width;
 27         this.actualHeight = this.opts.height;
 28     }
 29     this.type =  this.opts.type || "png";
 30     this.fileName = (this.opts.name || new Date().getTime()) + "." + this.type;
 31     this.init();
 32     return this;
 33 }
 34 
 35 /**
 36  * 初始化
 37  */
 38 Export2Image.prototype.init = function(){
 39     this._fixType();
 40 }
 41 
 42 Export2Image.prototype._encodeData = function(data){
 43     if(!window.btoa) throw "btoa undefined";
 44     var strDtata = "";
 45     if(typeof(data) !="string"){
 46         for(var i = 0 ; i < data.length;i++){
 47             strDtata +=String.fromCharCode(data[i]);
 48         }
 49     }else{
 50         strDtata = data;
 51     }
 52     return window.btoa(strDtata);
 53 };
 54 
 55 /**
 56  * 根据配置生成固定大小图片
 57  * @param width
 58  * @param height
 59  */
 60 Export2Image.prototype._scaleCanvas = function(width,height){
 61     var w = this.canvas.width;
 62     var h = this.canvas.height;
 63     width = width || w;
 64     height = height  || h;
 65 
 66     var newCanvas = document.createElement("canvas");
 67     newCanvas.width = width;
 68     newCanvas.height = height;
 69     var ctx = newCanvas.getContext("2d");
 70     ctx.drawImage(this.canvas,0,0,w,h,0,0,width,height);
 71     this.canvas = newCanvas;
 72 };
 73 
 74 /**
 75  * 获取canvas的Dataurl
 76  */
 77 Export2Image.prototype._getDataURL = function(){
 78     return this.canvas.toDataURL(this.type);
 79 };
 80 /**
 81  * 获取导出图片类型
 82  * @private
 83  */
 84 Export2Image.prototype._fixType = function(){
 85     var type = this.type.toLocaleLowerCase().replace(/jpg/i,"jpeg");
 86     var res = type.match(/png|jpeg|bmp|gif/)[0];
 87     this.type = "image/" + res;
 88 };
 89 
 90 /**
 91  * 获取数据
 92  */
 93 Export2Image.prototype.getData = function(){
 94     if(this.actualWidth && this.actualHeight){
 95         this._scaleCanvas(this.actualWidth,this.actualHeight);
 96     }
 97     var strData = "";
 98     if (/bmp/.test(this.type)) {
 99         var data = this._getImageData();
100         strData = this._getBitmapImage(data);
101     } else {
102         strData = this._getDataURL();
103     }
104     return strData;
105 }
106 
107 /**
108  * 普通图片获取
109  * @private
110  */
111 Export2Image.prototype._getImageData = function(){
112     var w = this.canvas.width, h = this.canvas.height;
113     return this.canvas.getContext('2d').getImageData(0, 0, w, h);
114 };
115 
116 /**
117  * 位图获取
118  * @private
119  */
120 Export2Image.prototype._getBitmapImage = function(oData){
121     var aHeader = [];
122 
123     var iWidth = oData.width;
124     var iHeight = oData.height;
125 
126     aHeader.push(0x42); // magic 1
127     aHeader.push(0x4D);
128 
129     var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
130     aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
131     aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
132     aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
133     aHeader.push(iFileSize % 256);
134 
135     aHeader.push(0); // reserved
136     aHeader.push(0);
137     aHeader.push(0); // reserved
138     aHeader.push(0);
139 
140     aHeader.push(54); // dataoffset
141     aHeader.push(0);
142     aHeader.push(0);
143     aHeader.push(0);
144 
145     var aInfoHeader = [];
146     aInfoHeader.push(40); // info header size
147     aInfoHeader.push(0);
148     aInfoHeader.push(0);
149     aInfoHeader.push(0);
150 
151     var iImageWidth = iWidth;
152     aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
153     aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
154     aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
155     aInfoHeader.push(iImageWidth % 256);
156 
157     var iImageHeight = iHeight;
158     aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
159     aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
160     aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
161     aInfoHeader.push(iImageHeight % 256);
162 
163     aInfoHeader.push(1); // num of planes
164     aInfoHeader.push(0);
165 
166     aInfoHeader.push(24); // num of bits per pixel
167     aInfoHeader.push(0);
168 
169     aInfoHeader.push(0); // compression = none
170     aInfoHeader.push(0);
171     aInfoHeader.push(0);
172     aInfoHeader.push(0);
173 
174     var iDataSize = iWidth*iHeight*3;
175     aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
176     aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
177     aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
178     aInfoHeader.push(iDataSize % 256);
179 
180     for (var i=0;i<16;i++) {
181         aInfoHeader.push(0);    // these bytes not used
182     }
183 
184     var iPadding = (4 - ((iWidth * 3) % 4)) % 4;
185 
186     var aImgData = oData.data;
187 
188     var strPixelData = "";
189     var y = iHeight;
190     do {
191         var iOffsetY = iWidth*(y-1)*4;
192         var strPixelRow = "";
193         for (var x=0;x<iWidth;x++) {
194             var iOffsetX = 4*x;
195 
196             strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
197             strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
198             strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
199         }
200         for (var c=0;c<iPadding;c++) {
201             strPixelRow += String.fromCharCode(0);
202         }
203         strPixelData += strPixelRow;
204     } while (--y);
205 
206     var strEncoded = this._encodeData(aHeader.concat(aInfoHeader)) + this._encodeData(strPixelData);
207 
208     return  this._makeDataURI(strEncoded);
209 };
210 
211 Export2Image.prototype._makeDataURI = function(strData){
212     return "data:" + this.type + ";base64," + strData;
213 }
214 
215 /**
216  * 保存
217  * @param data
218  * @param fileName
219  * @private
220  */
221 Export2Image.prototype._saveFile = function(data,fileName){
222     try{
223         //TODO:IE浏览器
224          new ActiveXObject("Microsoft.XMLHTTP");
225         var oImg = document.createElement("img");
226         oImg.src = data;
227         oImg.onload = function(){
228             myWindow=window.open('','_blank','width=800,height=600');
229             myWindow.document.write("<img src='"+data+"'>")
230             myWindow.focus()
231         }
232     }catch(e){
233          var saveLink = document.createElementNS("http://www.w3.org/1999/xhtml","a");
234         saveLink.href = data;
235         saveLink.download = fileName;
236         var event = document.createEvent("MouseEvents");
237         event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
238         saveLink.dispatchEvent(event);
239     }
240 
241 };
242 
243 Export2Image.prototype.exportPic = function(){
244     if(this.exportType == "html2Image"){
245         if(typeof(html2canvas) !="function"){
246             alert("需要引入html2canvas.js库文件");
247             return;
248         }
249         var that = this;
250         html2canvas(this.exportObj, {
251             onrendered: function(canvas) {
252                 that.canvas = canvas;
253                 var data = that.getData();
254                 var imgData = data.replace(that.type,'image/octet-stream');
255                 that._saveFile(imgData,that.fileName);
256             }
257         });
258     }else{
259         var data = this.getData();
260         var imgData = data.replace(this.type,'image/octet-stream');
261         this._saveFile(imgData,this.fileName);
262     }
263 
264 };
 1 <html>
 2 <meta http-equiv="X-UA-Compatible" content="chrome=1">
 3 <meta charset="utf-8">
 4 <head>
 5     <title>dom页面导出为图片</title>
 6     <style type="text/css">
 7         #wrap{
 8             width:400px;
 9             height:300px;
10             line-height:300px;
11             font-family: "Courier New", Courier, monospace;
12             font-size: 18px;
13             text-align: center;
14             border:  1px solid #ccc;
15             background-image: url("img/a.jpg");
16             overflow: auto;
17         }
18 
19     </style>
20 </head>
21 <body>
22     <div id="wrap">这是DOM元素,相当于项目中的图形所在的div
23     </div>
24     <input type="button" value="html导出图片" onclick="htmlExportHandler();"/><br><hr/>
25     <canvas id="myCanvas" width="600" height="400" style="background:yellowgreen"></canvas>
26     <input type="button" value="canvas导出图片" onclick="canvasExportHandler();"/><br><hr/>
27 
28 </body>
29 </html>
30 <script type="text/javascript" src="js/html5.js"></script>
31 <script type="text/javascript" src="js/html2canvas.js"></script>
32 <script type="text/javascript" src="js/Export2Image.js"></script>
33 <script>
34 
35 
36     window.onload = function() {
37         var canvas = document.getElementById("myCanvas");
38         var ctx=canvas.getContext('2d');
39         ctx.fillStyle='#FF0000';
40         ctx.fillRect(10,10,200,100);
41 
42     };
43 
44     function htmlExportHandler(){
45         var oContent = document.getElementById("wrap");
46         new Export2Image(oContent,{type:"bmp",name:"html导出文件"}).export();
47     }
48 
49     function canvasExportHandler(){
50         new Export2Image("myCanvas").export();
51     }
52 
53 </script>                                                                                                                          
原文地址:https://www.cnblogs.com/tengri/p/5477741.html