問題:用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實現網頁儲存為圖片及圖片清晰度最佳化