因为工作需要,近期一直在做关于数据的报告,pc端窗口的,东西不是很难但是久下载功能上遇到了很多坑。
html2canvas
1.html2canvas能够实现在用户浏览器端直接对整个或部分页面进行截屏。
2.这个html2canvas脚本将当页面渲染成一个Canvas图片,通过读取DOM并将不同的样式应用到这些元素上实现。
3.它不需要来自服务器任何渲染,整张图片都是在客户端浏览器创建。
4.当浏览器不支持Canvas时,将采用Flashcanvas或ExplorerCanvas技术代替实现。
5.以下浏览器能够很好的支持该脚本:Firefox 3.5+, Google Chrome, Opera新的版本, IE9以上的浏览器。
用法
html2canvas(element, options)
html2canvas(document.body, {
onrendered: function(canvas) {
var url = canvas.toDataURL();//图片地址
document.body.appendChild(canvas);
},
width: 300,
height: 300
})
兼容性
1.首先,图片上模糊,特别是文件机器打的时候,需要把图片转成base64格式的,
2.html2canvas虽然可以控制图片的质量有点好处(在同一个js长页面中可以控制质量来缓解浏览器的压力),
但是对Firefox于火狐浏览器,会有报错,下载失败err,所以本小白又找到了替代他的domtoimage,这个下文会仔细介绍的。
3.html2canvas性能损耗很厉害,很容易造成浏览器的崩溃,所以又想下载出品质高清的图片着实有点难。
常用代码
方法一
var canvas = document.getElementById('pieChart')
function base64Img2Blob(code){
var parts = code.split(';base64,')
var contentType = parts[0].split(':')[1]
var raw = window.atob(parts[1])
var rawLength = raw.length
var uInt8Array = new Uint8Array(rawLength)
for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i)
}
return new Blob([uInt8Array], {type: contentType})
}
function downloadFile(){
var aLink = document.createElement('a')
var blob = base64Img2Blob(canvas.toDataURL("image/png")) //new Blob([content])
var evt = document.createEvent("HTMLEvents")
evt.initEvent("click", false, false);//initEvent 不加后两个参数在FF下会报错
aLink.download = new Date().getTime() + ".png"
aLink.href = URL.createObjectURL(blob)
aLink.dispatchEvent(evt)
}
方法二
window.onload = function() {
var canvas = document.getElementById("pieChart")
var context = canvas.getContext("2d")
// no argument defaults to image/png; image/jpeg, etc also work on some
// implementations -- image/png is the only one that must be supported per spec.
window.location = canvas.toDataURL("image/png")
}
方法三
var canvas = document.getElementById("pieChart");
var ctx = canvas.getContext('2d');
var btn = document.getElementById('btn1');
btn.onclick() = function() {
var type = 'png';
download(type);
}
function download(type) {
var imgdate = 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;
}
imgdata = imgdata.replace(fixtype(type), 'image/octet-stream')
var saveFile = function (data, filename) {
var link = document.createElement('a');
link.href = data;
link.download = filename;
var event = document.createElement('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
}
var filename = new Date().toLocaleDateString() + '.' + type;
saveFile(imgdate, filename);
}
文字生成
// 默认a4大小,竖直方向,mm单位的PDF
var doc = new jsPDF();
// 添加文本‘Download PDF’
doc.text('Download PDF!', 10, 10);
doc.save('a4.pdf');
图片生成PDF
// 三个参数,第一个方向,第二个单位,第三个尺寸格式
var doc = new jsPDF('landscape','pt',[205, 115])
// 将图片转化为dataUrl
var imageData = ‘data:image/png;base64,iVBORw0KGgo...’;
doc.addImage(imageData, 'PNG', 0, 0, 205, 115);
doc.save('a4.pdf');
文字与图片生成PDF
// 三个参数,第一个方向,第二个尺寸,第三个尺寸格式
var doc = new jsPDF('landscape','pt',[205, 155])
// 将图片转化为dataUrl
var imageData = ‘data:image/png;base64,iVBORw0KGgo...’;
//设置字体大小
doc.setFontSize(20);
//10,20这两参数控制文字距离左边,与上边的距离
doc.text('Stone', 10, 20);
// 0, 40, 控制文字距离左边,与上边的距离
doc.addImage(imageData, 'PNG', 0, 40, 205, 115);
doc.save('a4.pdf')
html2canvas + jsPDF
单页
var downPdf = document.getElementById("renderPdf");
downPdf.onclick = function() {
html2canvas(document.body, {
onrendered:function(canvas) {
//小编个人认为,不用单独的去声名createElement一下canvans
,分页的时候一定要搭配async\await更佳
//返回图片dataURL,参数:图片格式和清晰度(0-1)
var pageData = canvas.toDataURL('image/jpeg', 1.0);
//方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
var pdf = new jsPDF('', 'pt', 'a4'); // 不传默认是a4格式
//addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
pdf.addImage(pageData, 'JPEG', 0, 0, 595.28, 592.28/canvas.width * canvas.height );
pdf.save('stone.pdf');
}
}
}
多页
var downPdf = document.getElementById("renderPdf");
downPdf.onclick = function() {
async function getPdf() {
for (var i = 0, i < downPdf.length; i += 1; ) {
await html2canvas(document.body, {
onrendered:function(canvas) {
//返回图片dataURL,参数:图片格式和清晰度(0-1)
这里我没有写opts,有很多参数,scale等有需要得可以设置
var pageData = canvas.toDataURL('image/jpeg', 1.0);
//方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
var pdf = new jsPDF('', 'pt', 'a4'); // 不传默认是a4格式
//addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
pdf.addImage(pageData, 'JPEG', 0, 0, 595.28, 592.28/canvas.width * canvas.height );
pdf.save('stone.pdf');
}
}
}
}
getPdf(downPdf)
}
})
}
domtoimage
html2canvas转换的base64位图不能被火狐/ios8以上版本所识别。会呈现出整个截图页面空白
问题分析:
这个问题的起因,应该是html2canvas对高版本的ios不支持(自我感觉),这个问题我很是头疼,当时根本没有对ios进行测
试。思来想去感觉html2canvas坑太多了。填都填不完。于是...
解决办法:
我采用了另一款插件,dom-to-image,弄上去没有问题了。
dom-to-image运用上去,在ios上能够出现内容了,但发现存在一个问题,部分图片内容,第一次进行公众号网页加载,没有
正确显示,要在次进入才会显示,此bug同样是ios8以上版本
问题分析:
这一个问题我没有找到问题所在,一脸懵,不过最终还是得到了解决。
解决办法:
运用dom-to-imagede toSvg方式完美解决问题。
domtoimage.toPng(pdfWrapper).then(function (dataUrl: any) {
const pageData = dataUrl
const tpye = 'image/png'
const baseStr = pageData.substr(pageData.indexOf('base64,') + 7, pageData.length)
const blob = b64toBlob(baseStr, tpye, 512)
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, `${'xxxx'}${'.png'}`)
} else {
const a = document.createElement('a')
a.download = `${'XXXX'}${'.png'}`
a.href = URL.createObjectURL(blob)
document.body.appendChild(a)
a.click()
a.remove()
}
unLoadBtn.style.display = 'block'
loadBtn.style.display = 'none'
document.getElementById('Anchor')!.style.display = 'block'
}).catch((err: any) => {
self.toggleTabelFix(true)
message.error('下载报告失败')
unLoadBtn.style.display = 'block'
loadBtn.style.display = 'none'
document.getElementById('Anchor')!.style.display = 'block'
console.log('下载报告失败', err)
})
总结
不同的浏览器之间兼容性是不同的,这个还学要具体问题具体分析,本小白只是根绝我所需要的进行了查阅分享给大家,
更多的还是要各位大佬去挖掘。