背景:项目现场提出将一个html做的图形页面导出为一张图片的需求,在网上搜了一下,发现都不是很全面,所以综合了很多大神的帖子,自己再次封装,以适用项目需求。
所需js库:html2canvas.js(https://github.com/niklasvh/html2canvas); Export2Image.js(自己封装),其中new Export2Image(htmlDom,[opts]).export()是执行导出命令。opts = {width:400,height:400,type:"png",fname:"downloadName"}为可选参数。
注意:在使用过程中,发现一个问题,dom背景图片千万不能设置background-size:contain/conver,否则背景图片导不出来。
代码:
/**
* Created by tengri on 2016-5-9.*/
/**
* 导出类
* @param content 要导出的内容
* @constructor
*/
function Export2Image(content,opts){
this.exportObj = typeof(content) == "string" ? document.getElementById(content) : content;
if(!this.exportObj) throw new Error("导出内容对象只能传递ID和DOM对象");
this.opts = opts || {};
if(this.exportObj.nodeName !="CANVAS"){
this.exportType = "html2Image";
this.canvas = document.createElement("canvas");
this.canvas.style.display = "none";
//如果没有设置宽度和高度,实际是多大就导出多大
this.canvas.width = this.opts.width || this.exportObj.scrollWidth + 10;
this.canvas.height = this.opts.height || this.exportObj.scrollHeight + 10;
}else{
this.exportType = "canvas2Image";
this.canvas = this.exportObj;
}
if(this.opts.width && this.opts.height){
this.actualWidth = this.opts.width;
this.actualHeight = this.opts.height;
}
this.type = this.opts.type || "png";
this.fileName = (this.opts.name || new Date().getTime()) + "." + this.type;
this.init();
return this;
}
/**
* 初始化
*/
Export2Image.prototype.init = function(){
this._fixType();
}
Export2Image.prototype._encodeData = function(data){
if(!window.btoa) throw "btoa undefined";
var strDtata = "";
if(typeof(data) !="string"){
for(var i = 0 ; i < data.length;i++){
strDtata +=String.fromCharCode(data[i]);
}
}else{
strDtata = data;
}
return window.btoa(strDtata);
};
/**
* 根据配置生成固定大小图片
* @param width
* @param height
*/
Export2Image.prototype._scaleCanvas = function(width,height){
var w = this.canvas.width;
var h = this.canvas.height;
width = width || w;
height = height || h;
var newCanvas = document.createElement("canvas");
newCanvas.width = width;
newCanvas.height = height;
var ctx = newCanvas.getContext("2d");
ctx.drawImage(this.canvas,0,0,w,h,0,0,width,height);
this.canvas = newCanvas;
};
/**
* 获取canvas的Dataurl
*/
Export2Image.prototype._getDataURL = function(){
return this.canvas.toDataURL(this.type);
};
/**
* 获取导出图片类型
* @private
*/
Export2Image.prototype._fixType = function(){
var type = this.type.toLocaleLowerCase().replace(/jpg/i,"jpeg");
var res = type.match(/png|jpeg|bmp|gif/)[0];
this.type = "image/" + res;
};
/**
* 获取数据
*/
Export2Image.prototype.getData = function(){
if(this.actualWidth && this.actualHeight){
this._scaleCanvas(this.actualWidth,this.actualHeight);
}
var strData = "";
if (/bmp/.test(this.type)) {
var data = this._getImageData();
strData = this._getBitmapImage(data);
} else {
strData = this._getDataURL();
}
return strData;
}
/**
* 普通图片获取
* @private
*/
Export2Image.prototype._getImageData = function(){
var w = this.canvas.width, h = this.canvas.height;
return this.canvas.getContext('2d').getImageData(0, 0, w, h);
};
/**
* 位图获取
* @private
*/
Export2Image.prototype._getBitmapImage = function(oData){
var aHeader = [];
var iWidth = oData.width;
var iHeight = oData.height;
aHeader.push(0x42); // magic 1
aHeader.push(0x4D);
var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
aHeader.push(iFileSize % 256);
aHeader.push(0); // reserved
aHeader.push(0);
aHeader.push(0); // reserved
aHeader.push(0);
aHeader.push(54); // dataoffset
aHeader.push(0);
aHeader.push(0);
aHeader.push(0);
var aInfoHeader = [];
aInfoHeader.push(40); // info header size
aInfoHeader.push(0);
aInfoHeader.push(0);
aInfoHeader.push(0);
var iImageWidth = iWidth;
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
aInfoHeader.push(iImageWidth % 256);
var iImageHeight = iHeight;
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
aInfoHeader.push(iImageHeight % 256);
aInfoHeader.push(1); // num of planes
aInfoHeader.push(0);
aInfoHeader.push(24); // num of bits per pixel
aInfoHeader.push(0);
aInfoHeader.push(0); // compression = none
aInfoHeader.push(0);
aInfoHeader.push(0);
aInfoHeader.push(0);
var iDataSize = iWidth*iHeight*3;
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
aInfoHeader.push(iDataSize % 256);
for (var i=0;i<16;i++) {
aInfoHeader.push(0); // these bytes not used
}
var iPadding = (4 - ((iWidth * 3) % 4)) % 4;
var aImgData = oData.data;
var strPixelData = "";
var y = iHeight;
do {
var iOffsetY = iWidth*(y-1)*4;
var strPixelRow = "";
for (var x=0;x<iWidth;x++) {
var iOffsetX = 4*x;
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
}
for (var c=0;c<iPadding;c++) {
strPixelRow += String.fromCharCode(0);
}
strPixelData += strPixelRow;
} while (--y);
var strEncoded = this._encodeData(aHeader.concat(aInfoHeader)) + this._encodeData(strPixelData);
return this._makeDataURI(strEncoded);
};
Export2Image.prototype._makeDataURI = function(strData){
return "data:" + this.type + ";base64," + strData;
}
/**
* 保存
* @param data
* @param fileName
* @private
*/
Export2Image.prototype._saveFile = function(data,fileName){
try{
//TODO:IE浏览器
new ActiveXObject("Microsoft.XMLHTTP");
var oImg = document.createElement("img");
oImg.src = data;
oImg.onload = function(){
myWindow=window.open('','_blank','width=800,height=600');
myWindow.document.write("<img src='"+data+"'>")
myWindow.focus()
}
}catch(e){
var saveLink = document.createElementNS("http://www.w3.org/1999/xhtml","a");
saveLink.href = data;
saveLink.download = fileName;
var event = document.createEvent("MouseEvents");
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
saveLink.dispatchEvent(event);
}
};
Export2Image.prototype.exportPic = function(){
if(this.exportType == "html2Image"){
if(typeof(html2canvas) !="function"){
alert("需要引入html2canvas.js库文件");
return;
}
var that = this;
html2canvas(this.exportObj, {
onrendered: function(canvas) {
that.canvas = canvas;
var data = that.getData();
var imgData = data.replace(that.type,'image/octet-stream');
that._saveFile(imgData,that.fileName);
}
});
}else{
var data = this.getData();
var imgData = data.replace(this.type,'image/octet-stream');
this._saveFile(imgData,this.fileName);
}
};