用html2canvas轉html為圖片遇到的那些問題


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上

   $('.top-img').attr('src',URL.createObjectURL(imgfile))
4.進行繪制canvas,此時canvas不會在報錯 能夠完整繪制整個html
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,

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM