玩轉html2canvas以及常見問題解決

freephp發表於2021-06-30

前端小夥伴經常會遇到頁面截圖或者把網頁中指定的區域(某個大div)的內容轉換成png的圖片。這個時候常常會用到html2canvas庫來實現,js真的很強大。

我最近也遇到了一個需求,需要把輸入的文字框裡面的文字轉換成帶有字型樣式的圖片。於是去研究了一下html2canvas。

html2canvas官網是:http://html2canvas.hertzen.com/,當前最新版本是1.0.0-rc.7。
安裝方式有三種,第1種是用npm進行安裝:

npm install --save html2canvas

第二種是用yarn,命令如下:

yarn add html2canvas

第三種是直接下載html2canvas.js或者壓縮版本html2canvas.min.js。然後直接script方式引入到需要使用這個js庫的html檔案中即可。

官網給的案例如下(usage), 首先是html部分,有一個div:

<div id="capture" style="padding: 10px; background: #f5da55">
    <h4 style="color: #000; ">Hello world!</h4>
</div>

js部分如下:

html2canvas(document.querySelector("#capture")).then(canvas => {
    document.body.appendChild(canvas)
});

這段程式碼就是把id為capture的div傳給html2canvas,回撥中的canvas是被捕獲的div物件。
如果要把這個div轉換成圖片,則還需要增加如下程式碼:

html2canvas(document.querySelector("#capture")).then(canvas => {
    document.body.appendChild(canvas);
    // 新增程式碼 返回圖片的URL,設定為png格式
    var dataUrl = canvas.toDataURL("image/png")
});

上面程式碼中的dataUrl是一個base64編碼的圖片URL地址。
在我的需求中,我需要把這個圖片資源儲存到伺服器中,所以需要在後面發起一個ajax請求(或者post請求)到後端服務,後端介面需要接收這個dataURL,先base64解碼,然後再把解碼後的圖片內容寫入到png格式的檔案中。
大致程式碼如下:

public function saveCustomTextToImage(Request $request) {
        $imageDataURL = $request->input('dataUrl');
        $encodeImage = explode(",", $imageDataURL)[1];
        // 解碼
        $decodeImage = base64_decode($encodeImage);
        $storePath = "./img/my-pic.png";
        // 寫入檔案
        file_put_contents($storePath, $decodeImage);
        $resArray['success'] = true;
        $resArray['url'] = "testme";
        return response()->json($resArray);
    }

如果是不想傳給後端處理,想直接跳轉瀏覽器下載,那麼之前的js部分的程式碼可以改為:

html2canvas(document.querySelector("#capture")).then(canvas => {
    document.body.appendChild(canvas);
    // 新增程式碼 返回圖片的URL,設定為png格式
    var dataUrl = canvas.toDataURL("image/png");
    var downloadUrl = dataUrl.replace("image/png","image/octet-stream");//圖片地址
    
    window.location.href = downloadUrl; // 跳轉下載
});

常規玩法說完了,下面說一下常見的坑。
第一個我遇到的就是版本造成的api呼叫的問題,從上面的js程式碼可以看出最新的html2canvas是基於Promise實現的,所以可以用".then"的方式進行鏈式呼叫。而老版本的html2canvas只能用傳統回撥方式來寫,我的同事就是用的0.4.1版本,所以他的寫法和我不一樣,如下所示:

html2canvas([document.getElementById('mydiv')], {
    onrendered: function(canvas) {
       document.body.appendChild(canvas);
       var data = canvas.toDataURL('image/png');
       // AJAX call to send `data` to server
    }
});

第二個遇到的問題是沒有任何報錯的前提下,生成的圖片是空白的。國內的童鞋們對這個問題往往說是去設定初始化選項,就可以解決帶有滾動條的頁面擷取出空白的問題。眾所紛紜,還有人說要給被選中的div設定寬高才行。
然而我採用這種方法沒有解決問題,Google了很久發現國外的開發真正解決了這個問題。其實還是和版本有關,將最新的版本降會1.0.0rc.0版本就可以了。
希望官方早點解決這個問題,不然強制降版本也不是個事兒啊。

相關文章