html2canvas.js 圖片跨域 生成圖片模糊 圖片偏移 高清圖的問題總結

首先 本人是一個canvas小白 基本不懂canvas的原理,拿到同事寫的代碼直接copy過來也沒看文檔(項目催的緊且文檔是英文的) 話很少說 上代碼 只是說出個人解決思路不少爲何還要花時間研究 好比canvas我都不會css

<script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
複製代碼
html2canvas(document.querySelector(".upload_box")).then((canvas) => {
    
        var imgData = canvas.toDataURL('image/png');
      
        $('#save_img').html($('<div id="downLoadImg"><img src="' + imgData + '" alt=""></div>'));

    })
複製代碼

如此簡單是否是!獲取dom 把返回的canvas轉成圖片顯示! 遇到兩個問題:html

  • 部分圖片沒有生成
  • 生成的圖片特別模糊(文字和圖片都是模糊的)手機上更糊

但是爲啥同事的代碼沒有問題呢!我拉來了同事 發現了一個問題:dom涉及到的圖片不是本地的話 生成不出來 當時試了好多方法 都不行(這個時候傻逼的我爲啥不去看看文檔!)總之在網上試了好久 最終的作法是把從服務器獲取的圖片都轉成base64顯示 (網上找的代碼) 暫時解決了

getBase64: function getBase64(img) {//傳入圖片路徑,返回base64
                function getBase64Image(img, width, height) {
                    var canvas = document.createElement("canvas");
                    canvas.width = width ? width : img.width;
                    canvas.height = height ? height : img.height;
                    var ctx = canvas.getContext("2d");
                    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
                    var dataURL = canvas.toDataURL();
                    return dataURL;
                }

                var image = new Image();
                image.src = img;
                image.crossOrigin = "Anonymous"
                var deferred = jQuery.Deferred();
                if (img) {
                    image.onload = function () {
                        deferred.resolve(getBase64Image(image));//將base64傳給done上傳處理
                    }
                    return deferred.promise();//問題要讓onload完成後再return sessionStorage['imgTest']
                }
            },
            
複製代碼
_this.getBase64(resp.avatar)
    .then(function(base64){
    // console.log(base64);
        $('.user_info .user_head img').attr('src',base64)
    },function(err){
        console.log(err);
    });
複製代碼

模糊我都不想處理了 !可是產品說不行啊,你這個生成的圖片二維碼都識別不出來 必需要清晰 就在我加班到早上六點也解決不了的時候 產品說能夠先隱藏這個功能,花時間研究一下。 因而次日 我就開始準備找方法了。

首先把官方文檔看了一遍:html2canvas.hertzen.com/configurati… 雖然是英文 但其實沒多少東西 主要就是參數配置 一句句谷歌也能翻譯出來(不要被英文嚇到)程序員

看到了一個配置:useCORS false Whether to attempt to load images from a server using CORS 不就是容許跨域獲取圖片嗎,爲何以前試了這句好像沒有效果呢?canvas

var opts = {
                                useCORS: true
                            };
                            
複製代碼
html2canvas(document.querySelector(".upload_box"),opts).then((canvas) => {
    
        var imgData = canvas.toDataURL('image/png');
      
        $('#save_img').html($('<div id="downLoadImg"><img src="' + imgData + '" alt=""></div>'));

    })
複製代碼

醬紫 遠程的圖片頁也能夠了 不會出現空白頁!真是開心,比轉成程base64方便多了 畢竟好幾張圖片都要轉很麻煩(後面還有一個轉化的大坑我這裏沒遇到,也是雷 後面會說) 並且轉化以後的圖片會更加不清晰!開心!後端

