問題:用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 => { 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"之後圖片無法顯示
這個有可能是瀏覽器緩存導致了,可以試試重新載入資源,也可以在資源的請求路徑後加上時間戳重新載入。
六、參考
- 中文文檔
- canvas.toDataURL()報錯的解決方案全都在這了
- 一個關於image訪問圖片跨域的問題
- canvas.toDataURL()報錯的解決方案全都在這了
- html2canvas生成圖片
- html2canvas截圖空白問題
- html2canvas生成pdf頁面空白
- 基於html2canvas實現網頁保存為圖片及圖片清晰度優化