Html2canvas——圖片空白的幾種排查解決方案

来源:https://www.cnblogs.com/xikui/p/18085166
-Advertisement-
Play Games

問題:用html2canvas生成畫布圖片,再轉成pdf。生成圖片時內容結構里的圖片顯示空白。 解決: 首先伺服器設置圖片允許跨域,如阿裡雲騰訊雲配置跨域規則。其次圖片設置crossOrigin=“anonymous”,並且拿到圖片地址加隨機參數如 src +‘?v=’ + Math.random( ...


問題:用html2canvas生成畫布圖片,再轉成pdf。生成圖片時內容結構里的圖片顯示空白。
解決: 首先伺服器設置圖片允許跨域,如阿裡雲騰訊雲配置跨域規則。其次圖片設置crossOrigin=“anonymous”,並且拿到圖片地址加隨機參數如 src +‘?v=’ + Math.random()防止使用緩存,再者html2canvas設置屬性useCORS, allowTaint為true。

  下列文章來源該篇

 

一、工作原理

html2canvas庫的工作原理並不是真正的“截圖”,而是讀取網頁上的目標DOM節點的信息來繪製canvas,所以它並不支持所有的css屬性

二、在 img標簽中載入外部圖片

前提是外部圖片允許跨域,需要伺服器設置

以nginx為例,response-header內要存在Access-Control-Allow-Orgin:xxxx(可以是*,安全性要求比較高的可以根據主功能變數名稱自定義),如果該資源所在的web-server是不支持跨域的,保存圖片是不會成功的。

img標簽設置跨域

當html2canvas中生成的截圖中包含外部圖片,那麼外部圖片在引入的時候就需要設置允許跨域。

另外,通過 ‘img’ 載入的圖片,瀏覽器預設情況下會將其緩存起來,在canvas中用到圖片時,就會直接使用緩存圖片,不會再重新發請求。又因為瀏覽器本身不會有跨域問題,所以如果‘img’沒有設置 crossorigin 屬性,那麼就會出現跨域問題,圖片不能再次被覆用到 canvas 上去的。

1. 'img’標簽設置crossOrigin屬性
<img crossOrigin="anonymous" src={imgSrc} alt="img" />

這是最簡單的方法,讓圖片可以復用到canvas上。

2. chrome設置
<img src={imgSrc} alt="img" />

瀏覽器設置 disable cache,這種方法需要設置瀏覽器屬性,不推薦。

 

3. 使用JS載入圖片
const [imgBase, setImgBase] = useState("");
<img src={imgBase} alt="img" />
  const downloadIamge = imgsrc => {
    //下載圖片地址和圖片名
    let image = new Image();
    // 解決跨域 Canvas 污染問題
    image.setAttribute("crossOrigin", "anonymous");
    image.onload = function() {
      let canvas = document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
      let context = canvas.getContext("2d");
      context.drawImage(image, 0, 0, image.width, image.height);
      let url = canvas.toDataURL("image/png"); //得到圖片的base64編碼數據
      setImgBase(url);
    };
    image.src = imgsrc;
  };

 

這種方法能避免使用圖片緩存,在開發過程中,使用js方式請求圖片資源,最好每一次都加個隨機數,以保證源都是最新的,不走緩存。

三、在 html2canvas 中使用
 const createImg = async id => {
     const dom = document.getElementById(id);
     const config = {
          useCORS: true,
          width: dom.offsetWidth,
          height: dom.offsetHeight,
          scrollX: 0,
          scrollY: 0,
          x: 0,
          y: 0,
        };
const data = await html2canvas(dom, config).then(canvas =&gt; {
  canvas.id = "mycanvas";

  document.body.appendChild(canvas);
  const mycanvas = document.getElementById("mycanvas");
  mycanvas.style.display = "none";
  mycanvas.style.position = "fixed";
  mycanvas.style.top = "0px";
  mycanvas.style.left = "0px";
  mycanvas.style.zIndex = "9999";

  let imgData = mycanvas.toDataURL("png");
  imgData = imgData.replace(fixType("png"), "image/octet-stream");
  const file = dataURLtoFile(imgData, "poster.png");

  return file;
});

return data;
};

 

四、html2canvas設置

使用外部圖片就會面臨跨域的問題,html2canvas也需要設置屬性。

1. 允許畫布圖片跨域
confit = { useCORS: true }

 

2. 允許外部圖片污染畫布
confit = { allowTaint: true } 

 

使用上面兩種方法就可以讓外部圖片顯示在畫布上,雖然方法2可以讓外部圖片顯示在畫布上,但是卻不能調用 toBlob(), toDataURL() 或 getImageData() 方法,調用它們會拋出安全錯誤。

五、可能出現的問題
1. html2canvas生成的圖片無法顯示

可能是使用緩存圖片,有以下解決方法

  • 在 Chrome 的調試器中,在 network 面板中,勾選 disable cache 選項,再重新載入圖片
  • 圖片的訪問地址加個隨機數
  • 將圖片url轉成base64
2. html2canvas生成的圖片顯示空白

如果是出現了空白,那有可能是轉成圖片的部分出現滾動條且是在彈窗中展示,需要設置相關滾動高度。
或者有可能是dom不對,請保證dom是要截圖那個元素的父元素

 const dom = document.getElementById(id);
 const config = {
    useCORS: true,
    windowHeight:modal.scrollHeight + 24 + 100,//獲取y方向頁麵包含滾動條的高度,24和100為padding,margin
    width: dom.offsetWidth + 48,//48為padding值
    height: dom.clientHeight + 400,//可見高度+padding+margin
    y: window.pageYOffset + 100,//滾動條高度修複
    scrollX: 17
 };

 

3. ‘img’ 加上crossOrigin="anonymous"之後圖片無法顯示

這個有可能是瀏覽器緩存導致了,可以試試重新載入資源,也可以在資源的請求路徑後加上時間戳重新載入。

六、參考
  1. 中文文檔
  2. canvas.toDataURL()報錯的解決方案全都在這了
  3. 一個關於image訪問圖片跨域的問題
  4. canvas.toDataURL()報錯的解決方案全都在這了
  5. html2canvas生成圖片
  6. html2canvas截圖空白問題
  7. html2canvas生成pdf頁面空白
  8. 基於html2canvas實現網頁保存為圖片及圖片清晰度優化
   
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Android 逆向(四) - adb常用逆向命令 本篇文章繼續記錄下adb 的一些常用逆向命令. 1: adb shell ps 該命令可以查看進程信息. 用法: adb shell ps |grep [pname] zh@zh:~/workSpace$ adb shell ps USER PID ...
  • linux 入門(四) 1: 文件夾下所有文件的大小和詳細信息 du -h --max-depth=1 | sort -hr du命令可以查看文件夾(文件)占用的磁碟大小 ls命令可以查看文件的詳細信息,包括文件大小。 該命令可以按照文件夾(文件)大小的降序排列,並以易讀的方式顯示文件夾(文件)大小 ...
  • 一.引言 在當前的移動開發生態中,跨平臺框架如uni-app因其高效、靈活的特點受到了開發者們的青睞。同時,隨著物聯網技術的飛速發展,智能列印設備已成為許多業務場景中不可或缺的一環。今天,我們就來探討如何使用uni-app輕鬆對接馳騰品牌的智能印表機,實現無線列印功能。無論您是初學者還是有經驗的開發 ...
  • 我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 本文作者:霜序 本文首發於:https://juejin.cn/post/7299384698882539574 在大數據業務中,時常會出現且或關係邏輯的拼接,有需要做 ...
  • 專註探討UUID的核心原理及其生成機制,並詳細介紹不同版本UUID(如版本1的時間戳+節點ID、版本4的隨機數生成等)背後的數學原理和技術細節。 ...
  • 寫入剪切板 使用 clipboard.js 第三方插件: clipboard.js 安裝clipboard.js yarn yarn add clipboard npm npm install clipboard --save 使用示例(vue) <template> <div> <span v-c ...
  • 目錄一.HTML基本框架二.標題標簽三.段落標簽四.換行與水平線標簽五.文本格式化標簽(加粗、傾斜、下劃線、刪除線)六.圖像標簽擴展:相對路徑,絕對路徑與線上網址七.超鏈接標簽八.音頻標簽九.視頻標簽十.列表標簽十一.表格標簽擴展:表格結構標簽合併單元格十二.表單標簽1.input標簽input占位 ...
  • 一、UDP UDP(User Datagram Protocol),用戶數據包協議,是一個簡單的面向數據報的通信協議,即對應用層交下來的報文,不合併,不拆分,只是在其上面加上首部後就交給了下麵的網路層 也就是說無論應用層交給UDP多長的報文,它統統發送,一次發送一個報文 而對接收方,接到後直接去除首 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...