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,