而後我就開始個人漫長的 研究怎麼生成清晰圖的探索之路了!(找到同事的代碼,他啥都沒有配置啊! 而後我發現html2canvas默認生成的canvas的寬高就是你dom結構的寬高 同事的代碼截圖的是整個網頁 很大 生成的圖片也就挺清晰的 ,可是個人截圖模塊只佔網頁不到1/2 過小了! 感受就是這個緣由,我開始想要說複製一個dom吧尺寸放大 可是以爲太low了 因而仍是想嘗試一下別的!跨域

固然能百度到不少promise

  • 最多的就是修改源碼 技術很渣的我直接放棄了 不會改不敢改
  • 而後修改配置項啊 反正按照他們的說的方法
var width = $('.upload_box').width()
    var height = $('.upload_box').height()
    var canvasBox = document.createElement("canvas"); 
    var scale = window.devicePixelRatio; 
    canvasBox.width = width * scale; 
    canvasBox.height = height * scale; 

    canvasBox.style.width = width + "px";
    canvasBox.style.height = height + "px";
    canvasBox.getContext("2d").scale(scale, scale); 
   // 獲取元素相對於視窗的偏移量
   var opts = {
        scale: scale, 
        useCORS: true,
    };
複製代碼

差很少都是這樣的寫法 可是可是出來canvas是清晰了!可是不居中啊 嘗試在配置項中增長參數 x y偏移 可是並無什麼用 而後我就想 程序員怎麼能用百度 !遂換谷歌 終於在 知乎裏面看到一個好像比較看不懂的寫法 因而就試試: www.zhihu.com/question/48…

做者:PajamaCat
連接:https://www.zhihu.com/question/48217555/answer/283209866
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

前面的回答沒有解決margin致使的生成圖片偏移問題, 這裏是解決方法:      var dom = $('#to-save-img')
      var width = dom.width();
      var height = dom.height();
      var type = "png";
      var scaleBy = 2; //縮放比例
      var canvas = document.createElement("canvas");
      // 獲取元素相對於視窗的偏移量
      var rect = dom.get(0).getBoundingClientRect(); 
      canvas.width = width * scaleBy;
      canvas.height = height * scaleBy; 
      canvas.style.width = width * scaleBy + "px";
      canvas.style.height = height * scaleBy + "px";
      var context = canvas.getContext("2d");
      context.scale(scaleBy, scaleBy);
      // 設置context位置, 值爲相對於視窗的偏移量的負值, 實現圖片復位
      context.translate(-rect.left,-rect.top);
複製代碼

就是這個所謂的偏移,我一看我要截圖 dom的確是margin:0 auto的 是相對居中的 因此試試安全

var width = $('.upload_box').width()
                var height = $('.upload_box').height()
                var canvasBox = document.createElement("canvas"); 
                var scale = window.devicePixelRatio; 
                var rect = $('.upload_box').get(0).getBoundingClientRect(); 
                canvasBox.width = width * scale; 
                canvasBox.height = height * scale; 

                canvasBox.style.width = width + "px";
                canvasBox.style.height = height + "px";
                canvasBox.getContext("2d").scale(scale, scale); 
                canvasBox.getContext("2d").translate(-rect.left, -rect.top); 
                           // 獲取元素相對於視窗的偏移量
                           var opts = {
                                scale: scale, 
                                canvas: canvasBox, 
                                // logging: true, 
                                // width: width*2, 
                                // height: height*2 ,
                                // allowTaint:true,
                                useCORS: true,
                                // x:-200,
                            };
複製代碼

而後真的就行了!!!!!!! 激動啊激動啊簡直大神啊!bash

而後我就很開心了 開心的發給測試 而後撲街 測試的手機上仍是徹底白板 啊?難道是兼容性的問題?但是咱們都是iphone7啊 ! 並且兼容性什麼的最討厭了! 我快絕望了 而後在個人手機上登錄她的帳號 也是截圖不了的 這太奇怪了 !難道是帳號的問題? 畢竟一成天都在解決所謂的跨域問題!圖片跨域啥的不少啊! 服務器

而後果真 她的帳號的微信頭像 : wx.qlogo.cn/mmopen/vi_3…

對這裏就是我以前說到的轉base64的坑 微信的頭像不容許跨域,因此html2canvas沒法直接使用微信的頭像生成canvas,因此啊 我就想本地base64就行了 就一個頭像,可是

查了一下是:污染的畫布沒法輸出,發現原來是受限於 CORS 策略,會存在跨域問題,雖然可使用圖像(好比append到頁面上)可是繪製到畫布上會污染畫布,一旦一個畫布被污染,就沒法提取畫布的數據,好比沒法使用使用畫布toBlob(),toDataURL(),或getImageData()方法;當使用這些方法的時候 會拋出一個安全錯誤

因此 我就妥妥的把問題丟給後端 讓他們把微信頭像轉成base64給我了! 徹底搞定了!撒花

寫下這個記錄帖 雖然問題暫時解決了 可是還有更多的不懂在等着我去看

相關文章
相關標籤/搜索