话不多说,直接上代码,自己写的小插件 不需要html2canvas也可以转
//调用示例 支持两种方式
htmltocanvas.init({
//支持html2canvas的参数
background: '#fff',
showTag: !!1, //显示标记 在控制台输出一些调试信息
plus: !!1, //为false的时候使用html2canvas转 为true的时候使用原生转换
qrcode: !!1, //有二维码的时候传递true
canvasCallBack: function (src) { //转成功时的回调
},
},elm);
可能会有bug请自己完善
var htmltocanvas = (function () {
var extend = {
//默认输出标记
showTag: !1,
//默认使用兼容模式
plus: !!1,
};
return {
tool: {
createBase64Img: async function (scope) {
var that = this;
return new Promise(function (resolve,reject) {
var num = $('[data-img]',scope).length;
var flag = 0;
$('[data-img]',scope).each(function (i,e) {
var _src = $(e).attr('src');
if (_src.indexOf('data:image') === -1) {
var img = new Image();
img.src = _src + '?time=' + new Date().valueOf();
img.crossOrigin = 'Anonymous';
img.onload = async function () {
await that.imgSrcToBase64(img,$(e));
flag++;
htmltocanvas.tag('第' + i + '张图片的src已替换为base64','共有' + num + '张图片');
if (flag == num) resolve();
}
img.onerror = function () {
reject();
}
} else {
flag++;
if (flag == num) resolve();
}
});
});
},
imgSrcToBase64: async function (image,elm) {
var that = this;
return new Promise(function (resolve,reject) {
try {
htmltocanvas.tag('正在替换图片 ' + elm.attr('class'));
htmltocanvas.tag(image.src);
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
var dataURL = canvas.toDataURL();
elm.attr('src',dataURL);
resolve();
} catch (error) {
console.log(error);
}
});
},
getDPR: function (){
if (window.devicePixelRatio && window.devicePixelRatio > 1) {
return window.devicePixelRatio;
}
return 1;
},
isIos: function () {
return navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
},
plusCreateBase64Img: function (scope) {
var that = this;
var num = $('[data-img]',scope).length
,flag = 0
,deferred = $.Deferred();
$('[data-img]',scope).each(function (i,e) {
var _src = $(e).attr('src');
if (_src.indexOf('data:image') === -1) {
var img = new Image();
img.src = _src + '?time=' + new Date().valueOf();
img.crossOrigin = 'Anonymous';
img.onload = function () {
$.when(that.plusImgSrcToBase64(img,$(e))).done(function () {
htmltocanvas.tag('第' + i + '张图片的src已替换为base64','共有' + num + '张图片');
flag++;
if (flag == num) deferred.resolve();
});
}
img.onerror = function () {
deferred.reject();
}
} else {
flag++;
if (flag == num) deferred.resolve();
}
});
return deferred.promise();
},
plusImgSrcToBase64: function (image,elm) {
var that = this;
var deferred = $.Deferred();
try {
htmltocanvas.tag('正在替换图片 ' + elm.attr('class'));
htmltocanvas.tag(image.src);
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
var dataURL = canvas.toDataURL();
elm.attr('src',dataURL);
deferred.resolve();
} catch (error) {
deferred.reject();
console.log(error);
}
return deferred.promise();
},
},
init: function (option,scope) {
var that = this;
$.extend(extend,option);
if (extend.plus) {
that.plusRenderCanvas(scope);
} else {
that.renderCanvas(scope);
}
},
tag: function (msg) {
if (extend.showTag) {
console.log(msg || '');
}
},
renderCanvas: async function (scope) {
var that = this;
await that.tool.createBase64Img($(scope));
that.tag('图片src替换已完成,正在渲染html2canvas...');
var _h = $(scope).outerHeight(),
_w = $(scope).outerWidth();
var _canvas = document.createElement('canvas');
var dp = that.tool.getDPR();
_canvas.width = _w * dp;
_canvas.height = _h * dp;
_canvas.style.width = _w + 'px';
_canvas.style.height = _h + 'px';
//TODO 处理canvas转出来的图片不清晰
//TODO 感觉还是不清晰,对清晰度有要求的同学可以使用 plusRenderCanvas
var context = _canvas.getContext("2d");
context.scale(dp, dp);
var rect = scope.getBoundingClientRect(); //获取元素相对于视察的偏移量
context.translate(-rect.left, -rect.top);
extend.canvas = _canvas;
html2canvas(scope,extend).then(function (canvas) {
if (extend && extend.canvasCallBack && typeof extend.canvasCallBack === 'function') {
extend.canvasCallBack(canvas);
}
});
},
plusRenderCanvas: function (scope) {
var that = this;
$.when(that.tool.plusCreateBase64Img($(scope))).done(function () {
that.tag('图片src替换已完成,正在生成canvas...');
var _h = $(scope).outerHeight() + 20,
_w = $(scope).outerWidth();
//TODO 处理qrcode生成的二维码
if (extend.qrcode) {
//FIXME 在IOS上面有BUG,还没有处理
if (that.tool.isIos) {
//TODO
}
$('canvas+img',$(scope)).attr({'style': 'display:block;','data-img': ''});
}
//TODO 在xhtml里面<img />标签必须要闭合,不然会报语法错误,并且也转不了svg
//TODO 这里利用自定义属性[data-img]给<img>标签替换一个结束标记
var divContent = scope.outerHTML.replace(/data-img="">/g,'/>');
var data = "data:image/svg+xml," +
"<svg xmlns='http://www.w3.org/2000/svg' width='"+_w+"' height='"+_h+"'>" +
"<foreignObject width='100%' height='100%' style='background-color:rgb(255,255,255);'>" +
//TODO 这里必须要声明xmlns为:http://www.w3.org/1999/xhtml
"<div xmlns='http://www.w3.org/1999/xhtml'>" +
divContent +
"</div>" +
"</foreignObject>" +
"</svg>";
var img = new Image();
img.src = data;
//TODO 必须要等img渲染完成后再进行下一步的操作
img.onload = function () {
//2.svg转成canvas
var canvas = document.createElement('canvas'); //准备空画布
canvas.width = img.width;
canvas.height = img.height;
//取得画布的2d绘图上下文
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
//3. 图片导出为 png 格式
var type = 'png';
var imgData = canvas.toDataURL(type);
var _fixType = function (type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
};
// 加工image data,替换mime type
imgData = imgData.replace(_fixType(type), 'image/octet-stream');
if (extend && extend.canvasCallBack && typeof extend.canvasCallBack === 'function') {
that.tag('canvas创建成功');
extend.canvasCallBack(imgData);
}
}
});
}
}
})();