1.图片跨域问题
在html转化为canvas在转化成图片地址的 时候 canvas.toDataURL("image/png")
遇到报错:
Access to image at \'png\' from origin \'null\' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
或者
Access to image at \'www.baidu.com/GT/github/hotelAdmin/img/tempalte-top.png\' from origin \'null\' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
报错原因 就是 图片 跨域 污染了画布,导致画布不能导出img的地址
在网上找方法
设置:
useCORS: true, //(图片跨域相关) allowTaint: false, //允许跨域(图片跨域相关
$(\'#div\').click(function () { html2canvas(template, { onrendered: function (canvas) { exportCanvasAsPNG(canvas, \'invoice.png\') }, useCORS: true, //(图片跨域相关) allowTaint: false, //允许跨域(图片跨域相关) x: 0, y: window.pageYOffset, windowWidth: document.body.scrollWidth, windowHeight: document.body.scrolHeight, }); })
但是并没有效果
追其根本 是图片跨域的问题
跨域怎么解决
1.设置请求头 Access-Control-Allow-Origin: *;
这个需要 图片服务器 那边去设置,这个无法验证是否好用,因为我们服务端说 弄不了这个 所以 pass
2.既然跨域,那我统一域名就可以了 ,再激进一点把文件直接写进代码里
将图片源码转成blob文件对象,然后用URL.createObjectURL()方法转换成img src可用的地址,然后再绘制在canvas上,在和html一起导出toDataURL,转成图片
怎么做
1.获取图片源码
我这里两张图片是静态图片,不涉及动态,所以 我直接在线转了base64码 在线转base64
2.将跨域的图片转成blob文件对象
//将base64转换为文件对象 function dataURLtoFile(dataurl, filename) { var arr = dataurl.split(\',\'); var mime = arr[0].match(/:(.*?);/)[1]; var bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } //转换成file对象 // return new File([u8arr], filename, { type: mime }); //转换成成blob对象 return new Blob([u8arr], { type: mime }); }
3.将blob图片对象通过URL.createObjectURL(‘图片blob对象’)转化成图片地址,赋值在img的src上
html2canvas(template, { onrendered: function (canvas) { var imgURL = canvas.toDataURL( "image/png"); 这个时候就可以正常执行toDataURL方法了 // 导出图片 exportCanvasAsPNG(canvas, \'invoice.png\') }, useCORS: true, //(图片跨域相关) allowTaint: false, //允许跨域(图片跨域相关) x: 0, y: window.pageYOffset, windowWidth: document.body.scrollWidth, windowHeight: document.body.scrolHeight, });
2.绘制出来是空白区域(不可见内容不可绘制)
有很多时候,我们所要绘制的内容是不能展示出来的,需求是需要直接导出,不需要让用户看到绘制的画布以及内容
这时候 一般做的处理 将所需要描述的内容区隐藏起来,但是一旦隐藏以后,就会发现,绘制出来时是一片空白,这是由于不可见内容不可绘制
什么情况下,是不能绘制的不可见内容:
1.display:none
2.opacity:0
但是由于需要隐藏 该怎么弄呢 解决方案 :
1.将需要绘制的div fixed定位,注意要定位在 top:0, left:0,保证内容区能在可是区域内容,
2.然后利用z-index来隐藏,这样需要上层有一个遮罩层,需要带背景的层来遮罩住下面的内容
3.超过屏幕的内容绘制出来的部分为空白
解决:设置windowHeight的高度等于页面包含滚动条的高度,这样滚动中的内容也会被截取出来
html2canvas(template, { onrendered: function (canvas) { exportCanvasAsPNG(canvas, \'invoice.png\') }, useCORS: true, //(图片跨域相关) allowTaint: false, //允许跨域(图片跨域相关) x: 0,//页面在横向方向上的滚动距离 横向上没有超过 所以设置为0 y: window.pageYOffset,//页面在垂直方向上的滚动距离 设置了以后 超过一屏幕的内容也可以截取 windowWidth: document.body.scrollWidth,//获取在x轴上滚动条中内容 windowHeight: document.body.scrolHeight,//获取在y轴上滚动条中内容 });
不设置设置width、height,就是默认template (被截取的dom元素)$(dom) 的宽高
4.背景图片虚化,模糊
当要截图的dom中,有元素有背景图,截取完以后 就会发现 背景图比较模糊,和正常img标签的图片清晰度要差很多
解决办法:将背景图,换成img标签,定位显示出来
5.文字阴影 text-shadow没有正常显示的问题
解决方案:https://blog.csdn.net/SDUST_JSJ/article/details/78122610
这篇文章还讲述了 文字描边,下划线的问题,在这里就不进行试验和重复讲述了,直接附上地址,方便以后查找
6.html2canvas截图时,背景音乐在IOS11下会重复播放
解决方法见博文:https://blog.csdn.net/lerayZhang/article/details/79207468
7.关于使用svg解决一下样式上不兼容的问题 利用box-shadow不支持的问题
这里有个博客有写到,因为我没有这个需求 所以 只是找了解决方案,并没有实际性操作:https://www.cnblogs.com/aigeileshei/p/9111925.html 中下篇的位置
8.清晰度问题
一般情况下,清晰度不够的情况下,一般采用绘制2倍图,就是绘制的内容 放大两倍,移动端一般转换的时候需要
设置屏幕像素比()
var c_width = $(\'.box\').outerWidth();//如果box设置了padding,需要获取outerWidth和outerHeight来赋给canvas; var c_height =$(\'.box\').outerHeight(); var canvas = document.createElement("canvas"); var context = canvas.getContext("2d"); //以下代码是获取根据屏幕分辨率,来设置canvas的宽高以获得高清图片 // 屏幕的设备像素比 var devicePixelRatio = window.devicePixelRatio || 2; // 浏览器在渲染canvas之前存储画布信息的像素比 var backingStoreRatio = context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1; // canvas的实际渲染倍率 var ratio = devicePixelRatio/backingStoreRatio; canvas.width = c_width * ratio; canvas.height = c_height * ratio; canvas.style.width = c_width + "px"; canvas.style.height = c_height + "px"; var transTop = $(document).scrollTop() - $(\'.card_box\').offset().top;//获取div垂直方向的位置 context.scale(ratio,ratio); context.translate((c_width-$(window).width())/2,transTop) //canvas的位置要保证与div位置相同。 //高清图设置完成 //解决跨域,将跨域图片路径转为base64格式 var img = new Image(); var canvas2 = document.createElement(\'canvas\'); var ctx = canvas2.getContext(\'2d\'); img.crossOrigin = \'Anonymous\'; img.src=$(\'#ossImg\').attr(\'src); img.onload = function () { canvas2.height = img.height; canvas2.width = img.width; ctx.drawImage(img, 0, 0); var dataURL = canvas2.toDataURL(\'image/png\'); $(\'#ossImg\').attr(\'src\',dataURL); canvas2 = null; //重新给img赋值成功后,执行截图方法 getCard() } function getCard(){ html2canvas($(".box"),{ allowTaint:true, useCORS:true, canvas:canvas, onrendered:function(canvas){ dataURL =canvas.toDataURL("image/png"); var img = new Image(); img.src=dataURL; img.className = \'cardImg\'; img.onload = function () { $(".card").append(img); } }, width:c_width, height:c_height }) }
关于清晰度 这里是深入讲解方法:https://www.cnblogs.com/GoTing/p/12850029.html
额外补充:
base64码限制
在微信中或者可以说在移动端浏览器里,canvas.toDataURL不成功。canvas.toDataURL() 得到空的 data:base64码的长度有个限制,可以换清晰度,图片大小小一点的图片转换
微信里的长按存图功能
先用html2canvas拿到一个html转为canvas的base64码,
再在页面建立一个img元素,src=图片base64码,opacity设置为0,设置z-index最大,确保用户长按到图片
这样长按保存的图片就是覆盖在上面的那个图片
9.图片出现白边
一般出现这个问题是 1.0版本出现的,1.0绘制出来的图片会清晰很多,应该是绘制了二倍图,在进行缩放,所以导致了白边的出现。
解决:
1.添加属性
backgroundColor: null,
使用这个可以使绘制出来的图片白边的地方,变成透明,实际还是有因为缩放导致的位移偏移,但是图片看不出来
2.微调
对宽高,位移进行像素移动
height: template.offsetHeight-1, width: template.offsetWidth-1,